Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions frontend/src/assets/images/identities/bluesky.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions frontend/src/assets/images/identities/instagram.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions frontend/src/assets/images/identities/tiktok.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions frontend/src/assets/images/identities/youtube.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions frontend/src/config/identities/bluesky/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { IdentityConfig } from '@/config/identities';

const image = new URL('@/assets/images/identities/bluesky.svg', import.meta.url).href;

const bluesky: IdentityConfig = {
key: 'bluesky',
name: 'Bluesky',
image,
member: {
urlPrefix: 'bsky.app/profile/',
url: ({ identity }) =>
identity.value ? `https://bsky.app/profile/${identity.value.replace(/^@/, '')}` : null,
},
activity: {
showLink: true,
},
};

export default bluesky;
5 changes: 1 addition & 4 deletions frontend/src/config/identities/facebook/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import type { IdentityConfig } from '@/config/identities';

const image = new URL(
'@/assets/images/identities/facebook.png',
import.meta.url,
).href;
const image = new URL('@/assets/images/identities/facebook.png', import.meta.url).href;

const facebook: IdentityConfig = {
key: 'facebook',
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/config/identities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
ContributorIdentity,
} from '@/modules/contributor/types/Contributor';
import type { OrganizationIdentity } from '@/modules/organization/types/Organization';
import bluesky from './bluesky/config';
import confluence from './confluence/config';
import crunchbase from './crunchbase/config';
import cvent from './cvent/config';
Expand All @@ -16,6 +17,7 @@ import github from './github/config';
import gitlab from './gitlab/config';
import groupsio from './groupsio/config';
import hackernews from './hackernews/config';
import instagram from './instagram/config';
import jira from './jira/config';
import lfid from './lfx/config';
import linkedin from './linkedin/config';
Expand All @@ -24,8 +26,10 @@ import n8n from './n8n/config';
import reddit from './reddit/config';
import slack from './slack/config';
import stackoverflow from './stackoverflow/config';
import tiktok from './tiktok/config';
import tnc from './tnc/config';
import twitter from './twitter/config';
import youtube from './youtube/config';
import zapier from './zapier/config';

export interface IdentityConfig {
Expand Down Expand Up @@ -86,4 +90,8 @@ export const lfIdentities: Record<string, IdentityConfig> = {
n8n,
training_cert: tnc,
zapier,
youtube,
bluesky,
tiktok,
instagram,
Comment thread
themarolt marked this conversation as resolved.
};
19 changes: 19 additions & 0 deletions frontend/src/config/identities/instagram/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { IdentityConfig } from '@/config/identities';

const image = new URL('@/assets/images/identities/instagram.svg', import.meta.url).href;

const instagram: IdentityConfig = {
key: 'instagram',
name: 'Instagram',
image,
member: {
urlPrefix: 'instagram.com/',
url: ({ identity }) =>
identity.value ? `https://www.instagram.com/${identity.value.replace(/^@/, '')}` : null,
},
activity: {
showLink: true,
},
};

export default instagram;
19 changes: 19 additions & 0 deletions frontend/src/config/identities/tiktok/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { IdentityConfig } from '@/config/identities';

const image = new URL('@/assets/images/identities/tiktok.svg', import.meta.url).href;

const tiktok: IdentityConfig = {
key: 'tiktok',
name: 'TikTok',
image,
member: {
urlPrefix: 'tiktok.com/@',
url: ({ identity }) =>
identity.value ? `https://www.tiktok.com/@${identity.value.replace(/^@/, '')}` : null,
},
activity: {
showLink: true,
},
};

export default tiktok;
19 changes: 19 additions & 0 deletions frontend/src/config/identities/youtube/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { IdentityConfig } from '@/config/identities';

const image = new URL('@/assets/images/identities/youtube.svg', import.meta.url).href;

const youtube: IdentityConfig = {
key: 'youtube',
name: 'YouTube',
image,
member: {
urlPrefix: 'youtube.com/channel/',
url: ({ identity }) =>
identity.value ? `https://www.youtube.com/channel/${identity.value}` : null,
},
activity: {
showLink: true,
},
};

export default youtube;
22 changes: 14 additions & 8 deletions frontend/src/config/integrations/integrations.helpers.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { mapGetters } from '@/shared/vuex/vuex.helpers';
import { useStore } from 'vuex';
import type { IntegrationConfig } from '@/config/integrations/index';
import { lfIntegrations } from '@/config/integrations/index';
import type { Integration } from '@/modules/admin/modules/integration/types/Integration';

type StoredIntegration = Pick<Integration<unknown>, 'status'> & { platform: string };

const useIntegrationsHelpers = () => {
const getActiveIntegrations = () => {
const { findByPlatform }: any = mapGetters('integrations');
const store = useStore();

const getActiveIntegrations = (): IntegrationConfig[] => {
const integrations: StoredIntegration[] = store.getters['integration/array'] ?? [];
Comment thread
themarolt marked this conversation as resolved.

return Object.values(lfIntegrations()).map((config) => ({
...config,
...(findByPlatform ? findByPlatform(config.key) : {}),
}))
.filter((integration) => integration.status);
return Object.values(lfIntegrations()).filter((config) =>
integrations.some(
(integration) => integration.platform === config.key && !!integration.status,
),
);
};

return {
Expand Down
16 changes: 15 additions & 1 deletion frontend/src/config/integrations/octolens/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@ import type { IntegrationConfig } from '@/config/integrations';

const image = new URL('@/assets/images/integrations/octolens.png', import.meta.url).href;

// Must match ENABLED_PLATFORMS in services/libs/connectors/src/connectors/octolens/mapper.ts.
export const octolensMentionPlatforms: readonly string[] = [
'github',
'twitter',
'linkedin',
'reddit',
'devto',
'hackernews',
'bluesky',
'tiktok',
'instagram',
'youtube',
];

const octolens: IntegrationConfig = {
key: 'octolens',
name: 'Octolens',
image,
description:
'Mentions of LF projects on GitHub, X/Twitter, LinkedIn and more, matched to projects automatically.',
'Mentions of LF projects on GitHub, X/Twitter, LinkedIn, Reddit, Bluesky and more, matched to projects automatically.',
showProgress: false,
autoManaged: true,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<script setup lang="ts">
import {
computed, onMounted, watch,
computed, watch,
} from 'vue';
import { storeToRefs } from 'pinia';
import { useStore } from 'vuex';
Expand All @@ -23,6 +23,7 @@ import { useActivityTypeStore } from '@/modules/activity/store/type';
import { useLfSegmentsStore } from '@/modules/lf/segments/store';
import { lfIdentities } from '@/config/identities';
import useIntegrationsHelpers from '@/config/integrations/integrations.helpers';
import octolens, { octolensMentionPlatforms } from '@/config/integrations/octolens/config';

interface FilterData { options?: MultiSelectFilterOptionGroup[] }

Expand Down Expand Up @@ -65,13 +66,30 @@ const toOptionGroup = (platform: string, activityTypes: Record<string, ActivityT
})),
});

const platformOptionGroup = (
platform: string,
activityTypes: Record<string, ActivityTypeDefinition>,
activeIntegrationsValue: string[],
): MultiSelectFilterOptionGroup | null => {
if (activeIntegrationsValue.includes(platform)) {
return toOptionGroup(platform, activityTypes);
}
if (
activeIntegrationsValue.includes(octolens.key)
&& octolensMentionPlatforms.includes(platform)
&& activityTypes.mention
) {
return toOptionGroup(platform, { mention: activityTypes.mention });
}
return null;
};

watch([types, activeIntegrations], ([typesValue, activeIntegrationsValue]) => {
const platformsOptions = Object.entries(typesValue.default)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.filter(([platform, _]) => activeIntegrationsValue.includes(platform))
.map(([platform, activityTypes]) => toOptionGroup(platform, activityTypes));
const platformsOptions = Object.entries(typesValue.default ?? {})
.map(([platform, activityTypes]) => platformOptionGroup(platform, activityTypes, activeIntegrationsValue))
.filter((group): group is MultiSelectFilterOptionGroup => group !== null);

const customOptions = Object.entries(typesValue.custom)
const customOptions = Object.entries(typesValue.custom ?? {})
.map(([platform, activityTypes]) => toOptionGroup(platform, activityTypes));

data.value.options = [
Expand All @@ -80,9 +98,10 @@ watch([types, activeIntegrations], ([typesValue, activeIntegrationsValue]) => {
];
}, {
deep: true,
immediate: true,
Comment thread
themarolt marked this conversation as resolved.
});

onMounted(async () => {
await store.dispatch('integration/doFetch', selectedProjectGroup.value?.id ? [selectedProjectGroup.value.id] : []);
});
watch(() => selectedProjectGroup.value?.id, async (projectGroupId) => {
await store.dispatch('integration/doFetch', projectGroupId ? [projectGroupId] : []);
}, { immediate: true });
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { computed, ref, watch } from 'vue';
import type {
MultiSelectFilterOptions,
MultiSelectFilterConfig, MultiSelectFilterOptionGroup,
Expand All @@ -58,17 +58,17 @@ const form = computed<string[]>({
});

const filteredOptions = ref<MultiSelectFilterOptionGroup[]>(props.options);
const searchQuery = ref('');

const searchOptions = (query: string) => {
searchQuery.value = query;
filteredOptions.value = props.options.map((g) => ({
...g,
options: g.options.filter((o) => o.label.toLowerCase().includes(query.toLowerCase())),
}));
};

onMounted(() => {
searchOptions('');
});
watch(() => props.options, () => searchOptions(searchQuery.value), { immediate: true, deep: true });
</script>

<script lang="ts">
Expand Down
Loading
Loading