Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration list page and integration config #2684

Merged
merged 16 commits into from
Nov 13, 2024
Merged
Binary file added frontend/public/images/integrations/devto.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/integrations/github.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/integrations/slack.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<div class="flex items-center gap-4">
<!-- <lf-button type="secondary-ghost" @click="isDetailsModalOpen = true">-->
<!-- <lf-icon name="circle-info" type="regular" />-->
<!-- Details-->
<!-- </lf-button>-->
<lf-button type="secondary" @click="isConfluenceSettingsDrawerVisible = true">
<lf-icon name="link-simple" />
Connect
</lf-button>
</div>
<lf-confluence-settings-drawer
v-if="isConfluenceSettingsDrawerVisible"
v-model="isConfluenceSettingsDrawerVisible"
:integration="props.integration"
/>
</template>

<script setup>
import { defineProps, ref } from 'vue';
import LfIcon from '@/ui-kit/icon/Icon.vue';
import LfButton from '@/ui-kit/button/Button.vue';
import LfConfluenceSettingsDrawer from '@/config/integrations/confluence/components/confluence-settings-drawer.vue';

const props = defineProps({
integration: {
type: Object,
default: () => {},
},
});

const isConfluenceSettingsDrawerVisible = ref(false);
</script>

<script>
export default {
name: 'LfConfluenceConnect',
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<template>
<lf-dropdown-item @click="isConfluenceSettingsDrawerVisible = true">
<lf-icon name="sliders-simple" type="regular" />
Settings
</lf-dropdown-item>
<lf-confluence-settings-drawer
v-if="isConfluenceSettingsDrawerVisible"
v-model="isConfluenceSettingsDrawerVisible"
:integration="props.integration"
/>
</template>

<script setup>
import { defineProps, ref } from 'vue';
import LfDropdownItem from '@/ui-kit/dropdown/DropdownItem.vue';
import LfIcon from '@/ui-kit/icon/Icon.vue';
import LfConfluenceSettingsDrawer from '@/config/integrations/confluence/components/confluence-settings-drawer.vue';

const props = defineProps({
integration: {
type: Object,
default: () => {},
},
});

const isConfluenceSettingsDrawerVisible = ref(false);
// const isDetailsModalOpen = ref(false);
</script>

<script>
export default {
name: 'AppGitConnect',
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="flex items-center gap-1">
<el-popover trigger="hover" placement="top" popper-class="!w-72">
<template #reference>
<div class="flex flex-row gap-1">
<div class="flex items-center gap-1">
<div
class="text-gray-600 text-2xs flex items-center leading-5 font-medium"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,23 @@
placeholder="Enter Organization URL"
/>
<el-input
v-if="form.space"
id="spaceId"
v-model="form.space.id"
class="text-green-500 mt-2"
spellcheck="false"
placeholder="Enter Space ID"
/>
<el-input
v-if="form.space"
id="spaceKey"
v-model="form.space.key"
class="text-green-500 mt-2"
spellcheck="false"
placeholder="Enter Space Key"
/>
<el-input
v-if="form.space"
id="spaceName"
v-model="form.space.name"
class="text-green-500 mt-2"
Expand All @@ -66,7 +69,7 @@
:loading="loading"
@click="connect"
>
{{ integration.settings ? 'Update' : 'Connect' }}
{{ integration?.settings ? 'Update' : 'Connect' }}
</el-button>
</div>
</template>
Expand Down Expand Up @@ -124,9 +127,9 @@ const isVisible = computed({
const logoUrl = computed(() => CrowdIntegrations.getConfig('confluence').image);

onMounted(() => {
if (props.integration.settings) {
form.url = props.integration.settings.url;
form.space = props.integration.settings.space;
if (props.integration?.settings) {
form.url = props.integration?.settings.url;
form.space = props.integration?.settings.space;
}
formSnapshot();
});
Expand Down Expand Up @@ -166,6 +169,6 @@ const connect = async () => {

<script>
export default {
name: 'AppConfluenceConnectDrawer',
name: 'LfConfluenceSettingsDrawer',
};
</script>
16 changes: 16 additions & 0 deletions frontend/src/config/integrations/confluence/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IntegrationConfig } from '@/config/integrations';
import ConfluenceConnect from './components/confluence-connect.vue';
import ConfluenceParams from './components/confluence-params.vue';
import ConfluenceDropdown from './components/confluence-dropdown.vue';

const confluence: IntegrationConfig = {
key: 'confluence',
name: 'Confluence',
image: '/images/integrations/confluence.svg',
description: 'Connect Confluence to sync documentation activities from your repos.',
connectComponent: ConfluenceConnect,
connectedParamsComponent: ConfluenceParams,
dropdownComponent: ConfluenceDropdown,
};

export default confluence;
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,12 @@ const connectDisabled = computed(() => {

const empty = validUsers.length + validOrgs.length === 0;

if (props.integration.settings && !empty) {
if (props.integration?.settings && !empty) {
return (
validUsers.length === props.integration.settings.users.length
&& validUsers.every((u) => props.integration.settings.users.includes(u.username))
&& validOrgs.length === props.integration.settings.organizations.length
&& validOrgs.every((o) => props.integration.settings.organizations.includes(o.username))
validUsers.length === props.integration?.settings.users.length
&& validUsers.every((u) => props.integration?.settings.users.includes(u.username))
&& validOrgs.length === props.integration?.settings.organizations.length
&& validOrgs.every((o) => props.integration?.settings.organizations.includes(o.username))
);
}

Expand Down Expand Up @@ -298,9 +298,9 @@ const syncData = () => {
$v.value.$reset();
$v.value.$clearExternalResults();

if (props.integration && props.integration.settings) {
props.integration.settings.users.forEach((u) => addNewUser(u));
props.integration.settings.organizations.forEach((o) => addNewOrganization(o));
if (props.integration && props.integration?.settings) {
props.integration?.settings.users.forEach((u) => addNewUser(u));
props.integration?.settings.organizations.forEach((o) => addNewOrganization(o));
}

if (users.value.length === 0) {
Expand Down Expand Up @@ -426,7 +426,7 @@ const save = async () => {
apiKey: form.apiKey,
});

const isUpdate = !!props.integration.settings;
const isUpdate = !!props.integration?.settings;

trackEvent({
key: isUpdate ? FeatureEventKey.EDIT_INTEGRATION_SETTINGS : FeatureEventKey.CONNECT_INTEGRATION,
Expand Down Expand Up @@ -497,7 +497,7 @@ onMounted(syncData);

<script>
export default {
name: 'AppDevtoConnectDrawer',
name: 'LfDevtoConnectDrawer',
};
</script>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<div class="flex items-center gap-4">
<!-- <lf-button type="secondary-ghost" @click="isDetailsModalOpen = true">-->
<!-- <lf-icon name="circle-info" type="regular" />-->
<!-- Details-->
<!-- </lf-button>-->
<lf-button type="secondary" @click="isDevtoConnectDrawerVisible = true">
<lf-icon name="link-simple" />
Connect
</lf-button>
</div>
<lf-devto-connect-drawer
v-if="isDevtoConnectDrawerVisible"
v-model="isDevtoConnectDrawerVisible"
:integration="props.integration"
/>
</template>

<script setup>
import { defineProps, ref } from 'vue';
import LfIcon from '@/ui-kit/icon/Icon.vue';
import LfButton from '@/ui-kit/button/Button.vue';
import LfDevtoConnectDrawer from '@/config/integrations/devto/components/devto-connect-drawer.vue';

const props = defineProps({
integration: {
type: Object,
default: () => {},
},
});

const isDevtoConnectDrawerVisible = ref(false);
</script>

<script>
export default {
name: 'AppDevtoConnect',
};
</script>
14 changes: 14 additions & 0 deletions frontend/src/config/integrations/devto/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { IntegrationConfig } from '@/config/integrations';
import DevtoConnect from './components/devto-connect.vue';
import DevtoParams from './components/devto-params.vue';

const devto: IntegrationConfig = {
key: 'devto',
name: 'DEV',
image: '/images/integrations/devto.png',
description: 'Connect DEV to sync profile information and comments on articles.',
connectComponent: DevtoConnect,
connectedParamsComponent: DevtoParams,
};

export default devto;
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<template>
<div class="flex items-center gap-4">
<!-- <lf-button type="secondary-ghost" @click="isDetailsModalOpen = true">-->
<!-- <lf-icon name="circle-info" type="regular" />-->
<!-- Details-->
<!-- </lf-button>-->
<lf-button type="secondary" @click="connect()">
<lf-icon name="link-simple" />
Connect
</lf-button>
</div>
</template>

<script setup>
import { computed, onMounted } from 'vue';
import config from '@/config';
import LfIcon from '@/ui-kit/icon/Icon.vue';
import LfButton from '@/ui-kit/button/Button.vue';
import { EventType, FeatureEventKey } from '@/shared/modules/monitoring/types/event';
import { Platform } from '@/shared/modules/platform/types/Platform';
import { mapActions } from '@/shared/vuex/vuex.helpers';
import { useRoute } from 'vue-router';

const route = useRoute();

const { doDiscordConnect } = mapActions('integration');

const connectUrl = computed(() => config.discordInstallationUrl);

const connect = () => {
window.open(connectUrl.value, '_self');
};

const finallizeDiscordConnect = () => {
const {
source, code,
} = route.query;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think route is defined anywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is you can catch route.query from anywhere and get the params

const guildId = route.query.guild_id;

if (code && source === 'discord' && guildId) {
doDiscordConnect({
guildId,
})
.then(() => {
trackEvent({
key: FeatureEventKey.CONNECT_INTEGRATION,
type: EventType.FEATURE,
properties: { platform: Platform.DISCORD },
});
});
}
};

onMounted(() => {
finallizeDiscordConnect();
});
</script>

<script>
export default {
name: 'LfDiscordConnect',
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ const channels = computed<{ id: string; name: string }[]>(

<script lang="ts">
export default {
name: 'AppGithubSettings',
name: 'LfDiscordParams',
};
</script>
14 changes: 14 additions & 0 deletions frontend/src/config/integrations/discord/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { IntegrationConfig } from '@/config/integrations';
import DiscordConnect from './components/discord-connect.vue';
import DiscordParams from './components/discord-params.vue';

const discord: IntegrationConfig = {
key: 'discord',
name: 'Discord',
image: '/images/integrations/discord.png',
description: 'Connect Discord to sync messages, threads, forum channels, and new joiners.',
connectComponent: DiscordConnect,
connectedParamsComponent: DiscordParams,
};

export default discord;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<div class="flex items-center gap-4">
<!-- <lf-button type="secondary-ghost" @click="isDetailsModalOpen = true">-->
<!-- <lf-icon name="circle-info" type="regular" />-->
<!-- Details-->
<!-- </lf-button>-->
<lf-button type="secondary" @click="isDiscourseConnectDrawerOpen = true">
<lf-icon name="link-simple" />
Connect
</lf-button>
</div>
<lf-discourse-settings-drawer
v-if="isDiscourseConnectDrawerOpen"
v-model="isDiscourseConnectDrawerOpen"
:integration="props.integration"
/>
</template>

<script setup>
import { defineProps, ref } from 'vue';
import LfDiscourseSettingsDrawer from '@/config/integrations/discourse/components/discourse-settings-drawer.vue';
import LfIcon from '@/ui-kit/icon/Icon.vue';
import LfButton from '@/ui-kit/button/Button.vue';

const props = defineProps({
integration: {
type: Object,
default: () => {},
},
});

const isDiscourseConnectDrawerOpen = ref(false);
</script>

<script>
export default {
name: 'AppDiscourseConnect',
};
</script>
Loading
Loading