From fab8ee5f144790a9e07ddc2fe7e8392062769180 Mon Sep 17 00:00:00 2001 From: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> Date: Tue, 29 Mar 2022 20:33:39 +0600 Subject: [PATCH] Applications view (#1237) Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> --- models/recruit/src/index.ts | 16 +++- models/recruit/src/plugin.ts | 3 +- .../src/components/ApplicationsView.svelte | 90 +++++++++++++++++++ plugins/recruit-resources/src/index.ts | 4 +- 4 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 plugins/recruit-resources/src/components/ApplicationsView.svelte diff --git a/models/recruit/src/index.ts b/models/recruit/src/index.ts index f8e9d934ad..8dcb08204c 100644 --- a/models/recruit/src/index.ts +++ b/models/recruit/src/index.ts @@ -30,6 +30,7 @@ import { UX } from '@anticrm/model' import attachment from '@anticrm/model-attachment' +import calendar from '@anticrm/model-calendar' import chunter from '@anticrm/model-chunter' import contact, { TPerson } from '@anticrm/model-contact' import core, { TSpace } from '@anticrm/model-core' @@ -39,10 +40,9 @@ import task, { TSpaceWithStates, TTask } from '@anticrm/model-task' import view from '@anticrm/model-view' import workbench from '@anticrm/model-workbench' import { Applicant, Candidate, Candidates, Vacancy } from '@anticrm/recruit' -import { TOpinion, TReview, TReviewCategory } from './review-model' import recruit from './plugin' import { createReviewModel, reviewTableConfig, reviewTableOptions } from './review' -import calendar from '@anticrm/model-calendar' +import { TOpinion, TReview, TReviewCategory } from './review-model' @Model(recruit.class.Vacancy, task.class.SpaceWithStates) @UX(recruit.string.Vacancy, recruit.icon.Vacancy) @@ -106,6 +106,10 @@ export class TApplicant extends TTask implements Applicant { @Prop(TypeRef(recruit.mixin.Candidate), recruit.string.Candidate) declare attachedTo: Ref<Candidate> + // We need to declare, to provide property with label + @Prop(TypeRef(recruit.class.Vacancy), recruit.string.Vacancy) + declare space: Ref<Vacancy> + @Prop(Collection(attachment.class.Attachment), attachment.string.Attachments) attachments?: number @@ -160,6 +164,14 @@ export function createModel (builder: Builder): void { createItemLabel: recruit.string.VacancyCreateLabel, position: 'bottom' }, + { + id: 'applicants', + component: recruit.component.ApplicationsView, + icon: recruit.icon.Application, + label: recruit.string.Applications, + createItemLabel: recruit.string.ApplicationCreateLabel, + position: 'bottom' + }, { id: 'candidates', component: recruit.component.Candidates, diff --git a/models/recruit/src/plugin.ts b/models/recruit/src/plugin.ts index a86fe6da22..cdcf5b30dd 100644 --- a/models/recruit/src/plugin.ts +++ b/models/recruit/src/plugin.ts @@ -77,7 +77,8 @@ export default mergeIds(recruitId, recruit, { EditReview: '' as AnyComponent, ReviewPresenter: '' as AnyComponent, Opinions: '' as AnyComponent, - OpinionPresenter: '' as AnyComponent + OpinionPresenter: '' as AnyComponent, + ApplicationsView: '' as AnyComponent }, template: { DefaultVacancy: '' as Ref<KanbanTemplate>, diff --git a/plugins/recruit-resources/src/components/ApplicationsView.svelte b/plugins/recruit-resources/src/components/ApplicationsView.svelte new file mode 100644 index 0000000000..be8a857228 --- /dev/null +++ b/plugins/recruit-resources/src/components/ApplicationsView.svelte @@ -0,0 +1,90 @@ +<!-- +// Copyright © 2020, 2021 Anticrm Platform Contributors. +// Copyright © 2021 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +--> + +<script lang="ts"> + import attachment from '@anticrm/attachment' + import chunter from '@anticrm/chunter' + import contact from '@anticrm/contact' + import core,{ Doc,DocumentQuery,FindOptions } from '@anticrm/core' + import { Applicant } from '@anticrm/recruit' + import task from '@anticrm/task' + import { Button,Icon,IconAdd,Label,Scroller,SearchEdit,showPopup } from '@anticrm/ui' +import { BuildModelKey } from '@anticrm/view'; + import { Table } from '@anticrm/view-resources' + import recruit from '../plugin' + import CreateApplication from './CreateApplication.svelte' + + let search = '' + let resultQuery: DocumentQuery<Doc> = {} + const baseQuery: DocumentQuery<Applicant> = { + doneState: null + } + + const config: (BuildModelKey | string)[] = [ + '', + '$lookup.space', + '$lookup.attachedTo', + '$lookup.assignee', + '$lookup.state', + { + key: '', + presenter: attachment.component.AttachmentsPresenter, + label: attachment.string.Files, + sortingKey: 'attachments' + }, + { key: '', presenter: chunter.component.CommentsPresenter, label: chunter.string.Comments, sortingKey: 'comments' }, + 'modifiedOn', + '$lookup.attachedTo.$lookup.channels' + ] + + const options: FindOptions<Applicant> = { + lookup: { + attachedTo: [recruit.mixin.Candidate, { _id: { channels: contact.class.Channel } }], + state: task.class.State, + assignee: contact.class.Employee, + space: recruit.class.Vacancy + } + } + + function showCreateDialog (ev: Event) { + showPopup(CreateApplication, { }, ev.target as HTMLElement) + } + + function updateResultQuery (search: string): void { + resultQuery = (search === '') ? baseQuery : { ...baseQuery,$search: search } + } +</script> + +<div class="ac-header full"> + <div class="ac-header__wrap-title"> + <div class="ac-header__icon"><Icon icon={recruit.icon.Application} size={'small'} /></div> + <span class="ac-header__title"><Label label={recruit.string.Applications} /></span> + </div> + + <SearchEdit bind:value={search} on:change={() => { updateResultQuery(search) }} /> + <Button icon={IconAdd} label={recruit.string.ApplicationCreateLabel} primary size={'small'} on:click={(ev) => showCreateDialog(ev)} /> +</div> + +<Scroller> + <Table + _class={recruit.class.Applicant} + {config} + {options} + query={ resultQuery } + showNotification + highlightRows + /> +</Scroller> diff --git a/plugins/recruit-resources/src/index.ts b/plugins/recruit-resources/src/index.ts index 6b4e598862..957a58c82c 100644 --- a/plugins/recruit-resources/src/index.ts +++ b/plugins/recruit-resources/src/index.ts @@ -48,6 +48,7 @@ import VacancyPresenter from './components/VacancyPresenter.svelte' import VacancyCountPresenter from './components/VacancyCountPresenter.svelte' import VacancyModifiedPresenter from './components/VacancyModifiedPresenter.svelte' import ReviewCategoryPresenter from './components/review/ReviewCategoryPresenter.svelte' +import ApplicationsView from './components/ApplicationsView.svelte' import recruit from './plugin' async function createApplication (object: Doc): Promise<void> { @@ -166,7 +167,8 @@ export default async (): Promise<Resources> => ({ Opinions, OpinionPresenter, OpinionsPresenter, - ReviewCategoryPresenter + ReviewCategoryPresenter, + ApplicationsView }, completion: { ApplicationQuery: async (client: Client, query: string) => await queryApplication(client, query)