From d1fb81582d4c95e4b76d1a0d87c39a05000789fb Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Sun, 29 Jan 2023 12:44:12 +0700 Subject: [PATCH] Various small issue fixes (#2556) * Fix Issue title be selectable * TSK-582: Fix Vacancy subtitle be hyperlink * TSK-585: Add tasks to Applications Signed-off-by: Andrey Sobolev --- models/recruit/package.json | 1 + models/recruit/src/index.ts | 90 ++++++++++- models/task/src/index.ts | 4 +- models/view/src/index.ts | 7 + packages/panel/src/components/Panel.svelte | 9 +- .../src/components/AssigneeBox.svelte | 4 +- .../src/components/UserBox.svelte | 4 +- packages/theme/styles/_layouts.scss | 1 + .../src/components/PersonCard.svelte | 4 +- .../src/components/PersonRefPresenter.svelte | 5 +- plugins/contact-resources/src/index.ts | 3 +- plugins/login-assets/lang/ru.json | 2 +- .../src/components/CandidateCard.svelte | 4 +- .../src/components/EditApplication.svelte | 8 +- .../src/components/EditVacancy.svelte | 12 +- .../src/components/KanbanCard.svelte | 25 +-- .../src/components/review/EditReview.svelte | 3 +- .../components/issues/edit/EditIssue.svelte | 4 +- .../related/RelatedIssueSelector.svelte | 153 ++++++++++++++++++ plugins/tracker-resources/src/index.ts | 4 +- plugins/tracker/src/index.ts | 1 + .../src/components/EditDoc.svelte | 24 ++- .../src/components/ObjectBox.svelte | 4 +- .../src/components/Table.svelte | 4 +- .../src/components/ViewOptions.svelte | 2 +- .../src/components/ViewletSetting.svelte | 2 +- .../src/components/list/List.svelte | 4 +- plugins/view-resources/src/utils.ts | 15 +- plugins/view/src/index.ts | 9 ++ plugins/workbench-assets/lang/ru.json | 2 +- server/core/src/storage.ts | 2 +- server/mongo/src/__tests__/storage.test.ts | 1 + 32 files changed, 348 insertions(+), 69 deletions(-) create mode 100644 plugins/tracker-resources/src/components/issues/related/RelatedIssueSelector.svelte diff --git a/models/recruit/package.json b/models/recruit/package.json index 32344b2d2b..497e932913 100644 --- a/models/recruit/package.json +++ b/models/recruit/package.json @@ -44,6 +44,7 @@ "@hcengineering/setting": "^0.6.2", "@hcengineering/model-task": "^0.6.0", "@hcengineering/workbench": "^0.6.2", + "@hcengineering/model-tracker": "^0.6.0", "@hcengineering/model-presentation": "^0.6.0", "@hcengineering/model-calendar": "^0.6.0", "@hcengineering/model-tags": "^0.6.0", diff --git a/models/recruit/src/index.ts b/models/recruit/src/index.ts index 0f028b2f64..8a63cbfb8b 100644 --- a/models/recruit/src/index.ts +++ b/models/recruit/src/index.ts @@ -39,6 +39,7 @@ import core, { TAttachedDoc, TSpace } from '@hcengineering/model-core' import presentation from '@hcengineering/model-presentation' import tags from '@hcengineering/model-tags' import task, { actionTemplates, DOMAIN_TASK, TSpaceWithStates, TTask } from '@hcengineering/model-task' +import tracker from '@hcengineering/model-tracker' import view, { actionTemplates as viewTemplates, createAction } from '@hcengineering/model-view' import workbench, { Application, createNavigateAction } from '@hcengineering/model-workbench' import { getEmbeddedLabel, IntlString } from '@hcengineering/platform' @@ -331,6 +332,11 @@ export function createModel (builder: Builder): void { 'city', 'applications', 'attachments', + { + key: '', + presenter: tracker.component.RelatedIssueSelector, + label: tracker.string.Relations + }, 'comments', { // key: '$lookup.skills', // Required, since presenter require list of tag references or '' and TagsPopupPresenter @@ -351,7 +357,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'] + } + } + } }, recruit.viewlet.TableCandidate ) @@ -390,8 +403,21 @@ export function createModel (builder: Builder): void { descriptor: task.viewlet.StatusTable, config: [ '', - 'attachedTo', + { + key: 'attachedTo', + presenter: contact.component.PersonRefPresenter, + sortingKey: 'attachedTo', + label: recruit.string.Talent, + props: { + _class: recruit.mixin.Candidate + } + }, 'assignee', + { + key: '', + presenter: tracker.component.RelatedIssueSelector, + label: tracker.string.Issues + }, 'state', 'doneState', 'attachments', @@ -399,9 +425,18 @@ export function createModel (builder: Builder): void { 'modifiedOn', { key: '$lookup.attachedTo.$lookup.channels', + label: contact.string.ContactInfo, sortingKey: ['$lookup.attachedTo.$lookup.channels.lastMessage', '$lookup.attachedTo.channels'] } - ] + ], + hiddenKeys: ['name', 'attachedTo'], + options: { + lookup: { + _id: { + related: [tracker.class.Issue, 'relations._id'] + } + } + } }, recruit.viewlet.TableApplicant ) @@ -413,18 +448,40 @@ export function createModel (builder: Builder): void { descriptor: view.viewlet.Table, config: [ '', - 'attachedTo', + { + key: 'attachedTo', + presenter: contact.component.PersonRefPresenter, + label: recruit.string.Talent, + sortingKey: 'attachedTo', + props: { + _class: recruit.mixin.Candidate + } + }, 'assignee', + { + key: '', + presenter: tracker.component.RelatedIssueSelector, + label: tracker.string.Issues + }, 'state', 'comments', 'attachments', 'modifiedOn', + '$lookup.space.company', { key: '$lookup.attachedTo.$lookup.channels', + label: contact.string.ContactInfo, sortingKey: ['$lookup.attachedTo.$lookup.channels.lastMessage', '$lookup.attachedTo.channels'] } ], - hiddenKeys: ['name'] + options: { + lookup: { + _id: { + related: [tracker.class.Issue, 'relations._id'] + } + } + }, + hiddenKeys: ['name', 'attachedTo'] }, recruit.viewlet.ApplicantTable ) @@ -452,7 +509,7 @@ export function createModel (builder: Builder): void { ], assignee: contact.class.Employee, _id: { - todoItems: task.class.TodoItem + related: [tracker.class.Issue, 'relations._id'] } } @@ -672,7 +729,7 @@ export function createModel (builder: Builder): void { }) builder.mixin(recruit.class.Applicant, core.class.Class, view.mixin.ClassFilters, { - filters: ['attachedTo', 'assignee', 'state', 'doneState', 'modifiedOn'] + filters: ['attachedTo', 'space', 'assignee', 'state', 'doneState', 'modifiedOn'] }) builder.mixin(recruit.class.Vacancy, core.class.Class, view.mixin.ClassFilters, { @@ -917,6 +974,25 @@ export function createModel (builder: Builder): void { group: 'create' } }) + + builder.mixin(recruit.mixin.Candidate, core.class.Class, view.mixin.ObjectEditorFooter, { + editor: tracker.component.RelatedIssuesSection, + props: { + label: recruit.string.RelatedIssues + } + }) + builder.mixin(recruit.class.Vacancy, core.class.Class, view.mixin.ObjectEditorFooter, { + editor: tracker.component.RelatedIssuesSection, + props: { + label: recruit.string.RelatedIssues + } + }) + builder.mixin(recruit.class.Applicant, core.class.Class, view.mixin.ObjectEditorFooter, { + editor: tracker.component.RelatedIssuesSection, + props: { + label: recruit.string.RelatedIssues + } + }) } export { recruitOperation } from './migration' diff --git a/models/task/src/index.ts b/models/task/src/index.ts index 5041dc9f50..bccc03b700 100644 --- a/models/task/src/index.ts +++ b/models/task/src/index.ts @@ -134,8 +134,8 @@ export class TTask extends TAttachedDoc implements Task { declare rank: string - @Prop(Collection(task.class.TodoItem), task.string.Todos) - todoItems!: number + // @Prop(Collection(task.class.TodoItem), task.string.Todos) + // todoItems!: number @Prop(Collection(tags.class.TagReference, task.string.TaskLabels), task.string.TaskLabels) labels!: number diff --git a/models/view/src/index.ts b/models/view/src/index.ts index 1f9f9d5891..45c0339ac1 100644 --- a/models/view/src/index.ts +++ b/models/view/src/index.ts @@ -46,6 +46,7 @@ import type { ListItemPresenter, ObjectEditor, ObjectEditorHeader, + ObjectEditorFooter, ObjectFactory, ObjectPresenter, ObjectTitle, @@ -173,6 +174,11 @@ export class TObjectEditorHeader extends TClass implements ObjectEditorHeader { editor!: AnyComponent } +@Mixin(view.mixin.ObjectEditorFooter, core.class.Class) +export class TObjectEditorFooter extends TClass implements ObjectEditorFooter { + editor!: AnyComponent +} + @Mixin(view.mixin.SpaceHeader, core.class.Class) export class TSpaceHeader extends TClass implements SpaceHeader { header!: AnyComponent @@ -325,6 +331,7 @@ export function createModel (builder: Builder): void { TObjectFactory, TObjectTitle, TObjectEditorHeader, + TObjectEditorFooter, TSpaceHeader, TSpaceName, TIgnoreActions, diff --git a/packages/panel/src/components/Panel.svelte b/packages/panel/src/components/Panel.svelte index 459b469798..a5fa38418c 100644 --- a/packages/panel/src/components/Panel.svelte +++ b/packages/panel/src/components/Panel.svelte @@ -71,7 +71,14 @@ {#if icon}
{/if}
{#if title}{title}{/if} - {#if subtitle}{subtitle}{/if} + {#if subtitle || $$slots.subtitle} + + {#if subtitle} + {subtitle} + {/if} + + + {/if}
{/if} diff --git a/packages/presentation/src/components/AssigneeBox.svelte b/packages/presentation/src/components/AssigneeBox.svelte index d4462e97b8..a42f2aaf9b 100644 --- a/packages/presentation/src/components/AssigneeBox.svelte +++ b/packages/presentation/src/components/AssigneeBox.svelte @@ -14,7 +14,7 @@ --> +
@@ -72,18 +70,7 @@
- {#if todoItems.length > 0} -
- ({doneTasks?.length}/{todoItems.length}) -
- {/if} +
{#if (object.attachments ?? 0) > 0}
diff --git a/plugins/recruit-resources/src/components/review/EditReview.svelte b/plugins/recruit-resources/src/components/review/EditReview.svelte index 51d27457eb..3dfe88aaf9 100644 --- a/plugins/recruit-resources/src/components/review/EditReview.svelte +++ b/plugins/recruit-resources/src/components/review/EditReview.svelte @@ -16,6 +16,7 @@ + +{#if hasSubIssues} +
+ +
+{/if} diff --git a/plugins/tracker-resources/src/index.ts b/plugins/tracker-resources/src/index.ts index d0d520f4ac..b4d5e7f40b 100644 --- a/plugins/tracker-resources/src/index.ts +++ b/plugins/tracker-resources/src/index.ts @@ -61,6 +61,7 @@ import SetParentIssueActionPopup from './components/SetParentIssueActionPopup.sv import Views from './components/views/Views.svelte' import Statuses from './components/workflow/Statuses.svelte' import RelatedIssuesSection from './components/issues/related/RelatedIssuesSection.svelte' +import RelatedIssueSelector from './components/issues/related/RelatedIssueSelector.svelte' import { getIssueId, getIssueTitle, @@ -280,7 +281,8 @@ export default async (): Promise => ({ TeamPresenter, IssueStatistics, StatusRefPresenter, - RelatedIssuesSection + RelatedIssuesSection, + RelatedIssueSelector }, completion: { IssueQuery: async (client: Client, query: string, filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }) => diff --git a/plugins/tracker/src/index.ts b/plugins/tracker/src/index.ts index 6fe7987f86..f3eb14e2fa 100644 --- a/plugins/tracker/src/index.ts +++ b/plugins/tracker/src/index.ts @@ -400,6 +400,7 @@ export default plugin(trackerId, { TrackerApp: '' as AnyComponent, RelatedIssues: '' as AnyComponent, RelatedIssuesSection: '' as AnyComponent, + RelatedIssueSelector: '' as AnyComponent, RelatedIssueTemplates: '' as AnyComponent, EditIssue: '' as AnyComponent, CreateIssue: '' as AnyComponent, diff --git a/plugins/view-resources/src/components/EditDoc.svelte b/plugins/view-resources/src/components/EditDoc.svelte index 186d98cf6e..bbef43a14e 100644 --- a/plugins/view-resources/src/components/EditDoc.svelte +++ b/plugins/view-resources/src/components/EditDoc.svelte @@ -35,8 +35,8 @@ import { categorizeFields, getCollectionCounter, getFiltredKeys } from '../utils' import ActionContext from './ActionContext.svelte' import DocAttributeBar from './DocAttributeBar.svelte' - import UpDownNavigator from './UpDownNavigator.svelte' import IconMixin from './icons/Mixin.svelte' + import UpDownNavigator from './UpDownNavigator.svelte' export let _id: Ref export let _class: Ref> @@ -147,19 +147,32 @@ pinned?: boolean } - async function getEditor (_class: Ref>): Promise { + function getEditor (_class: Ref>): MixinEditor { const clazz = hierarchy.getClass(_class) const editorMixin = hierarchy.as(clazz, view.mixin.ObjectEditor) if (editorMixin?.editor == null && clazz.extends != null) return getEditor(clazz.extends) return { editor: editorMixin.editor, pinned: editorMixin?.pinned } } + function getEditorFooter (_class: Ref>): { footer: AnyComponent; props?: Record } | undefined { + const clazz = hierarchy.getClass(_class) + const editorMixin = hierarchy.as(clazz, view.mixin.ObjectEditorFooter) + if (editorMixin?.editor == null && clazz.extends != null) return getEditorFooter(clazz.extends) + if (editorMixin.editor) { + return { footer: editorMixin.editor, props: editorMixin?.props } + } + return undefined + } + let mainEditor: MixinEditor | undefined + + $: editorFooter = getEditorFooter(_class) + $: getEditorOrDefault(realObjectClass, showAllMixins, _id) - async function getEditorOrDefault (_class: Ref>, showAllMixins: boolean, _id: Ref): Promise { + function getEditorOrDefault (_class: Ref>, showAllMixins: boolean, _id: Ref): void { parentClass = getParentClass(_class) - mainEditor = await getEditor(_class) + mainEditor = getEditor(_class) updateKeys(showAllMixins) } @@ -370,5 +383,8 @@
{/if} {/each} + {#if editorFooter} + + {/if} {/if} diff --git a/plugins/view-resources/src/components/ObjectBox.svelte b/plugins/view-resources/src/components/ObjectBox.svelte index 1793ecf65d..01426475f7 100644 --- a/plugins/view-resources/src/components/ObjectBox.svelte +++ b/plugins/view-resources/src/components/ObjectBox.svelte @@ -14,7 +14,7 @@ // limitations under the License. -->