-
Notifications
You must be signed in to change notification settings - Fork 727
Feature/lfx 1843 work history #2716
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
Changes from 3 commits
00a6f77
de0cfd5
cfb3f4e
7ee5163
430b2f2
a64d8d6
2933154
19d8b53
baaf71e
926d475
0ed5573
6564a79
00c85d3
572c259
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,14 +31,16 @@ | |
| </div> | ||
|
|
||
| <div v-if="!masked" class="flex flex-col gap-4"> | ||
| <lf-contributor-details-work-history-item | ||
| v-for="org of (orgs || []).slice(0, showMore ? (orgs || []).length : 3)" | ||
| :key="org.id" | ||
| :contributor="props.contributor" | ||
| :organization="org" | ||
| @edit="isEditModalOpen = true; editOrganization = org" | ||
| /> | ||
| <div v-if="orgs.length === 0" class="pt-2 flex flex-col items-center"> | ||
| <lf-timeline v-slot="{ group }" :groups="shownGroups"> | ||
| <lf-timeline-item v-for="item in group.items" :key="item.id" data="Item 1"> | ||
| <lf-contributor-details-work-history-item | ||
| :contributor="props.contributor" | ||
| :organization="item" | ||
| @edit="isEditModalOpen = true; editOrganization = item" | ||
| /> | ||
| </lf-timeline-item> | ||
| </lf-timeline> | ||
| <div v-if="orgGrouped.length === 0" class="pt-2 flex flex-col items-center"> | ||
| <lf-icon-old name="survey-line" :size="40" class="text-gray-300" /> | ||
| <p class="text-center pt-3 text-medium text-gray-400"> | ||
| No work experiences | ||
|
|
@@ -55,7 +57,7 @@ | |
| </div> | ||
|
|
||
| <lf-button | ||
| v-if="!masked && orgs.length > 3" | ||
| v-if="!masked && orgGrouped.length > minimumShownGroups" | ||
| type="primary-link" | ||
| size="medium" | ||
| class="mt-6" | ||
joanagmaia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
@@ -88,19 +90,52 @@ import LfContributorDetailsWorkHistoryItem | |
| from '@/modules/contributor/components/details/work-history/contributor-details-work-history-item.vue'; | ||
| import useContributorHelpers from '@/modules/contributor/helpers/contributor.helpers'; | ||
| import LfIcon from '@/ui-kit/icon/Icon.vue'; | ||
| import { TimelineGroup } from '@/ui-kit/timeline/types/TimelineTypes'; | ||
| import { groupBy } from 'lodash'; | ||
| import { storeToRefs } from 'pinia'; | ||
| import { useLfSegmentsStore } from '@/modules/lf/segments/store'; | ||
| import LfTimeline from '@/ui-kit/timeline/Timeline.vue'; | ||
| import LfTimelineItem from '@/ui-kit/timeline/TimelineItem.vue'; | ||
|
|
||
| const props = defineProps<{ | ||
| contributor: Contributor, | ||
| }>(); | ||
|
|
||
| const { hasPermission } = usePermissions(); | ||
| const { isMasked } = useContributorHelpers(); | ||
| const { selectedProjectGroup } = storeToRefs(useLfSegmentsStore()); | ||
|
|
||
| const showMore = ref<boolean>(false); | ||
| const isEditModalOpen = ref<boolean>(false); | ||
| const editOrganization = ref<Organization | null>(null); | ||
|
|
||
| const orgs = computed(() => props.contributor.organizations); | ||
| // const orgs = computed(() => props.contributor.organizations); | ||
| const orgGrouped = computed(() => { | ||
| const grouped = groupBy(props.contributor.organizations, 'id'); | ||
| return Object.keys(grouped).map((id): TimelineGroup => ({ | ||
| label: grouped[id][0].displayName, | ||
| labelLink: { | ||
| name: 'organizationView', | ||
| params: { | ||
| id, | ||
| }, | ||
| query: { | ||
| projectGroup: selectedProjectGroup.value?.id, | ||
| }, | ||
| }, | ||
| icon: grouped[id][0].logo, | ||
| items: grouped[id], | ||
| })); | ||
| }); | ||
| const minimumShownGroups = computed(() => { | ||
| const MIN_ITEMS = 3; | ||
|
||
| const groupMinIdx = props.contributor.organizations.length >= MIN_ITEMS ? MIN_ITEMS - 1 : 0; | ||
|
|
||
| return orgGrouped.value.length > 0 | ||
| ? orgGrouped.value.findIndex((group) => props.contributor.organizations[groupMinIdx].id === group.items[0].id) + 1 | ||
| : MIN_ITEMS; | ||
| }); | ||
| const shownGroups = computed(() => orgGrouped.value.slice(0, showMore.value ? orgGrouped.value.length : minimumShownGroups.value)); | ||
|
|
||
| const masked = computed(() => isMasked(props.contributor)); | ||
| </script> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,36 +4,7 @@ | |
| @mouseleave="hovered = false" | ||
| > | ||
| <div class="flex"> | ||
| <lf-avatar | ||
| :name="props.organization.displayName" | ||
| :src="props.organization.logo" | ||
| :size="24" | ||
| class="!rounded-md border border-gray-200 min-w-6" | ||
| img-class="!object-contain" | ||
| > | ||
| <template #placeholder> | ||
| <div class="w-full h-full bg-gray-50 flex items-center justify-center"> | ||
| <lf-icon-old name="community-line" :size="16" class="text-gray-400" /> | ||
| </div> | ||
| </template> | ||
| </lf-avatar> | ||
|
|
||
| <div class="pl-3 flex flex-auto flex-col overflow-hidden"> | ||
| <router-link | ||
| :to="{ | ||
| name: 'organizationView', | ||
| params: { | ||
| id: props.organization.id, | ||
| }, | ||
| query: { | ||
| projectGroup: selectedProjectGroup?.id, | ||
| }, | ||
| }" | ||
| class="font-semibold text-medium leading-6 mb-1 truncate text-black hover:text-primary-500 transition block w-full overflow-hidden" | ||
| > | ||
| {{ props.organization.displayName }} | ||
| </router-link> | ||
|
|
||
| <div class="flex flex-auto flex-col overflow-hidden"> | ||
| <div v-if="props.organization?.memberOrganizations?.title" class="text-small text-gray-500 mb-1.5 flex items-center gap-1.5"> | ||
|
||
| <lf-svg name="id-card" class="h-4 w-4 text-gray-400" /> | ||
| <p class="truncate" style="max-width: 30ch"> | ||
|
|
@@ -80,11 +51,8 @@ | |
| import LfIconOld from '@/ui-kit/icon/IconOld.vue'; | ||
| import { Contributor } from '@/modules/contributor/types/Contributor'; | ||
| import LfSvg from '@/shared/svg/svg.vue'; | ||
| import LfAvatar from '@/ui-kit/avatar/Avatar.vue'; | ||
| import { Organization } from '@/modules/organization/types/Organization'; | ||
| import moment from 'moment'; | ||
| import { storeToRefs } from 'pinia'; | ||
| import { useLfSegmentsStore } from '@/modules/lf/segments/store'; | ||
| import LfButton from '@/ui-kit/button/Button.vue'; | ||
| import LfDropdown from '@/ui-kit/dropdown/Dropdown.vue'; | ||
| import LfDropdownItem from '@/ui-kit/dropdown/DropdownItem.vue'; | ||
|
|
@@ -108,7 +76,6 @@ const props = defineProps<{ | |
|
|
||
| const emit = defineEmits<{(e:'edit'): void}>(); | ||
|
|
||
| const { selectedProjectGroup } = storeToRefs(useLfSegmentsStore()); | ||
| const { deleteContributorOrganization } = useContributorStore(); | ||
| const { trackEvent } = useProductTracking(); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import LfSvg from '@/shared/svg/svg.vue'; | ||
| import LfIconOld from '@/ui-kit/icon/IconOld.vue'; | ||
| import LfTimeline from './Timeline.vue'; | ||
| import LfTimelineItem from './TimelineItem.vue'; | ||
|
|
||
| export default { | ||
| title: 'LinuxFoundation/Timeline', | ||
| component: LfTimeline, | ||
| tags: ['autodocs'], | ||
| argTypes: { | ||
| groups: { | ||
| description: 'Timeline groups', | ||
| control: 'object', | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| export const Regular = { | ||
| args: { | ||
| groups: [ | ||
| { | ||
| label: 'Group 1', labelLink: { name: 'organizationView', params: { id: '1' } }, icon: 'https://avatars.githubusercontent.com/u/38015056?v=4', items: [{ id: 1, label: 'Item 1', date: 'Aug 2024 - Dec 2024' }, { id: 2, label: 'Item 2', date: 'Aug 2024' }, { id: 3, label: 'Item 3', date: 'Aug 2024' }, { id: 4, label: 'Item 4', date: 'Aug 2024' }], | ||
| }, | ||
| { | ||
| label: 'Group 2', labelLink: { name: 'organizationView', params: { id: '2' } }, icon: 'https://avatars.githubusercontent.com/u/38015056?v=4', items: [{ id: 3, label: 'Item 3', date: 'Aug 2024' }, { id: 4, label: 'Item 4', date: 'Aug 2024' }], | ||
| }, | ||
| ], | ||
| }, | ||
| render: (args: any) => ({ | ||
| components: { | ||
| LfTimeline, LfTimelineItem, LfSvg, LfIconOld, | ||
| }, | ||
| setup() { | ||
| return { args }; | ||
| }, | ||
emlimlf marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| template: `<lf-timeline :groups="args.groups" v-slot="{ group }"> | ||
| <lf-timeline-item data="Item 1" v-for="item in group.items" :key="item.id"> | ||
| <div class="text-small text-gray-900 mb-1.5 flex items-center gap-1.5"> | ||
| <lf-svg name="id-card" class="h-4 w-4 text-gray-400" /> | ||
| <p class="truncate" style="max-width: 30ch"> | ||
| {{ item.label }} | ||
| </p> | ||
|
||
| </div> | ||
| <p class="text-small text-gray-500 mb-1.5 flex items-center"> | ||
| <lf-icon-old name="calendar-line" :size="16" class="mr-1.5 text-gray-400" /> | ||
| {{ item.date }} | ||
| </p> | ||
| </lf-timeline-item> | ||
| </lf-timeline>`, | ||
| }), | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| <template> | ||
| <div v-for="group in props.groups" :key="group.label" class="c-timeline"> | ||
| <div class="c-timeline__group-icon"> | ||
| <lf-avatar | ||
| :name="group.label" | ||
| :src="group.icon" | ||
| :size="24" | ||
| class="!rounded-md border border-gray-200 min-w-6" | ||
| img-class="!object-contain" | ||
| /> | ||
| </div> | ||
| <div> | ||
| <div class="c-timeline__group-label"> | ||
| <router-link | ||
| v-if="group.labelLink" | ||
| :to="group.labelLink" | ||
| class="cursor-pointer" | ||
| > | ||
| {{ group.label }} | ||
| </router-link> | ||
| <span v-else> | ||
| {{ group.label }} | ||
| </span> | ||
| </div> | ||
|
|
||
| <div class="c-timeline__items"> | ||
| <slot name="default" :group="group" /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </template> | ||
|
|
||
| <script lang="ts" setup> | ||
| import LfAvatar from '@/ui-kit/avatar/Avatar.vue'; | ||
| import { TimelineGroup } from './types/TimelineTypes'; | ||
|
|
||
| const props = defineProps<{ | ||
| groups: TimelineGroup[]; | ||
| }>(); | ||
|
|
||
| </script> | ||
|
|
||
| <script lang="ts"> | ||
| export default { | ||
| name: 'LfTimeline', | ||
| }; | ||
| </script> | ||
|
|
||
| <style scoped lang="scss" src="./timeline.scss" /> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| <template> | ||
| <div class="c-timeline__item"> | ||
| <div class="c-timeline__item-dot" /> | ||
| <div class="c-timeline__item-content"> | ||
| <slot :data="props.data" /> | ||
| </div> | ||
| </div> | ||
| </template> | ||
|
|
||
| <script lang="ts" setup> | ||
| const props = defineProps<{ | ||
| data: any; | ||
| }>(); | ||
joanagmaia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| </script> | ||
| <script lang="ts"> | ||
| export default { | ||
| name: 'LfTimelineItem', | ||
| }; | ||
| </script> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| .c-timeline { | ||
| @apply flex items-start gap-3; | ||
| &__group-label { | ||
| @apply flex items-center font-semibold text-medium leading-6 mb-1 truncate text-black hover:text-primary-500 transition block w-full overflow-hidden; | ||
| } | ||
| // &__border { | ||
| // @apply w-px h-full bg-gray-200; | ||
| // } | ||
|
|
||
| ::v-deep .c-timeline__item { | ||
| @apply relative mb-4; | ||
| .c-timeline__item-dot { | ||
| @apply w-3 h-3 z-[2] bg-gray-200 rounded-full absolute top-[2px] -left-[30px] border-3 border-white; | ||
| } | ||
| .c-timeline__item-content { | ||
| @apply relative; | ||
| &::before { | ||
| content: ''; | ||
| @apply w-px bg-gray-200 absolute top-[2px] left-[-25px]; | ||
| height: calc(100% + 25px); | ||
| } | ||
| } | ||
|
|
||
| &:first-child { | ||
| .c-timeline__item-dot { | ||
| @apply invisible; | ||
| } | ||
| } | ||
|
|
||
| &:last-child { | ||
| .c-timeline__item-content { | ||
| &::before { | ||
| @apply h-[5px]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import type { RouteLocationRaw } from 'vue-router'; | ||
|
|
||
| export interface TimelineGroup { | ||
| label: string; | ||
| labelLink?: RouteLocationRaw; | ||
| icon?: string; | ||
| items: any[]; | ||
emlimlf marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.