mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-23 16:56:07 +00:00
Update TagEditor layout (#1420)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
5dee8d9072
commit
f0cca26e9b
@ -15,6 +15,6 @@
|
|||||||
"Search": "Search...",
|
"Search": "Search...",
|
||||||
"Unassigned": "Unassigned",
|
"Unassigned": "Unassigned",
|
||||||
"CreateMore": "Create more",
|
"CreateMore": "Create more",
|
||||||
"NumberMembers": "{lenght, plural, =0 {no members} =1 {1 member} other {# members}}"
|
"NumberMembers": "{count, plural, =0 {no members} =1 {1 member} other {# members}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,6 @@
|
|||||||
"Search": "Поиск...",
|
"Search": "Поиск...",
|
||||||
"Unassigned": "Не назначен",
|
"Unassigned": "Не назначен",
|
||||||
"CreateMore": "Создать еще",
|
"CreateMore": "Создать еще",
|
||||||
"NumberMembers": "{lenght, plural, =0 {нет участников} =1 {1 участик} other {# участника}}"
|
"NumberMembers": "{count, plural, =0 {нет участников} =1 {1 участик} other {# участника}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@
|
|||||||
{#if persons.length > 0}
|
{#if persons.length > 0}
|
||||||
<div class="flex-row-center flex-nowrap">
|
<div class="flex-row-center flex-nowrap">
|
||||||
<CombineAvatars {_class} bind:items size={'inline'} />
|
<CombineAvatars {_class} bind:items size={'inline'} />
|
||||||
{#await translate(presentation.string.NumberMembers, { lenght: persons.length }) then text}
|
{#await translate(presentation.string.NumberMembers, { count: persons.length }) then text}
|
||||||
<span class="ml-1-5">{text}</span>
|
<span class="ml-1-5">{text}</span>
|
||||||
{/await}
|
{/await}
|
||||||
</div>
|
</div>
|
||||||
|
@ -296,6 +296,7 @@ p:last-child { margin-block-end: 0; }
|
|||||||
.ml-12 { margin-left: 3rem; }
|
.ml-12 { margin-left: 3rem; }
|
||||||
.ml-22 { margin-left: 5.5rem; }
|
.ml-22 { margin-left: 5.5rem; }
|
||||||
.mr-1 { margin-right: .25rem; }
|
.mr-1 { margin-right: .25rem; }
|
||||||
|
.mr-1-5 { margin-right: .375rem; }
|
||||||
.mr-2 { margin-right: .5rem; }
|
.mr-2 { margin-right: .5rem; }
|
||||||
.mr-3 { margin-right: .75rem; }
|
.mr-3 { margin-right: .75rem; }
|
||||||
.mr-4 { margin-right: 1rem; }
|
.mr-4 { margin-right: 1rem; }
|
||||||
@ -461,6 +462,7 @@ a.no-line {
|
|||||||
color: var(--theme-content-trans-color);
|
color: var(--theme-content-trans-color);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
.text-xs { font-size: .625rem; }
|
||||||
.text-sm { font-size: .75rem; }
|
.text-sm { font-size: .75rem; }
|
||||||
.text-md { font-size: .8125rem; }
|
.text-md { font-size: .8125rem; }
|
||||||
.text-lg { font-size: 1.125rem; }
|
.text-lg { font-size: 1.125rem; }
|
||||||
|
@ -18,18 +18,20 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: min-content;
|
width: fit-content;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
max-width: 45rem;
|
max-width: 15rem;
|
||||||
max-height: 20rem;
|
max-height: 22rem;
|
||||||
background: var(--popup-bg-color);
|
background: var(--popup-bg-color);
|
||||||
border-radius: .5rem;
|
border-radius: .5rem;
|
||||||
box-shadow: var(--popup-shadow);
|
box-shadow: var(--popup-shadow);
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
|
|
||||||
|
&.maxHeight { height: 22rem; }
|
||||||
.header {
|
.header {
|
||||||
border-bottom: 1px solid var(--popup-divider);
|
border-bottom: 1px solid var(--popup-divider);
|
||||||
|
|
||||||
|
&.no-border { border-bottom-color: transparent; }
|
||||||
input {
|
input {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: .625rem .75rem;
|
padding: .625rem .75rem;
|
||||||
@ -59,25 +61,33 @@
|
|||||||
.menu-item {
|
.menu-item {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
padding: 0 .75rem;
|
padding: .25rem .75rem;
|
||||||
height: 2rem;
|
min-height: 2rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: var(--caption-color);
|
color: var(--caption-color);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&.high { height: 3rem; }
|
&.high { height: 3rem; }
|
||||||
.icon {
|
|
||||||
|
.icon, .color, .tag {
|
||||||
|
flex-shrink: 0;
|
||||||
margin-right: .75rem;
|
margin-right: .75rem;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
}
|
}
|
||||||
.color {
|
.color {
|
||||||
margin-right: .75rem;
|
|
||||||
width: .875rem;
|
width: .875rem;
|
||||||
height: .875rem;
|
height: .875rem;
|
||||||
border: 1px solid rgba(0, 0, 0, .1);
|
border: 1px solid rgba(0, 0, 0, .1);
|
||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
}
|
}
|
||||||
|
.tag {
|
||||||
|
width: .5rem;
|
||||||
|
height: .5rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
.label {
|
.label {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@ -89,11 +99,50 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-right: .75rem;
|
margin-right: .75rem;
|
||||||
height: 2rem;
|
|
||||||
}
|
}
|
||||||
.check-right { margin: 0 0 0 2rem; }
|
.check-right { margin: 0 0 0 2rem; }
|
||||||
&:hover { background-color: var(--popup-bg-hover); }
|
&:hover { background-color: var(--popup-bg-hover); }
|
||||||
}
|
}
|
||||||
|
.sticky-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&:not(:first-child) { margin-top: 1px; }
|
||||||
|
}
|
||||||
|
.menu-group {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 0;
|
||||||
|
transition: height .5s ease;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: .125rem .25rem;
|
||||||
|
min-height: 1.5rem;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: .75rem;
|
||||||
|
text-align: left;
|
||||||
|
color: var(--accent-color);
|
||||||
|
background-color: var(--button-bg-color);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: .25rem;
|
||||||
|
transform-origin: 40% 50%;
|
||||||
|
transform: rotate(0deg);
|
||||||
|
transition: transform .15s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
}
|
||||||
|
&.show .icon { transform: rotate(90deg); }
|
||||||
|
&:hover { color: var(--caption-color); }
|
||||||
|
&.show + .menu-group { height: auto; }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.antiPopup {
|
.antiPopup {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import { AnySvelteComponent } from '../types'
|
import { AnySvelteComponent } from '../types'
|
||||||
|
|
||||||
export let icon: Asset | AnySvelteComponent
|
export let icon: Asset | AnySvelteComponent
|
||||||
export let size: 'x-small' | 'small' | 'medium' | 'large' | 'full'
|
export let size: 'inline' | 'x-small' | 'small' | 'medium' | 'large' | 'full'
|
||||||
export let fill = 'currentColor'
|
export let fill = 'currentColor'
|
||||||
export let filled: boolean = false
|
export let filled: boolean = false
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
let modalHTML: HTMLElement
|
let modalHTML: HTMLElement
|
||||||
let componentInstance: any
|
let componentInstance: any
|
||||||
let show: boolean = false
|
let show: boolean = false
|
||||||
|
let height: number
|
||||||
|
|
||||||
function _update (result: any): void {
|
function _update (result: any): void {
|
||||||
if (onUpdate !== undefined) onUpdate(result)
|
if (onUpdate !== undefined) onUpdate(result)
|
||||||
@ -61,11 +62,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
afterUpdate(() => fitPopup())
|
afterUpdate(() => fitPopup())
|
||||||
|
$: if (height) fitPopup()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window on:resize={fitPopup} on:keydown={handleKeydown} />
|
<svelte:window on:resize={fitPopup} on:keydown={handleKeydown} />
|
||||||
|
|
||||||
<div class="popup" bind:this={modalHTML} style={`z-index: ${zIndex + 1};`}>
|
<div class="popup" bind:this={modalHTML} bind:clientHeight={height} style={`z-index: ${zIndex + 1};`}>
|
||||||
<svelte:component bind:this={componentInstance} this={is} {...props} on:update={(ev) => _update(ev.detail)} on:close={(ev) => _close(ev.detail)} />
|
<svelte:component bind:this={componentInstance} this={is} {...props} on:update={(ev) => _update(ev.detail)} on:close={(ev) => _close(ev.detail)} />
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-overlay" class:antiOverlay={show} style={`z-index: ${zIndex};`} on:click={() => escapeClose()} />
|
<div class="modal-overlay" class:antiOverlay={show} style={`z-index: ${zIndex};`} on:click={() => escapeClose()} />
|
||||||
|
@ -86,7 +86,8 @@
|
|||||||
"Participants": "Participants",
|
"Participants": "Participants",
|
||||||
"NoParticipants": "No participants added",
|
"NoParticipants": "No participants added",
|
||||||
"PersonsLabel": "{name}",
|
"PersonsLabel": "{name}",
|
||||||
"AddDescription": "Add description"
|
"AddDescription": "Add description",
|
||||||
|
"NumberSkills": "{count, plural, =0 {no skills} =1 {1 skill} other {# skills}}"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"CandidateRequired": "Please select candidate",
|
"CandidateRequired": "Please select candidate",
|
||||||
|
@ -87,7 +87,8 @@
|
|||||||
"Participants": "Участники",
|
"Participants": "Участники",
|
||||||
"NoParticipants": "Участники не добавлены",
|
"NoParticipants": "Участники не добавлены",
|
||||||
"PersonsLabel": "{name}",
|
"PersonsLabel": "{name}",
|
||||||
"AddDescription": "Add description"
|
"AddDescription": "Add description",
|
||||||
|
"NumberSkills": "{count, plural, =0 {нет навыков} =1 {1 навык} =2 {2 навыка} other {# навыков}}"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"CandidateRequired": "Пожалуйста выберите кандидата",
|
"CandidateRequired": "Пожалуйста выберите кандидата",
|
||||||
|
@ -231,22 +231,22 @@
|
|||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.card {
|
// .card {
|
||||||
align-self: stretch;
|
// align-self: stretch;
|
||||||
width: calc(50% - 3rem);
|
// width: calc(50% - 3rem);
|
||||||
min-height: 16rem;
|
// min-height: 16rem;
|
||||||
|
|
||||||
&.empty {
|
// &.empty {
|
||||||
display: flex;
|
// display: flex;
|
||||||
justify-content: center;
|
// justify-content: center;
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
font-size: .75rem;
|
// font-size: .75rem;
|
||||||
color: var(--dark-color);
|
// color: var(--dark-color);
|
||||||
border: 1px solid var(--divider-color);
|
// border: 1px solid var(--divider-color);
|
||||||
border-radius: .25rem;
|
// border-radius: .25rem;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
.arrows { width: 4rem; }
|
// .arrows { width: 4rem; }
|
||||||
.color {
|
.color {
|
||||||
margin-right: .375rem;
|
margin-right: .375rem;
|
||||||
width: .875rem;
|
width: .875rem;
|
||||||
|
@ -415,12 +415,19 @@
|
|||||||
{#if channels.length > 0}
|
{#if channels.length > 0}
|
||||||
<div class="ml-22"><ChannelsView value={channels} size={'small'} on:click /></div>
|
<div class="ml-22"><ChannelsView value={channels} size={'small'} on:click /></div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="flex-col">
|
<svelte:fragment slot="pool">
|
||||||
<span class="text-sm fs-bold content-accent-color"><Label label={recruit.string.SkillsLabel} /></span>
|
<YesNo label={recruit.string.Onsite} tooltip={recruit.string.WorkLocationPreferences} bind:value={object.onsite} />
|
||||||
<div class="flex-grow">
|
<YesNo label={recruit.string.Remote} tooltip={recruit.string.WorkLocationPreferences} bind:value={object.remote} />
|
||||||
<Component
|
<Component
|
||||||
is={tags.component.TagsEditor}
|
is={tags.component.TagsEditor}
|
||||||
props={{ items: skills, key, targetClass: recruit.mixin.Candidate, showTitle: false, elements }}
|
props={{
|
||||||
|
items: skills,
|
||||||
|
key,
|
||||||
|
targetClass: recruit.mixin.Candidate,
|
||||||
|
showTitle: false,
|
||||||
|
elements,
|
||||||
|
countLabel: recruit.string.NumberSkills
|
||||||
|
}}
|
||||||
on:open={(evt) => {
|
on:open={(evt) => {
|
||||||
addTagRef(evt.detail)
|
addTagRef(evt.detail)
|
||||||
}}
|
}}
|
||||||
@ -428,16 +435,6 @@
|
|||||||
skills = skills.filter((it) => it._id !== evt.detail)
|
skills = skills.filter((it) => it._id !== evt.detail)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<svelte:fragment slot="pool">
|
|
||||||
<div class="flex-between w-full">
|
|
||||||
<span class="ml-2 content-color overflow-label"><Label label={recruit.string.WorkLocationPreferences} /></span>
|
|
||||||
<div class="buttons-group small-gap">
|
|
||||||
<YesNo label={recruit.string.Onsite} bind:value={object.onsite} />
|
|
||||||
<YesNo label={recruit.string.Remote} bind:value={object.remote} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="footer">
|
<svelte:fragment slot="footer">
|
||||||
<Button
|
<Button
|
||||||
|
@ -15,19 +15,23 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { IntlString } from '@anticrm/platform'
|
import type { IntlString } from '@anticrm/platform'
|
||||||
import { Label } from '@anticrm/ui'
|
import type { TooltipAlignment } from '@anticrm/ui'
|
||||||
|
import { Label, Tooltip } from '@anticrm/ui'
|
||||||
import recruit from '../plugin'
|
import recruit from '../plugin'
|
||||||
|
|
||||||
export let label: IntlString
|
export let label: IntlString
|
||||||
|
export let tooltip: IntlString
|
||||||
export let value: boolean | undefined
|
export let value: boolean | undefined
|
||||||
export let disabled: boolean = false
|
export let disabled: boolean = false
|
||||||
|
export let labelDirection: TooltipAlignment | undefined = undefined
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button class="yesno-container" {disabled} class:yes={value === true} class:no={value === false} on:click={() => {
|
<Tooltip direction={labelDirection} label={tooltip}>
|
||||||
|
<button class="yesno-container" {disabled} class:yes={value === true} class:no={value === false} on:click={() => {
|
||||||
if (value === true) value = false
|
if (value === true) value = false
|
||||||
else if (value === false) value = undefined
|
else if (value === false) value = undefined
|
||||||
else value = true
|
else value = true
|
||||||
}}>
|
}}>
|
||||||
<span class="overflow-label">
|
<span class="overflow-label">
|
||||||
<Label {label} />
|
<Label {label} />
|
||||||
</span>
|
</span>
|
||||||
@ -43,7 +47,8 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.yesno-container {
|
.yesno-container {
|
||||||
|
@ -102,7 +102,8 @@ export default mergeIds(recruitId, recruit, {
|
|||||||
StartDate: '' as IntlString,
|
StartDate: '' as IntlString,
|
||||||
DueDate: '' as IntlString,
|
DueDate: '' as IntlString,
|
||||||
CandidateReviews: '' as IntlString,
|
CandidateReviews: '' as IntlString,
|
||||||
AddDescription: '' as IntlString
|
AddDescription: '' as IntlString,
|
||||||
|
NumberSkills: '' as IntlString
|
||||||
},
|
},
|
||||||
space: {
|
space: {
|
||||||
CandidatesPublic: '' as Ref<Space>
|
CandidatesPublic: '' as Ref<Space>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
import { Class, Doc, Ref, SortingOrder } from '@anticrm/core'
|
import { Class, Doc, Ref, SortingOrder } from '@anticrm/core'
|
||||||
import { createQuery } from '@anticrm/presentation'
|
import { createQuery } from '@anticrm/presentation'
|
||||||
import { TagCategory, TagElement } from '@anticrm/tags'
|
import { TagCategory, TagElement } from '@anticrm/tags'
|
||||||
import { getPlatformColorForText, Label } from '@anticrm/ui'
|
import { getPlatformColorForText, Button } from '@anticrm/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import tags from '../plugin'
|
import tags from '../plugin'
|
||||||
import { getTagStyle } from '../utils'
|
import { getTagStyle } from '../utils'
|
||||||
@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
$: visibleCategories = categories.filter((it) => categoryKeys.includes(it._id))
|
$: visibleCategories = categories.filter((it) => categoryKeys.includes(it._id))
|
||||||
|
|
||||||
const selectItem = (ev: Event, item: TagCategory): void => {
|
const selectItem = (item: TagCategory): void => {
|
||||||
if (category === item._id) {
|
if (category === item._id) {
|
||||||
category = undefined
|
category = undefined
|
||||||
} else {
|
} else {
|
||||||
@ -87,28 +87,27 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if visibleCategories.length > 0}
|
{#if visibleCategories.length > 0}
|
||||||
<div class="flex-between mb-4 header">
|
<div class="flex-between header">
|
||||||
<div class="flex-row-center buttons">
|
<div class="flex-row-center buttons">
|
||||||
<div
|
<Button
|
||||||
class="button flex-center"
|
label={tags.string.AllCategories}
|
||||||
class:active={category === undefined}
|
kind={'transparent'}
|
||||||
|
size={'large'}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
category = undefined
|
category = undefined
|
||||||
dispatch('change', { category, elements: [] })
|
dispatch('change', { category, elements: [] })
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
<Label label={tags.string.AllCategories} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-row-center caption-color states">
|
<div class="flex-row-center caption-color states">
|
||||||
<div class="antiStatesBar mask-none {stepStyle}">
|
<div class="antiStatesBar mask-none {stepStyle}">
|
||||||
{#each visibleCategories as item, i (item._id)}
|
{#each visibleCategories as item (item._id)}
|
||||||
<div
|
<div
|
||||||
class="categoryElement flex-center"
|
class="categoryElement flex-center"
|
||||||
label={item.label}
|
label={item.label}
|
||||||
style={getTagStyle(getPlatformColorForText(item.label), item._id === category)}
|
style={getTagStyle(getPlatformColorForText(item.label), item._id === category)}
|
||||||
on:click={(ev) => {
|
on:click={() => {
|
||||||
if (item._id !== category) selectItem(ev, item)
|
if (item._id !== category) selectItem(item)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.label} ({categoryCounts.get(item._id)?.length ?? ''})
|
{item.label} ({categoryCounts.get(item._id)?.length ?? ''})
|
||||||
@ -121,20 +120,20 @@
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.categoryElement {
|
.categoryElement {
|
||||||
padding: 0.5rem 0.75rem;
|
padding: .375rem .75rem;
|
||||||
height: 2.5rem;
|
// height: 2.5rem;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
border: 1px solid var(--theme-button-border-enabled);
|
border: 1px solid var(--theme-button-border-enabled);
|
||||||
border-radius: 0.5rem;
|
border-radius: .25rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.categoryElement + .categoryElement {
|
.categoryElement + .categoryElement {
|
||||||
margin-left: 0.75rem;
|
margin-left: .125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
margin-left: 2.5rem;
|
padding: 0 1.75rem 1rem 2.5rem;
|
||||||
margin-right: 1.75rem;
|
border-bottom: 1px solid var(--divider-color);
|
||||||
.buttons {
|
.buttons {
|
||||||
padding: 0.125rem 0;
|
padding: 0.125rem 0;
|
||||||
}
|
}
|
||||||
|
@ -56,16 +56,17 @@
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.tag-item {
|
.tag-item {
|
||||||
margin: .25rem;
|
margin: .125rem;
|
||||||
padding: .5rem;
|
padding: .125rem .25rem;
|
||||||
|
|
||||||
border-radius: .5rem;
|
border-radius: .25rem;
|
||||||
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: .625rem;
|
font-size: .625rem;
|
||||||
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--theme-caption-color);
|
color: var(--accent-color);
|
||||||
|
&:hover { color: var(--caption-color); }
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -63,4 +63,5 @@
|
|||||||
targetClass={_class}
|
targetClass={_class}
|
||||||
on:open={(evt) => addRef(evt.detail)}
|
on:open={(evt) => addRef(evt.detail)}
|
||||||
on:delete={(evt) => removeTag(evt.detail)}
|
on:delete={(evt) => removeTag(evt.detail)}
|
||||||
|
countLabel={key.attr.label}
|
||||||
/>
|
/>
|
||||||
|
@ -14,13 +14,13 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { AttachedDoc, Class, Collection, Doc, Ref } from '@anticrm/core'
|
import type { AttachedDoc, Class, Collection, Doc, Ref } from '@anticrm/core'
|
||||||
import { translate } from '@anticrm/platform'
|
import { IntlString, translate } from '@anticrm/platform'
|
||||||
import { KeyedAttribute } from '@anticrm/presentation'
|
import { KeyedAttribute } from '@anticrm/presentation'
|
||||||
import { TagElement, TagReference } from '@anticrm/tags'
|
import { TagElement, TagReference } from '@anticrm/tags'
|
||||||
import { CircleButton, IconAdd, IconClose, Label, ShowMore, showPopup, Tooltip } from '@anticrm/ui'
|
import type { ButtonKind, ButtonSize, TooltipAlignment } from '@anticrm/ui'
|
||||||
|
import { Button, showPopup, Tooltip } from '@anticrm/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import tags from '../plugin'
|
import tags from '../plugin'
|
||||||
import TagItem from './TagItem.svelte'
|
|
||||||
import TagsPopup from './TagsPopup.svelte'
|
import TagsPopup from './TagsPopup.svelte'
|
||||||
|
|
||||||
export let items: TagReference[] = []
|
export let items: TagReference[] = []
|
||||||
@ -28,6 +28,13 @@
|
|||||||
export let key: KeyedAttribute
|
export let key: KeyedAttribute
|
||||||
export let showTitle = true
|
export let showTitle = true
|
||||||
export let elements: Map<Ref<TagElement>, TagElement>
|
export let elements: Map<Ref<TagElement>, TagElement>
|
||||||
|
export let countLabel: IntlString
|
||||||
|
|
||||||
|
export let kind: ButtonKind = 'no-border'
|
||||||
|
export let size: ButtonSize = 'small'
|
||||||
|
export let justify: 'left' | 'center' = 'center'
|
||||||
|
export let width: string | undefined = undefined
|
||||||
|
export let labelDirection: TooltipAlignment | undefined = undefined
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@ -47,17 +54,12 @@
|
|||||||
TagsPopup,
|
TagsPopup,
|
||||||
{
|
{
|
||||||
targetClass,
|
targetClass,
|
||||||
title: keyLabel,
|
|
||||||
addRef,
|
addRef,
|
||||||
selected: items.map((it) => it.tag)
|
removeTag,
|
||||||
|
selected: items.map((it) => it.tag),
|
||||||
|
keyLabel
|
||||||
},
|
},
|
||||||
evt.target as HTMLElement,
|
evt.target as HTMLElement
|
||||||
async (result?: TagElement) => {
|
|
||||||
if (result === null || result === undefined) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
addRef(result)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,70 +68,22 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex-row">
|
<Tooltip label={key.attr.label} direction={labelDirection}>
|
||||||
{#if showTitle}
|
<Button
|
||||||
<div class="flex-row-center">
|
icon={tags.icon.Tags}
|
||||||
<div class="title">
|
label={items.length > 0 ? undefined : key.attr.label}
|
||||||
<Label label={key.attr.label} />
|
width={width ?? 'min-content'}
|
||||||
</div>
|
{kind} {size} {justify}
|
||||||
|
on:click={addTag}
|
||||||
|
>
|
||||||
|
<svelte:fragment slot="content">
|
||||||
|
{#if items.length > 0}
|
||||||
|
<div class="flex-row-center flex-nowrap">
|
||||||
|
{#await translate(countLabel, { count: items.length }) then text}
|
||||||
|
{text}
|
||||||
|
{/await}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<ShowMore ignore={!showTitle}>
|
</svelte:fragment>
|
||||||
<div class:tags-container={showTitle} class:mt-4={showTitle}>
|
</Button>
|
||||||
<div class="flex flex-reverse">
|
</Tooltip>
|
||||||
<div id='add-tag' class="ml-4">
|
|
||||||
<Tooltip label={tags.string.AddTagTooltip} props={{ word: keyLabel }}>
|
|
||||||
<CircleButton icon={IconAdd} size={'small'} selected on:click={addTag} />
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="tag-items" class:tag-items-scroll={!showTitle}>
|
|
||||||
{#if items.length === 0}
|
|
||||||
{#if keyLabel}
|
|
||||||
<div class="flex flex-grow title-center">
|
|
||||||
<Label label={tags.string.NoItems} params={{ word: keyLabel }} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
{#each items as tag}
|
|
||||||
<TagItem
|
|
||||||
{tag}
|
|
||||||
element={elements.get(tag.tag)}
|
|
||||||
action={IconClose}
|
|
||||||
on:action={() => {
|
|
||||||
removeTag(tag._id)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ShowMore>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.title {
|
|
||||||
margin-right: 0.75rem;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 1.25rem;
|
|
||||||
color: var(--theme-caption-color);
|
|
||||||
}
|
|
||||||
.tags-container {
|
|
||||||
padding: 1rem;
|
|
||||||
color: var(--theme-caption-color);
|
|
||||||
background: var(--theme-bg-accent-color);
|
|
||||||
border: 1px solid var(--theme-bg-accent-color);
|
|
||||||
border-radius: 0.75rem;
|
|
||||||
}
|
|
||||||
.tag-items {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.tag-items-scroll {
|
|
||||||
overflow-y: scroll;
|
|
||||||
max-height: 10rem;
|
|
||||||
}
|
|
||||||
.title-center {
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -15,27 +15,38 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Class, Doc, Ref } from '@anticrm/core'
|
import { Class, Doc, Ref } from '@anticrm/core'
|
||||||
import type { IntlString } from '@anticrm/platform'
|
import type { IntlString } from '@anticrm/platform'
|
||||||
import { createQuery } from '@anticrm/presentation'
|
import { translate } from '@anticrm/platform'
|
||||||
import { TagElement } from '@anticrm/tags'
|
import presentation, { createQuery, getClient } from '@anticrm/presentation'
|
||||||
import ui, { ActionIcon, Button, EditWithIcon, IconAdd, IconSearch, Label, showPopup } from '@anticrm/ui'
|
import { TagCategory, TagElement } from '@anticrm/tags'
|
||||||
|
import { CheckBox, Button, Icon, IconAdd, IconClose, Label, showPopup, getPlatformColor } from '@anticrm/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import tags from '../plugin'
|
import tags from '../plugin'
|
||||||
import CreateTagElement from './CreateTagElement.svelte'
|
import CreateTagElement from './CreateTagElement.svelte'
|
||||||
import TagItem from './TagItem.svelte'
|
import IconView from './icons/View.svelte'
|
||||||
|
import IconViewHide from './icons/ViewHide.svelte'
|
||||||
|
|
||||||
export let targetClass: Ref<Class<Doc>>
|
export let targetClass: Ref<Class<Doc>>
|
||||||
export let title: string
|
export let placeholder: IntlString = presentation.string.Search
|
||||||
export let caption: IntlString = ui.string.Suggested
|
|
||||||
export let addRef: (tag: TagElement) => Promise<void>
|
export let addRef: (tag: TagElement) => Promise<void>
|
||||||
|
export let removeTag: (tag: TagElement) => Promise<void>
|
||||||
export let selected: Ref<TagElement>[] = []
|
export let selected: Ref<TagElement>[] = []
|
||||||
|
export let keyLabel: string = ''
|
||||||
|
|
||||||
let search: string = ''
|
let search: string = ''
|
||||||
|
let searchElement: HTMLInputElement
|
||||||
|
let show: boolean = false
|
||||||
let objects: TagElement[] = []
|
let objects: TagElement[] = []
|
||||||
let available: TagElement[] = []
|
let categories: TagCategory[] = []
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const query = createQuery()
|
const query = createQuery()
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
client.findAll(tags.class.TagCategory, { targetClass }).then((res) => { categories = res })
|
||||||
|
|
||||||
|
let phTraslate: string = ''
|
||||||
|
$: if (placeholder) translate(placeholder, {}).then(res => { phTraslate = res })
|
||||||
|
|
||||||
// TODO: Add $not: {$in: []} query
|
// TODO: Add $not: {$in: []} query
|
||||||
$: query.query(
|
$: query.query(
|
||||||
tags.class.TagElement,
|
tags.class.TagElement,
|
||||||
@ -46,70 +57,141 @@
|
|||||||
{ limit: 200 }
|
{ limit: 200 }
|
||||||
)
|
)
|
||||||
|
|
||||||
$: available = objects.filter((it) => !selected.includes(it._id))
|
|
||||||
|
|
||||||
let anchor: HTMLElement
|
|
||||||
async function createTagElement (): Promise<void> {
|
async function createTagElement (): Promise<void> {
|
||||||
showPopup(CreateTagElement, { targetClass, keyTitle: title }, anchor)
|
showPopup(CreateTagElement, { targetClass }, 'top')
|
||||||
}
|
}
|
||||||
async function addTag (element: TagElement): Promise<void> {
|
async function addTag (element: TagElement): Promise<void> {
|
||||||
await addRef(element)
|
await addRef(element)
|
||||||
selected = [...selected, element._id]
|
selected = [...selected, element._id]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isSelected = (element: TagElement): boolean => {
|
||||||
|
if (selected.filter(p => p === element._id).length > 0) return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const checkSelected = (element: TagElement): void => {
|
||||||
|
if (isSelected(element)) {
|
||||||
|
selected = selected.filter(p => p !== element._id)
|
||||||
|
removeTag(element)
|
||||||
|
} else {
|
||||||
|
selected.push(element._id)
|
||||||
|
addTag(element)
|
||||||
|
}
|
||||||
|
objects = objects
|
||||||
|
categories = categories
|
||||||
|
dispatch('update', selected)
|
||||||
|
}
|
||||||
|
const toggleGroup = (ev: MouseEvent): void => {
|
||||||
|
const el: HTMLElement = ev.currentTarget as HTMLElement
|
||||||
|
el.classList.toggle('show')
|
||||||
|
}
|
||||||
|
const getCount = (cat: TagCategory): string => {
|
||||||
|
const count = objects.filter(el => el.category === cat._id).filter((it) => selected.includes(it._id)).length
|
||||||
|
if (count > 0) return count.toString()
|
||||||
|
return ''
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiPopup antiPopup-withHeader antiPopup-withTitle">
|
<div class="selectPopup maxHeight">
|
||||||
<div class="ap-title">
|
<div class="header no-border">
|
||||||
<Label label={tags.string.AddTagTooltip} params={{ word: title }} />
|
<div class="flex-between flex-grow pr-2">
|
||||||
|
<div class="flex-grow">
|
||||||
|
<input bind:this={searchElement} type="text" bind:value={search} placeholder={phTraslate} style="width: 100%;" on:change/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ap-header">
|
<div class="buttons-group small-gap">
|
||||||
<EditWithIcon icon={IconSearch} bind:value={search} placeholder={tags.string.SearchCreate} focus>
|
<div class="clear-btn" class:show={search !== ''} on:click={() => {
|
||||||
<svelte:fragment slot="extra">
|
search = ''
|
||||||
<div id='new-tag' class="ml-27" bind:this={anchor}>
|
searchElement.focus()
|
||||||
<ActionIcon
|
}}>
|
||||||
label={tags.string.AddNowTooltip}
|
{#if search !== ''}<div class="icon"><Icon icon={IconClose} size={'inline'} /></div>{/if}
|
||||||
labelProps={{ word: title }}
|
|
||||||
icon={IconAdd}
|
|
||||||
action={createTagElement}
|
|
||||||
size={'small'}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</svelte:fragment>
|
<Button kind={'transparent'} size={'small'} icon={show ? IconView : IconViewHide} on:click={() => show = !show} />
|
||||||
</EditWithIcon>
|
<Button kind={'transparent'} size={'small'} icon={IconAdd} on:click={createTagElement} />
|
||||||
<div class="ap-caption">
|
|
||||||
<Label label={caption} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ap-space" />
|
</div>
|
||||||
<div class="ap-scroll">
|
<div class="scroll">
|
||||||
<div class="flex flex-wrap" style={'max-height: 15rem;'}>
|
<div class="box">
|
||||||
{#each available as element}
|
{#each categories as cat}
|
||||||
<div
|
{#if objects.filter(el => el.category === cat._id).length > 0}
|
||||||
class="hover-trans"
|
<div class="sticky-wrapper">
|
||||||
on:click={() => {
|
<button class="menu-group__header" class:show={search !== '' || show} on:click={toggleGroup}>
|
||||||
addTag(element)
|
<div class="flex-row-center">
|
||||||
}}
|
<span class="mr-1-5">{cat.label}</span>
|
||||||
>
|
<div class="icon">
|
||||||
<div class="flex-between">
|
<svg fill="var(--content-color)" viewBox="0 0 6 6" xmlns="http://www.w3.org/2000/svg">
|
||||||
<TagItem
|
<path d="M0,0L6,3L0,6Z" />
|
||||||
{element}
|
</svg>
|
||||||
action={IconAdd}
|
|
||||||
on:action={() => {
|
|
||||||
addTag(element)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex-row-center text-xs">
|
||||||
|
<span class="content-color mr-1">({objects.filter(el => el.category === cat._id).length})</span>
|
||||||
|
<span class="counter">{getCount(cat)}</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<div class="menu-group">
|
||||||
|
{#each objects.filter(el => el.category === cat._id) as element}
|
||||||
|
<button class="menu-item" on:click={() => {
|
||||||
|
checkSelected(element)
|
||||||
|
}}>
|
||||||
|
<div class="check pointer-events-none">
|
||||||
|
<CheckBox checked={isSelected(element)} primary />
|
||||||
|
</div>
|
||||||
|
<div class="tag" style="background-color: {getPlatformColor(element.color)};" />
|
||||||
|
{element.title}
|
||||||
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ap-footer">
|
{/if}
|
||||||
<Button
|
{/each}
|
||||||
label={tags.string.CancelLabel}
|
{#if objects.length === 0}
|
||||||
size={'small'}
|
<div class="empty">
|
||||||
on:click={() => {
|
<Label label={tags.string.NoItems} params={{ word: keyLabel }} />
|
||||||
dispatch('close')
|
</div>
|
||||||
}}
|
{/if}
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.clear-btn {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: .75rem;
|
||||||
|
height: .75rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: .625rem;
|
||||||
|
height: .625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
color: var(--content-color);
|
||||||
|
background-color: var(--button-border-color);
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: var(--accent-color);
|
||||||
|
background-color: var(--button-border-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.counter {
|
||||||
|
padding-right: .125rem;
|
||||||
|
min-width: 1.5rem;
|
||||||
|
text-align: right;
|
||||||
|
font-size: .8125rem;
|
||||||
|
color: var(--caption-color);
|
||||||
|
}
|
||||||
|
.empty {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
font-size: .75rem;
|
||||||
|
color: var(--dark-color);
|
||||||
|
border-top: 1px solid var(--popup-divider);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showCreateDialog (ev: Event) {
|
function showCreateDialog () {
|
||||||
showPopup(CreateTagElement, { targetClass, keyTitle }, 'top')
|
showPopup(CreateTagElement, { targetClass, keyTitle }, 'top')
|
||||||
}
|
}
|
||||||
const opt: FindOptions<TagElement> = {
|
const opt: FindOptions<TagElement> = {
|
||||||
@ -65,7 +65,7 @@
|
|||||||
updateResultQuery(search, category)
|
updateResultQuery(search, category)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button icon={IconAdd} label={сreateItemLabel} kind={'primary'} on:click={(ev) => showCreateDialog(ev)} />
|
<Button icon={IconAdd} label={сreateItemLabel} kind={'primary'} on:click={showCreateDialog} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CategoryBar
|
<CategoryBar
|
||||||
|
25
plugins/tags-resources/src/components/icons/View.svelte
Normal file
25
plugins/tags-resources/src/components/icons/View.svelte
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!--
|
||||||
|
// 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">
|
||||||
|
export let size: 'x-small' | 'small' | 'medium' | 'large'
|
||||||
|
const fill: string = 'currentColor'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg class="svg-{size}" {fill} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z M12,15c-1.7,0-3-1.3-3-3s1.3-3,3-3s3,1.3,3,3 S13.7,15,12,15z" />
|
||||||
|
<path d="M20.6,10.6l-0.4,0.3l-0.4,0.3c0.4,0.5,0.5,0.6,0.5,0.7s-0.1,0.3-0.5,0.7c-1.5,1.8-4.4,4.8-7.8,4.8c-3.4,0-6.3-3-7.8-4.8 c-0.4-0.5-0.5-0.6-0.5-0.7c0-0.2,0.1-0.3,0.5-0.7C5.7,9.5,8.6,6.5,12,6.5c3.4,0,6.3,3,7.8,4.8l0.4-0.3L20.6,10.6L20.6,10.6 C19,8.7,15.8,5.5,12,5.5c-3.8,0-7,3.2-8.6,5.1C3,11.1,2.7,11.5,2.7,12s0.3,0.9,0.7,1.4c1.6,1.9,4.8,5.1,8.6,5.1 c3.8,0,7-3.2,8.6-5.1c0.4-0.5,0.7-0.8,0.7-1.4S21,11.1,20.6,10.6z" />
|
||||||
|
</svg>
|
26
plugins/tags-resources/src/components/icons/ViewHide.svelte
Normal file
26
plugins/tags-resources/src/components/icons/ViewHide.svelte
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<!--
|
||||||
|
// 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">
|
||||||
|
export let size: 'x-small' | 'small' | 'medium' | 'large'
|
||||||
|
const fill: string = 'currentColor'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg class="svg-{size}" {fill} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8.7,9.8C8.2,10.4,8,11.2,8,12c0,2.2,1.8,4,4,4c0.8,0,1.6-0.2,2.2-0.7l-0.7-0.7C13,14.9,12.5,15,12,15c-1.7,0-3-1.3-3-3 c0-0.5,0.1-1,0.4-1.5L8.7,9.8z" />
|
||||||
|
<path d="M12,17.5c-1.7,0-3.3-0.7-4.6-1.7c-1.4-1-2.5-2.2-3.2-3c-0.4-0.5-0.5-0.6-0.5-0.7s0-0.2,0.5-0.7c0.7-0.8,1.7-2,3-2.9 L6.5,7.6c-1.3,1-2.4,2.2-3.1,3l-0.1,0.1C3,11.1,2.7,11.5,2.7,12s0.3,0.9,0.6,1.3l0.1,0.1c0.7,0.9,1.9,2.1,3.4,3.2 c1.5,1,3.3,1.9,5.2,1.9c1.5,0,2.9-0.5,4.2-1.2l-0.7-0.7C14.4,17.1,13.2,17.5,12,17.5z" />
|
||||||
|
<path d="M18.9,15.2c0.7-0.7,1.3-1.3,1.7-1.8l0.1-0.1c0.3-0.4,0.6-0.8,0.6-1.3s-0.3-0.9-0.6-1.3l-0.1-0.1c-0.7-0.9-1.9-2.1-3.4-3.2 c-1.5-1-3.3-1.9-5.2-1.9c-0.8,0-1.6,0.2-2.4,0.4L5.4,1.6L4.6,2.4l16,16l0.7-0.7L18.9,15.2z M12,6.5c1.7,0,3.3,0.7,4.6,1.7 c1.4,1,2.5,2.2,3.2,3c0.4,0.5,0.5,0.6,0.5,0.7s0,0.2-0.5,0.7c-0.4,0.5-1,1.1-1.6,1.7L16,12.3c0-0.1,0-0.2,0-0.3c0-2.2-1.8-4-4-4 c-0.1,0-0.2,0-0.3,0l-1.3-1.3C10.9,6.6,11.5,6.5,12,6.5z M14.9,11.2l-2-2C13.8,9.4,14.6,10.2,14.9,11.2z" />
|
||||||
|
</svg>
|
@ -24,17 +24,19 @@ test.describe('recruit tests', () => {
|
|||||||
// Fill [placeholder="Appleseed"]
|
// Fill [placeholder="Appleseed"]
|
||||||
await page.fill('[placeholder="Appleseed"]', 'Dooliutl')
|
await page.fill('[placeholder="Appleseed"]', 'Dooliutl')
|
||||||
// Click .ml-4 .tooltip-trigger .flex-center
|
// Click .ml-4 .tooltip-trigger .flex-center
|
||||||
await page.click('#add-tag')
|
await page.click('button:has-text("Skills")')
|
||||||
// Click text=Add/Create Skill Suggested Cancel >> button
|
// Click text=Add/Create Skill Suggested Cancel >> button
|
||||||
await page.click('#new-tag')
|
await page.click('.buttons-group button:nth-child(3)')
|
||||||
// Fill [placeholder="Please\ type\ Skill\ title"]
|
// Fill [placeholder="Please\ type\ Skill\ title"]
|
||||||
await page.fill('[placeholder="Please\\ type\\ Skill\\ title"]', 's1')
|
await page.fill('[placeholder="Please\\ type\\ \\ title"]', 's1')
|
||||||
// Click text=Create Skill s1 Please type description here Category Other Create Cancel >> button
|
// Click text=Create Skill s1 Please type description here Category Other Create Cancel >> button
|
||||||
await page.click('text=Create more Create >> button')
|
await page.click('text=Create more Create >> button')
|
||||||
|
await page.click('button:has-text("Other (1)")')
|
||||||
// Click text=s1
|
// Click text=s1
|
||||||
await page.click('text=s1')
|
await page.click('text=s1')
|
||||||
// Click :nth-match(:text("Cancel"), 2)
|
// Click :nth-match(:text("Cancel"), 2)
|
||||||
await page.click('button:has-text("Cancel")')
|
// await page.click('button:has-text("Cancel")')
|
||||||
|
await page.keyboard.press('Escape')
|
||||||
// Click button:has-text("Create")
|
// Click button:has-text("Create")
|
||||||
await page.click('button:has-text("Create")')
|
await page.click('button:has-text("Create")')
|
||||||
})
|
})
|
||||||
@ -74,11 +76,13 @@ test.describe('recruit tests', () => {
|
|||||||
// Click button:has-text("Candidate")
|
// Click button:has-text("Candidate")
|
||||||
await page.click('button:has-text("Candidate")')
|
await page.click('button:has-text("Candidate")')
|
||||||
// Click #add-tag div div
|
// Click #add-tag div div
|
||||||
await page.click('#add-tag div div')
|
await page.click('button:has-text("Skills")')
|
||||||
|
await page.click('button:has-text("Backend development (1)")')
|
||||||
// Click text=java
|
// Click text=java
|
||||||
await page.click('text=java')
|
await page.click('text=java')
|
||||||
// Click :nth-match(:text("Cancel"), 2)
|
// Click :nth-match(:text("Cancel"), 2)
|
||||||
await page.click('button:has-text("Cancel")')
|
// await page.click('button:has-text("Cancel")')
|
||||||
|
await page.keyboard.press('Escape')
|
||||||
// Click [placeholder="John"]
|
// Click [placeholder="John"]
|
||||||
await page.click('[placeholder="John"]')
|
await page.click('[placeholder="John"]')
|
||||||
// Fill [placeholder="John"]
|
// Fill [placeholder="John"]
|
||||||
|
Loading…
Reference in New Issue
Block a user