Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,19 @@
<lf-table class="!overflow-visible">
<thead>
<tr>
<lf-table-head class="pl-5">
Project
</lf-table-head>
<lf-table-head class="pl-5"> Project </lf-table-head>
<lf-table-head>
Affiliation
<el-popover placement="top" width="20rem">
<template #reference>
<lf-icon-old name="question-line" :size="14" class="text-secondary-200 font-normal" />
</template>
<div class="p-1">
<p class="text-small font-semibold mb-2 text-black">
Affiliation
</p>
<p class="text-small font-semibold mb-2 text-black">Affiliation</p>
<p class="text-small text-gray-500 break-normal text-left">
Organization(s) that an individual represents while contributing to a project.
This association indicates that the person's activities were made in the context
of their role within the organization, rather than as an independent contributor.
Organization(s) that an individual represents while contributing to a project. This association
indicates that the person's activities were made in the context of their role within the
organization, rather than as an independent contributor.
</p>
</div>
</el-popover>
Expand All @@ -35,32 +31,26 @@
<lf-icon-old name="question-line" :size="14" class="text-secondary-200 font-normal" />
</template>
<div class="p-1">
<p class="text-small font-semibold mb-2 text-black">
Maintainer
</p>
<p class="text-small font-semibold mb-2 text-black">Maintainer</p>
<p class="text-small text-gray-500 break-normal mb-5 text-left">
Individual responsible for overseeing and managing code repositories by
reviewing and merging pull requests, addressing issues, ensuring code quality, and guiding contributors.
</p>
<p class="text-small font-semibold mb-2 text-black">
Contributor
Individual responsible for overseeing and managing code repositories by reviewing and merging pull
requests, addressing issues, ensuring code quality, and guiding contributors.
</p>
<p class="text-small font-semibold mb-2 text-black">Contributor</p>
<p class="text-small text-gray-500 break-normal text-left">
Someone who has contributed to a project by making changes or additions to its code.
Contributions require that code was successfully merged into a repository.
Someone who has contributed to a project by making changes or additions to its code. Contributions
require that code was successfully merged into a repository.
</p>
</div>
</el-popover>
</lf-table-head>
<lf-table-head> Activities </lf-table-head>
<lf-table-head />
</tr>
</thead>

<tbody>
<tr
v-for="project in (projects || []).slice(0, showMore ? (projects || []).length : 3)"
:key="project.id"
>
<tr v-for="project in (projects || []).slice(0, showMore ? (projects || []).length : 3)" :key="project.id">
<lf-table-cell class="pl-5">
<p class="text-medium font-semibold py-1.5">
{{ project.name }}
Expand All @@ -71,14 +61,22 @@
<lf-contributor-details-projects-affiliation :project="project" />
</div>
<div v-else-if="hasPermission(LfPermission.memberEdit)">
<lf-button type="primary-link" size="small" class="!text-primary-300 hover:!text-primary-600" @click="isAffilationEditOpen = true">
<lf-button
type="primary-link"
size="small"
class="!text-primary-300 hover:!text-primary-600"
@click="isAffilationEditOpen = true"
>
<lf-icon-old name="add-line" />Add affiliation
</lf-button>
</div>
</lf-table-cell>
<lf-table-cell>
<lf-contributor-details-projects-maintainer :maintainer-roles="getMaintainerRoles(project)" />
</lf-table-cell>
<lf-table-cell>
<p class="text-small text-gray-500 whitespace-nowrap">{{ project.activityCount }}</p>
</lf-table-cell>
<lf-table-cell>
<lf-dropdown placement="bottom-end" width="160px">
<template #trigger>
Expand All @@ -93,11 +91,13 @@
<lf-icon-old name="pencil-line" />Edit affiliation
</lf-dropdown-item>
<lf-dropdown-item
@click="setReportDataModal({
contributor: props.contributor,
type: ReportDataType.PROJECT_AFFILIATION,
attribute: project,
})"
@click="
setReportDataModal({
contributor: props.contributor,
type: ReportDataType.PROJECT_AFFILIATION,
attribute: project,
})
"
>
<lf-icon-old name="feedback-line" class="!text-red-500" />Report issue
</lf-dropdown-item>
Expand Down Expand Up @@ -127,24 +127,21 @@ import LfIconOld from '@/ui-kit/icon/IconOld.vue';
import { computed, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Contributor, ContributorAffiliation } from '@/modules/contributor/types/Contributor';
import LfContributorEditAffilations
from '@/modules/contributor/components/edit/affilations/contributor-affilations-edit.vue';
import LfContributorEditAffilations from '@/modules/contributor/components/edit/affilations/contributor-affilations-edit.vue';
import LfTable from '@/ui-kit/table/Table.vue';
import LfDropdown from '@/ui-kit/dropdown/Dropdown.vue';
import LfTableCell from '@/ui-kit/table/TableCell.vue';
import LfTableHead from '@/ui-kit/table/TableHead.vue';
import LfDropdownItem from '@/ui-kit/dropdown/DropdownItem.vue';
import LfContributorDetailsProjectsAffiliation
from '@/modules/contributor/components/details/overview/project/contributor-details-projects-affiliation.vue';
import LfContributorDetailsProjectsMaintainer
from '@/modules/contributor/components/details/overview/project/contributor-details-projects-maintainer.vue';
import LfContributorDetailsProjectsAffiliation from '@/modules/contributor/components/details/overview/project/contributor-details-projects-affiliation.vue';
import LfContributorDetailsProjectsMaintainer from '@/modules/contributor/components/details/overview/project/contributor-details-projects-maintainer.vue';
import usePermissions from '@/shared/modules/permissions/helpers/usePermissions';
import { LfPermission } from '@/shared/modules/permissions/types/Permissions';
import { ReportDataType } from '@/shared/modules/report-issue/constants/report-data-type.enum';
import { useSharedStore } from '@/shared/pinia/shared.store';

const props = defineProps<{
contributor: Contributor,
contributor: Contributor;
}>();

const router = useRouter();
Expand All @@ -156,26 +153,31 @@ const { setReportDataModal } = useSharedStore();
const showMore = ref<boolean>(false);
const isAffilationEditOpen = ref<boolean>(false);

const getAffiliations = (projectId: string) => (props.contributor.affiliations || []).filter((affiliation) => affiliation.segmentId === projectId)
.reduce((obj: Record<string, ContributorAffiliation[]>, aff: ContributorAffiliation) => {
if (!obj[aff.organizationId]) {
const getAffiliations = (projectId: string) =>
(props.contributor.affiliations || [])
.filter((affiliation) => affiliation.segmentId === projectId)
.reduce((obj: Record<string, ContributorAffiliation[]>, aff: ContributorAffiliation) => {
if (!obj[aff.organizationId]) {
return {
...obj,
[aff.organizationId]: [aff],
};
}
return {
...obj,
[aff.organizationId]: [aff],
[aff.organizationId]: [...obj[aff.organizationId], aff],
};
}
return {
...obj,
[aff.organizationId]: [...obj[aff.organizationId], aff],
};
}, {});
}, {});

const projects = computed(() => props.contributor.segments.map((p) => ({
...p,
affiliations: getAffiliations(p.id),
})));
const projects = computed(() =>
props.contributor.segments.map((p) => ({
...p,
affiliations: getAffiliations(p.id),
}))
);

const getMaintainerRoles = (project: any) => props.contributor.maintainerRoles.filter((role) => role.segmentId === project.id);
const getMaintainerRoles = (project: any) =>
props.contributor.maintainerRoles.filter((role) => role.segmentId === project.id);

const viewActivity = (projectId: string) => {
router.replace({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
:search-config="memberSearchFilter"
:saved-views-config="memberSavedViews"
:custom-config="customAttributesFilter"
:exclude-filters="excludeFilters"
hash="people"
@fetch="onFilterChange($event)"
/>
Expand All @@ -20,9 +21,7 @@
<template #trigger>
<div class="flex items-center gap-1 py-2">
<p class="text-small">
<span class="font-semibold">
Sort:
</span>
<span class="font-semibold"> Sort: </span>
{{ sorters[sort] }}
</p>
<lf-icon-old name="arrow-down-s-line" :size="16" />
Expand All @@ -37,12 +36,7 @@
@click="onSortChange(key)"
>
<span>{{ label }}</span>
<lf-icon-old
v-if="sort === key"
name="check-line"
:size="16"
class="text-primary-500"
/>
<lf-icon-old v-if="sort === key" name="check-line" :size="16" class="text-primary-500" />
</lf-dropdown-item>
</lf-dropdown>
</div>
Expand Down Expand Up @@ -71,11 +65,7 @@
class="border-2 rounded-full p-0.5"
:class="isNew(contributor) ? 'border-primary-500' : 'border-transparent'"
>
<lf-avatar
:src="avatar(contributor)"
:name="contributor.displayName"
:size="32"
/>
<lf-avatar :src="avatar(contributor)" :name="contributor.displayName" :size="32" />
</div>
<p class="text-medium font-semibold text-black group-hover:text-primary-500 transition">
{{ contributor.displayName }}
Expand Down Expand Up @@ -117,11 +107,7 @@
</div>
</template>
</app-identities-horizontal-list-members>
<lf-tooltip
v-else
placement="top-end"
content="This person's data is not shown because of the GDPR."
>
<lf-tooltip v-else placement="top-end" content="This person's data is not shown because of the GDPR.">
<div class="h-6 w-21 rounded-md bg-gray-200" />
</lf-tooltip>
</div>
Expand All @@ -131,26 +117,17 @@
<div class="flex justify-center pb-8">
<lf-icon-old name="group-2-line" :size="80" class="text-gray-200" />
</div>
<h5 class="text-center text-h5">
No people found
</h5>
<h5 class="text-center text-h5">No people found</h5>
<p class="text-gray-600 text-small text-center mt-4">
We couldn't find any results that match your search criteria, please try a different query
</p>
</div>
<div
v-if="pagination.total > (pagination.page * pagination.perPage)"
v-if="pagination.total > pagination.page * pagination.perPage"
class="pt-10 pb-6 gap-4 flex justify-center items-center"
>
<p class="text-small text-gray-400">
{{ contributors.length }} of {{ totalContacts }} people
</p>
<lf-button
type="primary-ghost"
loading-text="Loading people..."
:loading="loading"
@click="loadMore"
>
<p class="text-small text-gray-400">{{ contributors.length }} of {{ totalContacts }} people</p>
<lf-button type="primary-ghost" loading-text="Loading people..." :loading="loading" @click="loadMore">
Load more
</lf-button>
</div>
Expand All @@ -176,16 +153,15 @@ import LfDropdown from '@/ui-kit/dropdown/Dropdown.vue';
import LfDropdownItem from '@/ui-kit/dropdown/DropdownItem.vue';
import { useLfSegmentsStore } from '@/modules/lf/segments/store';
import LfButton from '@/ui-kit/button/Button.vue';
import AppIdentitiesHorizontalListMembers
from '@/shared/modules/identities/components/identities-horizontal-list-members.vue';
import AppIdentitiesHorizontalListMembers from '@/shared/modules/identities/components/identities-horizontal-list-members.vue';
import pluralize from 'pluralize';
import LfTooltip from '@/ui-kit/tooltip/Tooltip.vue';
import LfSpinner from '@/ui-kit/spinner/Spinner.vue';
import LfContributorEngagementLevel from '@/modules/contributor/components/shared/contributor-engagement-level.vue';
import useContributorHelpers from '@/modules/contributor/helpers/contributor.helpers';

const props = defineProps<{
organization: Organization,
organization: Organization;
}>();

const filterConfig = { ...memberFilters };
Expand All @@ -202,11 +178,12 @@ const totalContacts = ref<number>(0);
const loading = ref<boolean>(false);

const savedBody = ref<any>({});
const searchStr = ref<string>('');

const {
avatar, isNew, identities, isMasked,
} = useContributorHelpers();
const { avatar, isNew, identities, isMasked } = useContributorHelpers();

// TODO: need to revisit this. Understand why the filter.vue is parsing the segmentId for this component as a filter in that component
const excludeFilters = ['segmentId'];
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Address TODO comment with proper documentation

The TODO comment indicates uncertainty about the segmentId parsing. This should be properly documented or resolved rather than leaving it as a TODO.

Please either:

  1. Document why segmentId needs to be excluded and remove the TODO
  2. Implement a proper fix if this is a workaround

const sorters = {
score_DESC: 'Most engaged',
activityCount_DESC: 'Most activities',
Expand Down Expand Up @@ -245,22 +222,19 @@ const doGetMembersCount = () => {
filter: orgFilter,
segments: selectedProjectGroup.value?.id ? [selectedProjectGroup.value?.id] : props.organization.segments,
},
true,
)
.then(({ count }) => {
totalContacts.value = count;
});
true
).then(({ count }) => {
totalContacts.value = count;
});
};

const fetch = () => {
loading.value = true;
MemberService.listMembers({
filter: {
and: [
orgFilter,
savedBody.value,
],
and: [orgFilter, savedBody.value],
},
search: searchStr.value,
Comment on lines 237 to +240
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling in fetch function

The fetch function resets data on error but doesn't provide user feedback about the failure.

Consider adding error handling:

 filter: {
   and: [orgFilter, savedBody.value],
 },
 search: searchStr.value,
+}).catch((error) => {
+  contributors.value = [];
+  pagination.value.total = 0;
+  // Add error notification
+  console.error('Failed to fetch contributors:', error);
+  // If you have a notification system
+  // notify.error('Failed to load contributors. Please try again.');

Committable suggestion skipped: line range outside the PR's diff.

offset: (pagination.value.page - 1) * pagination.value.perPage,
limit: pagination.value.perPage,
orderBy: sort.value,
Expand All @@ -284,15 +258,16 @@ const fetch = () => {
};

const loadMore = () => {
if (pagination.value.total <= (pagination.value.page * pagination.value.perPage)) {
if (pagination.value.total <= pagination.value.page * pagination.value.perPage) {
return;
}
pagination.value.page += 1;
fetch();
};

const onFilterChange = (filterQuery: FilterQuery) => {
savedBody.value = filterQuery.filter;
savedBody.value = filterQuery.body;
searchStr.value = filterQuery.search;
pagination.value.page = 1;
pagination.value.total = 0;
fetch();
Expand Down
Loading
Loading