Vacancies sorting (#1143)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2022-03-15 16:01:49 +07:00 committed by GitHub
parent 728216c936
commit 36ddf8477a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 63 additions and 12 deletions

View File

@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import { Doc, DocumentQuery, Ref } from '@anticrm/core'
import core, { Doc, DocumentQuery, Ref } from '@anticrm/core'
import { createQuery } from '@anticrm/presentation'
import { Applicant, Vacancy } from '@anticrm/recruit'
import { Button, getCurrentLocation, Icon, Label, navigate, Scroller, showPopup, IconAdd } from '@anticrm/ui'
@ -42,7 +42,7 @@
vacancies = res
})
function lowerIncludes (a?: string, b: string): boolean {
function lowerIncludes (a: string | undefined, b: string): boolean {
return (a ?? '').toLowerCase().includes(b)
}
@ -63,8 +63,8 @@
}
$: resultQuery = vquery === '' ? {} : { $search: vquery }
let applications: Map<Ref<Vacancy>, number> | undefined
type ApplicationInfo = { count: number, modifiedOn: number }
let applications: Map<Ref<Vacancy>, ApplicationInfo> | undefined
const applicantQuery = createQuery()
$: if (vacancies.length > 0) {
@ -73,10 +73,13 @@
recruit.class.Applicant,
{ ...(resultQuery as DocumentQuery<Applicant>), space: { $in: vacancies.map((it) => it._id) } },
(res) => {
const result = new Map<Ref<Vacancy>, number>()
const result = new Map<Ref<Vacancy>, ApplicationInfo>()
for (const d of res) {
result.set(d.space, (result.get(d.space) ?? 0) + 1)
const v = result.get(d.space) ?? { count: 0, modifiedOn: 0 }
v.count++
v.modifiedOn = Math.max(v.modifiedOn, d.modifiedOn)
result.set(d.space, v)
}
applications = result
@ -88,6 +91,8 @@
function showCreateDialog (ev: Event) {
showPopup(CreateVacancy, { space: recruit.space.CandidatesPublic }, ev.target as HTMLElement)
}
const applicationSorting = (a:Doc, b:Doc) => ((applications?.get(b._id as Ref<Vacancy>)?.count ?? 0) - (applications?.get(a._id as Ref<Vacancy>)?.count ?? 0)) ?? 0
const modifiedSorting = (a:Doc, b:Doc) => ((applications?.get(b._id as Ref<Vacancy>)?.modifiedOn ?? 0) - (applications?.get(a._id as Ref<Vacancy>)?.modifiedOn ?? 0)) ?? 0
</script>
<div class="ac-header full">
@ -118,12 +123,21 @@
key: '',
presenter: recruit.component.VacancyCountPresenter,
label: recruit.string.Applications,
props: { applications, resultQuery }
props: { applications, resultQuery },
sortingKey: '@applications',
sortingFunction: applicationSorting
},
'company',
'location',
'description',
'modifiedOn'
{
key: '',
presenter: recruit.component.VacancyModifiedPresenter,
label: core.string.Modified,
props: { applications },
sortingKey: 'modifiedOn',
sortingFunction: modifiedSorting
}
]}
options={{}}
query={{

View File

@ -21,14 +21,14 @@ import recruit from '../plugin'
import VacancyApplicationsPopup from './VacancyApplicationsPopup.svelte'
export let value: Vacancy
export let applications: Map<Ref<Vacancy>, number> | undefined
export let applications: Map<Ref<Vacancy>, {count: number, modifiedOn: number}> | undefined
export let resultQuery: DocumentQuery<Doc>
</script>
{#if (applications?.get(value._id) ?? 0) > 0}
{#if (applications?.get(value._id)?.count ?? 0) > 0}
<Tooltip label={recruit.string.Applications} component={VacancyApplicationsPopup} props={{ value: value._id, resultQuery }}>
<div class="sm-tool-icon">
<span class="icon"><Icon icon={recruit.icon.Application} size={'small'} /></span>&nbsp;{(applications?.get(value._id) ?? 0)}
<span class="icon"><Icon icon={recruit.icon.Application} size={'small'} /></span>&nbsp;{(applications?.get(value._id)?.count ?? 0)}
</div>
</Tooltip>
{/if}

View File

@ -0,0 +1,25 @@
<!--
// Copyright © 2022 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 { Ref } from '@anticrm/core'
import { Vacancy } from '@anticrm/recruit'
import { TimeSince } from '@anticrm/ui'
export let value: Vacancy
export let applications: Map<Ref<Vacancy>, {count: number, modifiedOn: number}> | undefined
</script>
<TimeSince value={Math.max(applications?.get(value._id)?.modifiedOn ?? 0, value.modifiedOn)}/>

View File

@ -47,6 +47,7 @@ import Vacancies from './components/Vacancies.svelte'
import VacancyItemPresenter from './components/VacancyItemPresenter.svelte'
import VacancyPresenter from './components/VacancyPresenter.svelte'
import VacancyCountPresenter from './components/VacancyCountPresenter.svelte'
import VacancyModifiedPresenter from './components/VacancyModifiedPresenter.svelte'
import recruit from './plugin'
import PersonsPresenter from './components/review/PersonsPresenter.svelte'
@ -155,6 +156,7 @@ export default async (): Promise<Resources> => ({
Vacancies,
VacancyItemPresenter,
VacancyCountPresenter,
VacancyModifiedPresenter,
CreateReviewCategory,
EditReviewCategory,

View File

@ -116,6 +116,7 @@ export default mergeIds(recruitId, recruit, {
VacancyItemPresenter: '' as AnyComponent,
VacancyCountPresenter: '' as AnyComponent,
OpinionsPresenter: '' as AnyComponent,
PersonsPresenter: '' as AnyComponent
PersonsPresenter: '' as AnyComponent,
VacancyModifiedPresenter: '' as AnyComponent
}
})

View File

@ -45,6 +45,8 @@
const q = createQuery()
$: sortingFunction = (config.find(it => (typeof it !== 'string') && it.sortingKey === sortKey) as BuildModelKey)?.sortingFunction
async function update (
_class: Ref<Class<Doc>>,
query: DocumentQuery<Doc>,
@ -58,6 +60,10 @@
query,
(result) => {
objects = result
if (sortingFunction !== undefined) {
const sf = sortingFunction
objects.sort((a, b) => -1 * sortOrder * sf(a, b))
}
loading = false
},
{ sort: { [sortKey]: sortOrder }, ...options, limit: 200 }

View File

@ -124,6 +124,9 @@ export interface BuildModelKey {
label?: IntlString
sortingKey?: string
// On client sorting function
sortingFunction?: (a: Doc, b: Doc) => number
}
/**