From b46b65fe5d6453cbb883b576ec3511752b1ddf77 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Sun, 28 May 2023 13:33:42 +0700 Subject: [PATCH] UBER-268: List views (#3270) --- models/lead/package.json | 3 +- models/lead/src/index.ts | 121 +++++++++++++----- models/recruit/src/index.ts | 79 +++++++++++- models/recruit/src/plugin.ts | 1 + models/tracker/src/index.ts | 7 +- .../src/components/ContactPresenter.svelte | 3 +- .../src/components/ContactRefPresenter.svelte | 4 +- .../components/OrganizationPresenter.svelte | 8 +- .../src/components/PersonContent.svelte | 2 + .../src/components/PersonPresenter.svelte | 2 + .../src/components/TitlePresenter.svelte | 55 ++++++++ plugins/lead-resources/src/index.ts | 4 +- plugins/lead-resources/src/plugin.ts | 3 +- 13 files changed, 252 insertions(+), 40 deletions(-) create mode 100644 plugins/lead-resources/src/components/TitlePresenter.svelte diff --git a/models/lead/package.json b/models/lead/package.json index 7d413c17af..730bd95219 100644 --- a/models/lead/package.json +++ b/models/lead/package.json @@ -44,6 +44,7 @@ "@hcengineering/model-notification": "^0.6.0", "@hcengineering/notification": "^0.6.12", "@hcengineering/model-task": "^0.6.0", - "@hcengineering/workbench": "^0.6.6" + "@hcengineering/workbench": "^0.6.6", + "@hcengineering/model-tracker": "^0.6.0" } } diff --git a/models/lead/src/index.ts b/models/lead/src/index.ts index 8c80f5a514..06566b8d26 100644 --- a/models/lead/src/index.ts +++ b/models/lead/src/index.ts @@ -42,6 +42,7 @@ import { ViewOptionsModel } from '@hcengineering/view' import { generateClassNotificationTypes } from '@hcengineering/model-notification' import notification from '@hcengineering/notification' import lead from './plugin' +import tracker from '@hcengineering/model-tracker' export { leadId } from '@hcengineering/lead' export { leadOperation } from './migration' @@ -193,6 +194,13 @@ export function createModel (builder: Builder): void { '', '_class', 'leads', + 'attachments', + { + key: '', + presenter: tracker.component.RelatedIssueSelector, + label: tracker.string.Relations + }, + 'comments', 'modifiedOn', { key: '$lookup.channels', @@ -200,7 +208,14 @@ export function createModel (builder: Builder): void { sortingKey: ['$lookup.channels.lastMessage', 'channels'] } ], - hiddenKeys: ['name'] + hiddenKeys: ['name'], + options: { + lookup: { + _id: { + related: [tracker.class.Issue, 'relations._id'] + } + } + } }, lead.viewlet.TableCustomer ) @@ -215,49 +230,38 @@ export function createModel (builder: Builder): void { '', 'title', 'attachedTo', + 'assignee', + { + key: '', + presenter: tracker.component.RelatedIssueSelector, + label: tracker.string.Issues + }, 'state', 'doneState', 'attachments', + { + key: '', + presenter: tracker.component.RelatedIssueSelector, + label: tracker.string.Relations + }, 'comments', 'modifiedOn', { key: '$lookup.attachedTo.$lookup.channels', sortingKey: ['$lookup.attachedTo.$lookup.channels.lastMessage', '$lookup.attachedTo.channels'] } - ] + ], + options: { + lookup: { + _id: { + related: [tracker.class.Issue, 'relations._id'] + } + } + } }, lead.viewlet.TableLead ) - builder.createDoc( - view.class.Viewlet, - core.space.Model, - { - attachTo: lead.class.Lead, - descriptor: view.viewlet.List, - config: [ - { key: '', props: { listProps: { fixed: 'left' } } }, - { key: 'title', props: { listProps: { fixed: 'left' } } }, - { key: 'state', props: { listProps: { fixed: 'left' } } }, - { key: 'doneState', props: { listProps: { fixed: 'left' } } }, - { key: '', presenter: view.component.GrowPresenter }, - 'attachments', - 'comments', - 'assignee' - ], - viewOptions: { - groupBy: ['assignee', 'state', 'attachedTo'], - orderBy: [ - ['assignee', -1], - ['state', 1], - ['attachedTo', 1], - ['modifiedOn', -1] - ], - other: [] - } - }, - lead.viewlet.ListLead - ) const leadViewOptions: ViewOptionsModel = { groupBy: ['state', 'assignee'], orderBy: [ @@ -278,6 +282,61 @@ export function createModel (builder: Builder): void { } ] } + builder.createDoc( + view.class.Viewlet, + core.space.Model, + { + attachTo: lead.class.Lead, + descriptor: view.viewlet.List, + config: [ + { key: '', props: { listProps: { fixed: 'left', key: 'lead' } } }, + { + key: '', + presenter: lead.component.TitlePresenter, + props: { listProps: { fixed: 'left', key: 'title' }, maxWidth: '10rem' } + }, + { + key: '$lookup.attachedTo', + presenter: contact.component.PersonPresenter, + label: lead.string.Customer, + sortingKey: '$lookup.attachedTo.name', + props: { + _class: lead.mixin.Customer, + listProps: { fixed: 'left', key: 'talent' }, + inline: true, + maxWidth: '10rem' + } + }, + { key: 'state', props: { listProps: { fixed: 'left', key: 'state' } } }, + { + key: '', + presenter: tracker.component.RelatedIssueSelector, + label: tracker.string.Relations, + props: { listProps: { fixed: 'left', key: 'issues' } } + }, + { key: 'attachments', props: { listProps: { fixed: 'left', key: 'attachments' } } }, + { key: 'comments', props: { listProps: { fixed: 'left' }, key: 'comments' } }, + { key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } }, + { key: '', presenter: view.component.DividerPresenter, props: { type: 'divider' } }, + { + key: '$lookup.attachedTo.$lookup.channels', + label: contact.string.ContactInfo, + sortingKey: ['$lookup.attachedTo.$lookup.channels.lastMessage', '$lookup.attachedTo.channels'], + props: { + listProps: { + fixed: 'left', + key: 'channels' + } + } + }, + { key: '', presenter: view.component.DividerPresenter, props: { type: 'divider' } }, + { key: 'modifiedOn', props: { listProps: { key: 'modified', fixed: 'left' } } }, + { key: 'assignee', props: { listProps: { key: 'assignee', fixed: 'right' }, shouldShowLabel: false } } + ], + viewOptions: leadViewOptions + }, + lead.viewlet.ListLead + ) const lookupLeadOptions: FindOptions = { lookup: { diff --git a/models/recruit/src/index.ts b/models/recruit/src/index.ts index 5ff71f5809..e9f66cb93b 100644 --- a/models/recruit/src/index.ts +++ b/models/recruit/src/index.ts @@ -284,7 +284,12 @@ export function createModel (builder: Builder): void { label: recruit.string.Applications, createLabel: recruit.string.ApplicationCreateLabel, createComponent: recruit.component.CreateApplication, - descriptors: [view.viewlet.Table, task.viewlet.Kanban, recruit.viewlet.ApplicantDashboard] + descriptors: [ + view.viewlet.Table, + view.viewlet.List, + task.viewlet.Kanban, + recruit.viewlet.ApplicantDashboard + ] }, position: 'vacancy' }, @@ -556,8 +561,8 @@ export function createModel (builder: Builder): void { label: tracker.string.Issues }, 'state', - 'comments', 'attachments', + 'comments', 'modifiedOn', '$lookup.space.company', { @@ -639,6 +644,76 @@ export function createModel (builder: Builder): void { } ] } + builder.createDoc( + view.class.Viewlet, + core.space.Model, + { + attachTo: recruit.class.Applicant, + descriptor: view.viewlet.List, + config: [ + { key: '', props: { listProps: { fixed: 'left', key: 'app' } } }, + { + key: '$lookup.attachedTo', + presenter: contact.component.PersonPresenter, + label: recruit.string.Talent, + sortingKey: '$lookup.attachedTo.name', + props: { + _class: recruit.mixin.Candidate, + listProps: { fixed: 'left', key: 'talent' }, + inline: true + } + }, + { key: 'state', props: { listProps: { fixed: 'left', key: 'state' }, inline: true, showLabel: false } }, + { + key: '$lookup.space.company', + props: { + listProps: { fixed: 'left', key: 'company' }, + inline: true, + maxWidth: '10rem' + } + }, + { + key: '', + presenter: tracker.component.RelatedIssueSelector, + label: tracker.string.Issues, + props: { listProps: { fixed: 'left', key: 'issues' } } + }, + { key: 'attachments', props: { listProps: { fixed: 'left', key: 'attachments' } } }, + { key: 'comments', props: { listProps: { fixed: 'left' }, key: 'comments' } }, + { key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } }, + { key: '', presenter: view.component.DividerPresenter, props: { type: 'divider' } }, + { + key: '$lookup.attachedTo.$lookup.channels', + label: contact.string.ContactInfo, + sortingKey: ['$lookup.attachedTo.$lookup.channels.lastMessage', '$lookup.attachedTo.channels'], + props: { + listProps: { + fixed: 'left', + key: 'channels' + } + } + }, + { key: '', presenter: view.component.DividerPresenter, props: { type: 'divider' } }, + { key: 'modifiedOn', props: { listProps: { key: 'modified', fixed: 'left' } } }, + { key: 'assignee', props: { listProps: { key: 'assignee', fixed: 'right' }, shouldShowLabel: false } } + ], + options: { + lookup: { + _id: { + related: [tracker.class.Issue, 'relations._id'] + }, + space: recruit.class.Vacancy + } + }, + hiddenKeys: ['name', 'attachedTo'], + baseQuery: { + doneState: null, + '$lookup.space.archived': false + }, + viewOptions: applicantViewOptions + }, + recruit.viewlet.ListApplicant + ) builder.createDoc( view.class.Viewlet, diff --git a/models/recruit/src/plugin.ts b/models/recruit/src/plugin.ts index 758443a0e5..2f4bcc5eed 100644 --- a/models/recruit/src/plugin.ts +++ b/models/recruit/src/plugin.ts @@ -113,6 +113,7 @@ export default mergeIds(recruitId, recruit, { TableVacancy: '' as Ref, ApplicantTable: '' as Ref, ApplicantKanban: '' as Ref, + ListApplicant: '' as Ref, TableApplicant: '' as Ref, TableApplicantMatch: '' as Ref, CalendarReview: '' as Ref, diff --git a/models/tracker/src/index.ts b/models/tracker/src/index.ts index f7c894b7da..aec22b92ff 100644 --- a/models/tracker/src/index.ts +++ b/models/tracker/src/index.ts @@ -573,7 +573,12 @@ export function createModel (builder: Builder): void { { key: 'assignee', presenter: tracker.component.AssigneePresenter, - props: { defaultClass: contact.class.Employee, shouldShowLabel: false } + props: { + listProps: { key: 'assigee', fixed: 'right' }, + key: 'assignee', + defaultClass: contact.class.Employee, + shouldShowLabel: false + } } ], options: { diff --git a/plugins/contact-resources/src/components/ContactPresenter.svelte b/plugins/contact-resources/src/components/ContactPresenter.svelte index 5e741041e8..faa2c007de 100644 --- a/plugins/contact-resources/src/components/ContactPresenter.svelte +++ b/plugins/contact-resources/src/components/ContactPresenter.svelte @@ -25,6 +25,7 @@ export let value: Contact export let inline: boolean = false export let disabled = false + export let maxWidth = '' function isPerson (value: Contact): boolean { const client = getClient() @@ -45,5 +46,5 @@ {:else if isPerson(value)} {:else} - + {/if} diff --git a/plugins/contact-resources/src/components/ContactRefPresenter.svelte b/plugins/contact-resources/src/components/ContactRefPresenter.svelte index c21e9dc7e1..6ce078f967 100644 --- a/plugins/contact-resources/src/components/ContactRefPresenter.svelte +++ b/plugins/contact-resources/src/components/ContactRefPresenter.svelte @@ -22,6 +22,8 @@ export let value: Ref export let disabled = false + export let maxWidth = '' + export let inline = false let doc: Contact | undefined const query = createQuery() @@ -29,5 +31,5 @@ {#if doc} - + {/if} diff --git a/plugins/contact-resources/src/components/OrganizationPresenter.svelte b/plugins/contact-resources/src/components/OrganizationPresenter.svelte index b4271bb190..5495cda482 100644 --- a/plugins/contact-resources/src/components/OrganizationPresenter.svelte +++ b/plugins/contact-resources/src/components/OrganizationPresenter.svelte @@ -22,11 +22,17 @@ export let value: Organization export let inline: boolean = false + export let maxWidth = '' {#if value} -
+
{#if !inline}
{/if} diff --git a/plugins/contact-resources/src/components/PersonContent.svelte b/plugins/contact-resources/src/components/PersonContent.svelte index c7bbe5ae34..363decb5ee 100644 --- a/plugins/contact-resources/src/components/PersonContent.svelte +++ b/plugins/contact-resources/src/components/PersonContent.svelte @@ -43,6 +43,7 @@ export let enlargedText = false export let colorInherit: boolean = false export let accent: boolean = false + export let maxWidth = '' const onEditClick = (evt: MouseEvent) => { if (!disabled) { @@ -70,6 +71,7 @@ class="contentPresenter" class:text-base={enlargedText} class:inline-presenter={inline} + style:max-width={maxWidth} > {#if !inline && shouldShowAvatar} diff --git a/plugins/lead-resources/src/components/TitlePresenter.svelte b/plugins/lead-resources/src/components/TitlePresenter.svelte new file mode 100644 index 0000000000..0775f8b185 --- /dev/null +++ b/plugins/lead-resources/src/components/TitlePresenter.svelte @@ -0,0 +1,55 @@ + + + +{#if value} + + {value.title} + +{/if} + + diff --git a/plugins/lead-resources/src/index.ts b/plugins/lead-resources/src/index.ts index 78793651a5..112267c065 100644 --- a/plugins/lead-resources/src/index.ts +++ b/plugins/lead-resources/src/index.ts @@ -28,6 +28,7 @@ import NewItemsHeader from './components/NewItemsHeader.svelte' import { getLeadTitle } from './utils' import EditFunnel from './components/EditFunnel.svelte' import MyLeads from './components/MyLeads.svelte' +import TitlePresenter from './components/TitlePresenter.svelte' export default async (): Promise => ({ component: { @@ -42,7 +43,8 @@ export default async (): Promise => ({ CreateCustomer, NewItemsHeader, EditFunnel, - MyLeads + MyLeads, + TitlePresenter }, function: { LeadTitleProvider: getLeadTitle diff --git a/plugins/lead-resources/src/plugin.ts b/plugins/lead-resources/src/plugin.ts index 480d410126..e574268fe1 100644 --- a/plugins/lead-resources/src/plugin.ts +++ b/plugins/lead-resources/src/plugin.ts @@ -49,7 +49,8 @@ export default mergeIds(leadId, lead, { LeadsPresenter: '' as AnyComponent, CreateFunnel: '' as AnyComponent, EditFunnel: '' as AnyComponent, - MyLeads: '' as AnyComponent + MyLeads: '' as AnyComponent, + TitlePresenter: '' as AnyComponent }, function: { LeadTitleProvider: '' as Resource<(client: Client, ref: Ref) => Promise>