diff --git a/models/tags/src/index.ts b/models/tags/src/index.ts index 5817516760..555ace1050 100644 --- a/models/tags/src/index.ts +++ b/models/tags/src/index.ts @@ -17,7 +17,14 @@ import { ArrOf, Builder, Index, Model, Prop, TypeNumber, TypeRef, TypeString, UX import core, { TAttachedDoc, TDoc } from '@hcengineering/model-core' import view from '@hcengineering/model-view' import { Asset, IntlString } from '@hcengineering/platform' -import type { TagCategory, TagElement, TagReference } from '@hcengineering/tags' +import type { + ExpertKnowledge, + InitialKnowledge, + MeaningfullKnowledge, + TagCategory, + TagElement, + TagReference +} from '@hcengineering/tags' import tags from './plugin' export { TagCategory, TagElement, TagReference } from '@hcengineering/tags' @@ -63,6 +70,9 @@ export class TTagReference extends TAttachedDoc implements TagReference { @Prop(TypeString(), tags.string.ColorLabel) color!: number + + @Prop(TypeNumber(), tags.string.Weight) + weight!: InitialKnowledge | MeaningfullKnowledge | ExpertKnowledge } @Model(tags.class.TagCategory, core.class.Doc, DOMAIN_TAGS) diff --git a/plugins/recruit-resources/src/components/Applications.svelte b/plugins/recruit-resources/src/components/Applications.svelte index 0a16680f94..5c8d312002 100644 --- a/plugins/recruit-resources/src/components/Applications.svelte +++ b/plugins/recruit-resources/src/components/Applications.svelte @@ -34,8 +34,7 @@ const config: (BuildModelKey | string)[] = [ '', '$lookup.space.name', - 'comments', - 'attachments', + '$lookup.space.$lookup.company', '$lookup.state', '$lookup.doneState' ] diff --git a/plugins/recruit-resources/src/components/CreateCandidate.svelte b/plugins/recruit-resources/src/components/CreateCandidate.svelte index 7d019b970d..21affd35c3 100644 --- a/plugins/recruit-resources/src/components/CreateCandidate.svelte +++ b/plugins/recruit-resources/src/components/CreateCandidate.svelte @@ -197,7 +197,8 @@ await client.addCollection(skill._class, skill.space, candidateId, recruit.mixin.Candidate, 'skills', { title: skill.title, color: skill.color, - tag: skill.tag + tag: skill.tag, + weight: skill.weight }) } @@ -404,7 +405,7 @@ 0 && lastName.length > 0} + canSave={!loading && (firstName.length > 0 || lastName.length > 0 || channels.length > 0)} on:close={() => { dispatch('close') }} @@ -470,47 +471,80 @@ - it.provider)} - /> - - - { - addTagRef(evt.detail) - }} - on:delete={(evt) => { - skills = skills.filter((it) => it._id !== evt.detail) - }} - /> +
+
+ it.provider)} + /> + + + { + addTagRef(evt.detail) + }} + on:delete={(evt) => { + skills = skills.filter((it) => it._id !== evt.detail) + }} + /> +
+ {#if skills.length > 0} +
+ { + addTagRef(evt.detail) + }} + on:delete={(evt) => { + skills = skills.filter((it) => it._id !== evt.detail) + }} + on:change={(evt) => { + evt.detail.tag.weight = evt.detail.weight + skills = skills + }} + /> +
+ {/if} +
+
diff --git a/plugins/tags-assets/assets/icons.svg b/plugins/tags-assets/assets/icons.svg index c00325b710..0cb9b6c64b 100644 --- a/plugins/tags-assets/assets/icons.svg +++ b/plugins/tags-assets/assets/icons.svg @@ -2,4 +2,19 @@ + + + + + + + + + + + + + + + diff --git a/plugins/tags-assets/lang/en.json b/plugins/tags-assets/lang/en.json index 9e93e39e1c..1a6e41b7d5 100644 --- a/plugins/tags-assets/lang/en.json +++ b/plugins/tags-assets/lang/en.json @@ -33,6 +33,10 @@ "DefaultLabel": "Default category", "SelectAll": "Select all", "SelectNone": "Select none", - "ApplyTags": "Apply" + "ApplyTags": "Apply", + "Weight": "Weight", + "Expert": "Expert", + "Meaningfull": "Meaningfull", + "Initial": "Initial" } } \ No newline at end of file diff --git a/plugins/tags-assets/lang/ru.json b/plugins/tags-assets/lang/ru.json index 84b6b73b63..9f5b2e8fea 100644 --- a/plugins/tags-assets/lang/ru.json +++ b/plugins/tags-assets/lang/ru.json @@ -33,6 +33,10 @@ "DefaultLabel": "Категория по умолчанию", "SelectAll": "Выбрать все", "SelectNone": "Выбрать ничего", - "ApplyTags": "Применить" + "ApplyTags": "Применить", + "Weight": "Вес", + "Expert": "Эксперт", + "Meaningfull": "Значимый", + "Initial": "Начальный" } } \ No newline at end of file diff --git a/plugins/tags-assets/src/index.ts b/plugins/tags-assets/src/index.ts index 7d72d2467b..77044d6741 100644 --- a/plugins/tags-assets/src/index.ts +++ b/plugins/tags-assets/src/index.ts @@ -19,7 +19,10 @@ import tags, { tagsId } from '@hcengineering/tags' const icons = require('../assets/icons.svg') as string // eslint-disable-line loadMetadata(tags.icon, { - Tags: `${icons}#tags` + Tags: `${icons}#tags`, + Level1: `${icons}#level-1`, + Level2: `${icons}#level-2`, + Level3: `${icons}#level-3` }) addStringsLoader(tagsId, async (lang: string) => await import(`../lang/${lang}.json`)) diff --git a/plugins/tags-resources/src/components/TagItem.svelte b/plugins/tags-resources/src/components/TagItem.svelte index 4af76c96fe..380481db94 100644 --- a/plugins/tags-resources/src/components/TagItem.svelte +++ b/plugins/tags-resources/src/components/TagItem.svelte @@ -15,10 +15,10 @@
{name} + + {#if tag} + + {/if} + {#if action}
{ dispatch('action') }} @@ -61,7 +70,7 @@ border-radius: 0.25rem; font-weight: 500; - font-size: 0.625rem; + font-size: 0.75rem; text-transform: uppercase; color: var(--accent-color); diff --git a/plugins/tags-resources/src/components/TagReferencePresenter.svelte b/plugins/tags-resources/src/components/TagReferencePresenter.svelte index 6802e31d54..c0b515f9fd 100644 --- a/plugins/tags-resources/src/components/TagReferencePresenter.svelte +++ b/plugins/tags-resources/src/components/TagReferencePresenter.svelte @@ -14,9 +14,10 @@ --> {#if value} @@ -48,7 +50,10 @@ }} >
- {value.title} + {value.title}- + + {#if isEditable}
@@ -169,7 +200,9 @@ shape={'round'} label={view.string.Apply} on:click={async () => { - filter.value = selected + filter.value = [...selected] + // Replace last one with value with level + filter.props = { level } onChange(filter) dispatch('close') }} diff --git a/plugins/tags-resources/src/components/TagsPopup.svelte b/plugins/tags-resources/src/components/TagsPopup.svelte index 81e6fcdb8d..13b750d862 100644 --- a/plugins/tags-resources/src/components/TagsPopup.svelte +++ b/plugins/tags-resources/src/components/TagsPopup.svelte @@ -123,6 +123,7 @@ />
+
> @@ -39,13 +40,32 @@ (res) => { items = res }, - { sort: { title: 1 } } + { sort: { weight: -1, title: 1 } } ) + + $: expert = items.filter((it) => (it.weight ?? 0) >= 6 && (it.weight ?? 0) <= 8) + $: meaningfull = items.filter((it) => (it.weight ?? 0) >= 3 && (it.weight ?? 0) <= 5) + $: initial = items.filter((it) => (it.weight ?? 1) >= 0 && (it.weight ?? 0) <= 2) + + $: categories = [ + { items: expert, label: tags.string.Expert }, + { items: meaningfull, label: tags.string.Meaningfull }, + { items: initial, label: tags.string.Initial } + ] -
- {#each items as tag} - +
+ {#each categories as cat, ci} + {#if cat.items.length > 0} +
0 && categories[ci - 1].items.length > 0}> +
+ {/if} +
+ {#each cat.items as tag} + + {/each} +
{/each}
diff --git a/plugins/tags-resources/src/components/WeightPopup.svelte b/plugins/tags-resources/src/components/WeightPopup.svelte new file mode 100644 index 0000000000..9ed6962c36 --- /dev/null +++ b/plugins/tags-resources/src/components/WeightPopup.svelte @@ -0,0 +1,47 @@ + + + +
dispatch('changeContent')}> +
+ {#each labels as l, i} +
+ {#each Object.entries(tagLevel) as k, j} + {@const valueK = i * 3 + j} +
+ {/each} +
+
diff --git a/plugins/tags-resources/src/plugin.ts b/plugins/tags-resources/src/plugin.ts index f4078f984a..572dd0b8b0 100644 --- a/plugins/tags-resources/src/plugin.ts +++ b/plugins/tags-resources/src/plugin.ts @@ -46,7 +46,12 @@ export default mergeIds(tagsId, tags, { AllCategories: '' as IntlString, SelectAll: '' as IntlString, SelectNone: '' as IntlString, - ApplyTags: '' as IntlString + ApplyTags: '' as IntlString, + + Weight: '' as IntlString, + Expert: '' as IntlString, + Meaningfull: '' as IntlString, + Initial: '' as IntlString }, function: { FilterTagsInResult: '' as Resource<(filter: Filter, onUpdate: () => void) => Promise>>, diff --git a/plugins/tags-resources/src/utils.ts b/plugins/tags-resources/src/utils.ts index d34c193584..455ad48481 100644 --- a/plugins/tags-resources/src/utils.ts +++ b/plugins/tags-resources/src/utils.ts @@ -1,10 +1,11 @@ // Copyright © 2022 Hardcore Engineering Inc. -import { Doc, FindResult, Ref } from '@hcengineering/core' -import { TagReference } from '@hcengineering/tags' -import tags from './plugin' -import { FilterQuery } from '@hcengineering/view-resources' +import { Doc, DocumentQuery, FindResult, Ref } from '@hcengineering/core' +import { Asset } from '@hcengineering/platform' +import { InitialKnowledge, TagReference } from '@hcengineering/tags' import { Filter } from '@hcengineering/view' +import { FilterQuery } from '@hcengineering/view-resources' +import tags from './plugin' export function getTagStyle (color: string, selected = false): string { return ` @@ -16,21 +17,29 @@ export function getTagStyle (color: string, selected = false): string { export async function getRefs (filter: Filter, onUpdate: () => void): Promise>> { const lq = FilterQuery.getLiveQuery(filter.index) const promise = new Promise>>((resolve, reject) => { - const refresh = lq.query( - tags.class.TagReference, - { - tag: { $in: filter.value } - }, - (refs: FindResult) => { - const result = Array.from(new Set(refs.map((p) => p.attachedTo))) - FilterQuery.results.set(filter.index, result) - resolve(result) - onUpdate() - } - ) + const level = filter.props?.level ?? 0 + const q: DocumentQuery = { + tag: { $in: filter.value }, + weight: + level === 0 + ? { $in: [null as unknown as InitialKnowledge, 0, 1, 2, 3, 4, 5, 6, 7, 8] } + : { $gte: level as TagReference['weight'] } + } + const refresh = lq.query(tags.class.TagReference, q, (refs: FindResult) => { + const result = Array.from(new Set(refs.map((p) => p.attachedTo))) + FilterQuery.results.set(filter.index, result) + resolve(result) + onUpdate() + }) if (!refresh) { resolve(FilterQuery.results.get(filter.index) ?? []) } }) return await promise } + +export const tagLevel: Record<1 | 2 | 3, Asset> = { + 3: tags.icon.Level3, + 2: tags.icon.Level2, + 1: tags.icon.Level1 +} diff --git a/plugins/tags/src/index.ts b/plugins/tags/src/index.ts index 65cbcdca7e..0144852664 100644 --- a/plugins/tags/src/index.ts +++ b/plugins/tags/src/index.ts @@ -32,6 +32,21 @@ export interface TagElement extends Doc { refCount?: number } +/** + * @public + */ +export type InitialKnowledge = 0 | 1 | 2 + +/** + * @public + */ +export type MeaningfullKnowledge = 3 | 4 | 5 + +/** + * @public + */ +export type ExpertKnowledge = 6 | 7 | 8 + /** * @public */ @@ -39,6 +54,9 @@ export interface TagReference extends AttachedDoc { tag: Ref title: string // Copy of title for full text search, updated with trigger. color: number // Copy of color from tagElement. Updated with trigger. + + // If set in [8-10] it is speciality, [5-7] - meaningfull, [1-4] - initial + weight?: InitialKnowledge | MeaningfullKnowledge | ExpertKnowledge } /** @@ -76,7 +94,10 @@ const tagsPlugin = plugin(tagsId, { Tags: '' as Ref }, icon: { - Tags: '' as Asset + Tags: '' as Asset, + Level1: '' as Asset, + Level2: '' as Asset, + Level3: '' as Asset }, component: { TagsView: '' as AnyComponent, diff --git a/plugins/task-resources/src/components/state/DoneStatePresenter.svelte b/plugins/task-resources/src/components/state/DoneStatePresenter.svelte index 1c373b6920..715bd35e6c 100644 --- a/plugins/task-resources/src/components/state/DoneStatePresenter.svelte +++ b/plugins/task-resources/src/components/state/DoneStatePresenter.svelte @@ -21,7 +21,7 @@ import Lost from '../icons/Lost.svelte' export let value: DoneState - export let showTitle: boolean = false + export let showTitle: boolean = true $: color = value._class === task.class.WonState ? getPlatformColor(0) : getPlatformColor(11) diff --git a/plugins/view-resources/src/components/TableBrowser.svelte b/plugins/view-resources/src/components/TableBrowser.svelte index 81f9a8a111..97a3d7dbd9 100644 --- a/plugins/view-resources/src/components/TableBrowser.svelte +++ b/plugins/view-resources/src/components/TableBrowser.svelte @@ -47,11 +47,9 @@ onMount(() => { ;(document.activeElement as HTMLElement)?.blur() }) - - let docWidth: number - + (resultQuery = e.detail)} /> {/if} - + modes: Ref[] value: any[] + props?: Record index: number onRemove?: () => void }