mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-26 13:47:26 +03:00
Vacancies sorting (#1143)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
728216c936
commit
36ddf8477a
@ -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={{
|
||||
|
@ -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> {(applications?.get(value._id) ?? 0)}
|
||||
<span class="icon"><Icon icon={recruit.icon.Application} size={'small'} /></span> {(applications?.get(value._id)?.count ?? 0)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
{/if}
|
@ -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)}/>
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
})
|
||||
|
@ -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 }
|
||||
|
@ -124,6 +124,9 @@ export interface BuildModelKey {
|
||||
|
||||
label?: IntlString
|
||||
sortingKey?: string
|
||||
|
||||
// On client sorting function
|
||||
sortingFunction?: (a: Doc, b: Doc) => number
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user