mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 11:01:54 +03:00
UBER-177: fixed Filter pop-ups (#3225)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
c0bb68be9e
commit
78034e6a00
@ -745,7 +745,7 @@
|
||||
.list-container .datetime-button,
|
||||
.list-container .datetime-button:hover {
|
||||
background-color: var(--theme-list-button-color) !important;
|
||||
.icon {
|
||||
.icon, .btn-icon {
|
||||
margin-right: .5rem;
|
||||
color: var(--theme-halfcontent-color) !important;
|
||||
}
|
||||
|
@ -48,11 +48,12 @@
|
||||
max-width: 40rem !important;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: .5rem;
|
||||
padding: .5rem;
|
||||
border-bottom: 1px solid var(--theme-popup-divider);
|
||||
|
||||
&.no-border { border-bottom-color: transparent; }
|
||||
|
||||
&:not(.no-border) {
|
||||
margin-bottom: .5rem;
|
||||
border-bottom: 1px solid var(--theme-popup-divider);
|
||||
}
|
||||
.clear-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -345,11 +346,13 @@
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
justify-content: flex-start;
|
||||
margin: 0 .5rem;
|
||||
padding: .25rem .5rem;
|
||||
min-width: 0;
|
||||
min-height: 2.25rem;
|
||||
text-align: left;
|
||||
color: var(--theme-caption-color);
|
||||
border-radius: .25rem;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
|
||||
|
@ -153,11 +153,7 @@
|
||||
>
|
||||
<svelte:fragment slot="item" let:item={itemId}>
|
||||
{@const item = filteredObjects[itemId]}
|
||||
<button
|
||||
class="menu-item withList w-full"
|
||||
class:selected={item.isSelected}
|
||||
on:click={() => dispatch('close', item.id)}
|
||||
>
|
||||
<button class="menu-item withList w-full" on:click={() => dispatch('close', item.id)}>
|
||||
<div class="flex-row-center flex-grow pointer-events-none">
|
||||
{#if item.component}
|
||||
<div class="flex-grow clear-mins"><svelte:component this={item.component} {...item.props} /></div>
|
||||
|
@ -70,6 +70,7 @@
|
||||
"DM": "Direct message",
|
||||
"DMNotification": "Sent you a message",
|
||||
"ConfigLabel": "Chat",
|
||||
"ConfigDescription": "Extension to perform text communications"
|
||||
"ConfigDescription": "Extension to perform text communications",
|
||||
"LastMessage": "Last message"
|
||||
}
|
||||
}
|
@ -70,6 +70,7 @@
|
||||
"DM": "Личное сообщение",
|
||||
"DMNotification": "Отправил сообщение",
|
||||
"ConfigLabel": "Чат",
|
||||
"ConfigDescription": "Расширение для текстовых переписок"
|
||||
"ConfigDescription": "Расширение для текстовых переписок",
|
||||
"LastMessage": "Последнее сообщение"
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import { ChannelProvider } from '@hcengineering/contact'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { CheckBox, Icon, Label, resizeObserver } from '@hcengineering/ui'
|
||||
import { IconCheck, Icon, Label, resizeObserver } from '@hcengineering/ui'
|
||||
import { Filter } from '@hcengineering/view'
|
||||
import { FILTER_DEBOUNCE_MS, FilterQuery, sortFilterValues } from '@hcengineering/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
@ -65,28 +65,28 @@
|
||||
</script>
|
||||
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
<div class="menu-space" />
|
||||
<div class="scroll">
|
||||
<div class="box">
|
||||
{#each sortFilterValues($channelProviders, (v) => isSelected(v, selected)) as element}
|
||||
<button
|
||||
class="menu-item"
|
||||
class="menu-item no-focus flex-row-center content-pointer-events-none"
|
||||
on:click={() => {
|
||||
handleFilterToggle(element)
|
||||
}}
|
||||
>
|
||||
<div class="flex-between w-full">
|
||||
<div class="flex">
|
||||
<div class="check pointer-events-none">
|
||||
<CheckBox checked={isSelected(element, selected)} primary />
|
||||
</div>
|
||||
{#if element.icon}
|
||||
<span class="mr-2"><Icon icon={element.icon} size="inline" /></span>
|
||||
{/if}
|
||||
<Label label={element.label} />
|
||||
</div>
|
||||
{#if element.icon}
|
||||
<div class="icon"><Icon icon={element.icon} size={'small'} /></div>
|
||||
{/if}
|
||||
<span class="overflow-label label flex-grow"><Label label={element.label} /></span>
|
||||
<div class="check">
|
||||
{#if isSelected(element, selected)}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
@ -17,11 +17,20 @@
|
||||
import core, { Doc, FindResult, getObjectValue, Ref, SortingOrder, Space } from '@hcengineering/core'
|
||||
import { translate } from '@hcengineering/platform'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import ui, { addNotification, deviceOptionsStore, Icon, IconCheck, Loading, resizeObserver } from '@hcengineering/ui'
|
||||
import ui, {
|
||||
addNotification,
|
||||
deviceOptionsStore,
|
||||
Icon,
|
||||
IconCheck,
|
||||
Loading,
|
||||
resizeObserver,
|
||||
EditWithIcon,
|
||||
IconSearch
|
||||
} from '@hcengineering/ui'
|
||||
import { Filter } from '@hcengineering/view'
|
||||
import { FILTER_DEBOUNCE_MS, FilterRemovedNotification, sortFilterValues } from '@hcengineering/view-resources'
|
||||
import view from '@hcengineering/view-resources/src/plugin'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import EmployeePresenter from './EmployeePresenter.svelte'
|
||||
|
||||
export let filter: Filter
|
||||
@ -113,15 +122,6 @@
|
||||
}
|
||||
|
||||
let search: string = ''
|
||||
let phTraslate: string = ''
|
||||
let searchInput: HTMLInputElement
|
||||
$: translate(presentation.string.Search, {}).then((res) => {
|
||||
phTraslate = res
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
if (searchInput && !$deviceOptionsStore.isMobile) searchInput.focus()
|
||||
})
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
$: getValues(search)
|
||||
@ -129,14 +129,16 @@
|
||||
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
<div class="header">
|
||||
<input
|
||||
bind:this={searchInput}
|
||||
type="text"
|
||||
<EditWithIcon
|
||||
icon={IconSearch}
|
||||
size={'large'}
|
||||
width={'100%'}
|
||||
focus={!$deviceOptionsStore.isMobile}
|
||||
bind:value={search}
|
||||
placeholder={presentation.string.Search}
|
||||
on:change={() => {
|
||||
getValues(search)
|
||||
}}
|
||||
placeholder={phTraslate}
|
||||
/>
|
||||
</div>
|
||||
<div class="scroll">
|
||||
@ -146,24 +148,23 @@
|
||||
{:else}
|
||||
{#each sortFilterValues(values, (v) => isSelected(v, filter.value)) as value}
|
||||
<button
|
||||
class="menu-item no-focus"
|
||||
class="menu-item no-focus flex-row-center"
|
||||
on:click={() => {
|
||||
handleFilterToggle(value)
|
||||
}}
|
||||
>
|
||||
<div class="flex-between w-full">
|
||||
<div class="flex-row-center">
|
||||
<EmployeePresenter {value} shouldShowPlaceholder defaultName={ui.string.NotSelected} disabled />
|
||||
</div>
|
||||
<div class="pointer-events-none">
|
||||
{#if isSelected(value, filter.value)}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="clear-mins flex-grow">
|
||||
<EmployeePresenter {value} shouldShowPlaceholder defaultName={ui.string.NotSelected} disabled />
|
||||
</div>
|
||||
<div class="check pointer-events-none">
|
||||
{#if isSelected(value, filter.value)}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
@ -27,12 +27,12 @@
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<DocNavLink {disabled} object={value} {inline} component={recruit.component.EditVacancy}>
|
||||
<DocNavLink {disabled} object={value} {inline} noUnderline={disabled} component={recruit.component.EditVacancy}>
|
||||
<div class="flex-presenter" class:inline-presenter={inline} use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
||||
{#if !inline}
|
||||
<div class="icon"><Icon icon={recruit.icon.Vacancy} size={'small'} /></div>
|
||||
{/if}
|
||||
<span class="label">{value.name}</span>
|
||||
<span class="label" class:no-underline={disabled}>{value.name}</span>
|
||||
</div>
|
||||
</DocNavLink>
|
||||
{/if}
|
||||
|
@ -14,13 +14,14 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Class, Doc, FindResult, Ref } from '@hcengineering/core'
|
||||
import { translate } from '@hcengineering/platform'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import { TagCategory, TagElement } from '@hcengineering/tags'
|
||||
import {
|
||||
Button,
|
||||
Icon,
|
||||
IconCheck,
|
||||
IconSearch,
|
||||
EditWithIcon,
|
||||
Label,
|
||||
Loading,
|
||||
deviceOptionsStore,
|
||||
@ -31,7 +32,7 @@
|
||||
} from '@hcengineering/ui'
|
||||
import { Filter } from '@hcengineering/view'
|
||||
import { FILTER_DEBOUNCE_MS, FilterQuery, sortFilterValues } from '@hcengineering/view-resources'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import tags from '../plugin'
|
||||
import { tagLevel } from '../utils'
|
||||
import WeightPopup from './WeightPopup.svelte'
|
||||
@ -76,15 +77,6 @@
|
||||
}
|
||||
|
||||
let search: string = ''
|
||||
let phTraslate: string = ''
|
||||
let searchInput: HTMLInputElement
|
||||
$: translate(presentation.string.Search, {}).then((res) => {
|
||||
phTraslate = res
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
if (searchInput && !$deviceOptionsStore.isMobile) searchInput.focus()
|
||||
})
|
||||
|
||||
const toggleGroup = (ev: MouseEvent): void => {
|
||||
const el: HTMLElement = ev.currentTarget as HTMLElement
|
||||
@ -137,18 +129,20 @@
|
||||
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
<div class="header">
|
||||
<input
|
||||
bind:this={searchInput}
|
||||
type="text"
|
||||
<EditWithIcon
|
||||
icon={IconSearch}
|
||||
size={'large'}
|
||||
width={'100%'}
|
||||
focus={!$deviceOptionsStore.isMobile}
|
||||
bind:value={search}
|
||||
placeholder={presentation.string.Search}
|
||||
on:change={() => {
|
||||
getValues(search)
|
||||
}}
|
||||
placeholder={phTraslate}
|
||||
/>
|
||||
{#if schema !== '0'}
|
||||
<div class="flex-row-center flex-between flex-grow p-1">
|
||||
<Label label={tags.string.Weight} />
|
||||
<div class="flex-between w-full mt-2">
|
||||
<span class="overflow-label pl-2 mr-2"><Label label={tags.string.Weight} /></span>
|
||||
<Button
|
||||
label={tagLevelLabel}
|
||||
icon={tagLevelIcon}
|
||||
@ -170,9 +164,10 @@
|
||||
{#if objectsPromise}
|
||||
<Loading />
|
||||
{:else}
|
||||
{#each categories as cat}
|
||||
{#each categories as cat, i}
|
||||
{@const values = objects.filter((el) => el.category === cat._id)}
|
||||
{#if values.length > 0}
|
||||
{#if i > 0}<div class="menu-separator" />{/if}
|
||||
<div class="sticky-wrapper">
|
||||
<button
|
||||
class="menu-group__header"
|
||||
@ -198,21 +193,17 @@
|
||||
<div class="menu-group">
|
||||
{#each sortFilterValues(values, isSelected) as element}
|
||||
<button
|
||||
class="menu-item"
|
||||
class="menu-item no-focus flex-row-center"
|
||||
on:click={() => {
|
||||
handleFilterToggle(element)
|
||||
}}
|
||||
>
|
||||
<div class="flex-between w-full">
|
||||
<div class="flex">
|
||||
<div class="tag" style="background-color: {getPlatformColor(element.color)};" />
|
||||
{element.title}
|
||||
</div>
|
||||
<div class="pointer-events-none">
|
||||
{#if isSelected(element)}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="tag" style="background-color: {getPlatformColor(element.color)};" />
|
||||
<span class="overflow-label label flex-grow">{element.title}</span>
|
||||
<div class="check pointer-events-none">
|
||||
{#if isSelected(element)}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
@ -223,6 +214,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Button, resizeObserver } from '@hcengineering/ui'
|
||||
import { resizeObserver, Icon, IconCheck, Label } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import tags from '../plugin'
|
||||
import { tagLevel } from '../utils'
|
||||
@ -27,34 +27,36 @@
|
||||
</script>
|
||||
|
||||
<div class="selectPopup max-width-40" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
<div class="header no-border p-3">
|
||||
{#each labels as l, i}
|
||||
<div class="flex gap-2 p-1">
|
||||
<div class="menu-space" />
|
||||
<div class="scroll">
|
||||
<div class="box">
|
||||
{#each labels as l, i}
|
||||
{#if schema === '9'}
|
||||
{#each Object.entries(tagLevel) as k, j}
|
||||
{@const valueK = i * 3 + j}
|
||||
<Button
|
||||
label={l}
|
||||
icon={k[1]}
|
||||
size={'small'}
|
||||
justify={'left'}
|
||||
selected={value === valueK}
|
||||
on:click={() => dispatch('close', valueK)}
|
||||
width={'8rem'}
|
||||
/>
|
||||
<button class="menu-item flex-row-center" on:click={() => dispatch('close', valueK)}>
|
||||
<div class="icon"><Icon icon={k[1]} size={'small'} /></div>
|
||||
<span class="overflow-label label flex-grow"><Label label={l} /></span>
|
||||
<div class="check pointer-events-none">
|
||||
{#if value === valueK}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
{:else}
|
||||
{@const valueK = i * 3}
|
||||
<Button
|
||||
label={l}
|
||||
size={'small'}
|
||||
justify={'left'}
|
||||
selected={value === valueK}
|
||||
on:click={() => dispatch('close', valueK)}
|
||||
width={'8rem'}
|
||||
/>
|
||||
<button class="menu-item flex-row-center" on:click={() => dispatch('close', valueK)}>
|
||||
<span class="overflow-label label flex-grow"><Label label={l} /></span>
|
||||
<div class="check pointer-events-none">
|
||||
{#if value === valueK}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
@ -23,6 +23,8 @@
|
||||
export let inline: boolean = false
|
||||
export let colorInherit: boolean = false
|
||||
export let accent: boolean = false
|
||||
export let disabled: boolean = false
|
||||
export let oneLine: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@ -46,7 +48,7 @@
|
||||
{#if shouldShowAvatar}
|
||||
<div class="state-container" class:inline style="background-color: {fill}" />
|
||||
{/if}
|
||||
<span class="label nowrap">{value.name}</span>
|
||||
<span class="overflow-label label" class:nowrap={oneLine} class:no-underline={disabled}>{value.name}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
@ -14,13 +14,21 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { DocumentQuery, FindResult, Ref, SortingOrder } from '@hcengineering/core'
|
||||
import { translate } from '@hcengineering/platform'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import { Project, Milestone, MilestoneStatus } from '@hcengineering/tracker'
|
||||
import ui, { CheckBox, Icon, Label, Loading, deviceOptionsStore, resizeObserver } from '@hcengineering/ui'
|
||||
import ui, {
|
||||
IconCheck,
|
||||
Icon,
|
||||
Label,
|
||||
Loading,
|
||||
deviceOptionsStore,
|
||||
resizeObserver,
|
||||
EditWithIcon,
|
||||
IconSearch
|
||||
} from '@hcengineering/ui'
|
||||
import { FILTER_DEBOUNCE_MS, sortFilterValues } from '@hcengineering/view-resources'
|
||||
import view, { Filter } from '@hcengineering/view'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
import { milestoneStatusAssets } from '../../types'
|
||||
import MilestoneTitlePresenter from './MilestoneTitlePresenter.svelte'
|
||||
@ -34,11 +42,6 @@
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let search: string = ''
|
||||
let phTraslate: string = ''
|
||||
let searchInput: HTMLInputElement
|
||||
$: translate(presentation.string.Search, {}).then((res) => {
|
||||
phTraslate = res
|
||||
})
|
||||
|
||||
let values: Milestone[] = []
|
||||
let objectsPromise: Promise<FindResult<Milestone>> | undefined = undefined
|
||||
@ -110,23 +113,21 @@
|
||||
return res
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (searchInput && !$deviceOptionsStore.isMobile) searchInput.focus()
|
||||
})
|
||||
|
||||
getValues(search)
|
||||
</script>
|
||||
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
<div class="header">
|
||||
<input
|
||||
bind:this={searchInput}
|
||||
type="text"
|
||||
<EditWithIcon
|
||||
icon={IconSearch}
|
||||
size={'large'}
|
||||
width={'100%'}
|
||||
focus={!$deviceOptionsStore.isMobile}
|
||||
bind:value={search}
|
||||
placeholder={presentation.string.Search}
|
||||
on:change={() => {
|
||||
getValues(search)
|
||||
}}
|
||||
placeholder={phTraslate}
|
||||
/>
|
||||
</div>
|
||||
<div class="scroll">
|
||||
@ -135,41 +136,46 @@
|
||||
<Loading />
|
||||
{:else}
|
||||
<button
|
||||
class="menu-item"
|
||||
class="menu-item no-focus flex-row-center"
|
||||
on:click={() => {
|
||||
handleFilterToggle(undefined)
|
||||
}}
|
||||
>
|
||||
<div class="flex clear-mins">
|
||||
<div class="check pointer-events-none">
|
||||
<CheckBox checked={isSelected(undefined, selectedValues)} primary />
|
||||
</div>
|
||||
<div class="overflow-label flex-grow">
|
||||
<Label label={ui.string.NotSelected} />
|
||||
</div>
|
||||
<div class="check pointer-events-none">
|
||||
{#if isSelected(undefined, selectedValues)}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
{#each getStatuses() as group}
|
||||
{@const status = milestoneStatusAssets[group]}
|
||||
{@const items = getStatusItem(group, values)}
|
||||
{#if items.length > 0}
|
||||
<div class="flex-row-center p-1">
|
||||
<Icon icon={status.icon} size={'small'} />
|
||||
<div class="ml-2">
|
||||
<Label label={status.label} />
|
||||
<div class="menu-separator" />
|
||||
<div class="menu-group__header">
|
||||
<div class="flex-row-center gap-2">
|
||||
<Icon icon={status.icon} size={'small'} />
|
||||
<span class="overflow-label"><Label label={status.label} /></span>
|
||||
</div>
|
||||
</div>
|
||||
{#each sortFilterValues(items, (v) => isSelected(v._id, selectedValues)) as doc}
|
||||
<button
|
||||
class="menu-item"
|
||||
class="menu-item no-focus flex-row-center"
|
||||
on:click={() => {
|
||||
handleFilterToggle(doc._id)
|
||||
}}
|
||||
>
|
||||
<div class="flex clear-mins">
|
||||
<div class="check pointer-events-none">
|
||||
<CheckBox checked={isSelected(doc._id, selectedValues)} primary />
|
||||
</div>
|
||||
<div class="flex-grow clear-mins">
|
||||
<MilestoneTitlePresenter value={doc} />
|
||||
</div>
|
||||
<div class="check pointer-events-none">
|
||||
{#if isSelected(doc._id, selectedValues)}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
{/if}
|
||||
@ -177,4 +183,5 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
@ -265,6 +265,7 @@
|
||||
</script>
|
||||
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
<div class="menu-space" />
|
||||
<Scroller>
|
||||
{#if nestedFrom}
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
@ -320,15 +321,9 @@
|
||||
</button>
|
||||
{/if}
|
||||
{#if nextDiffCat(types, i)}
|
||||
<div class="divider" />
|
||||
<div class="menu-separator" />
|
||||
{/if}
|
||||
{/each}
|
||||
</Scroller>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.divider {
|
||||
height: 1px;
|
||||
background-color: var(--theme-popup-divider);
|
||||
}
|
||||
</style>
|
||||
|
@ -20,13 +20,15 @@
|
||||
addNotification,
|
||||
Icon,
|
||||
IconCheck,
|
||||
IconSearch,
|
||||
deviceOptionsStore,
|
||||
Label,
|
||||
Loading,
|
||||
resizeObserver
|
||||
resizeObserver,
|
||||
EditWithIcon
|
||||
} from '@hcengineering/ui'
|
||||
import { Filter } from '@hcengineering/view'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import view from '../../plugin'
|
||||
import { FILTER_DEBOUNCE_MS, sortFilterValues } from '../../filter'
|
||||
import { buildConfigLookup, getPresenter } from '../../utils'
|
||||
@ -152,15 +154,6 @@
|
||||
}
|
||||
|
||||
let search: string = ''
|
||||
let phTraslate: string = ''
|
||||
let searchInput: HTMLInputElement
|
||||
$: translate(presentation.string.Search, {}).then((res) => {
|
||||
phTraslate = res
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
if (searchInput && !$deviceOptionsStore.isMobile) searchInput.focus()
|
||||
})
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
$: if (targetClass) getValues(search)
|
||||
@ -169,16 +162,20 @@
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
{#if clazz.sortingKey}
|
||||
<div class="header">
|
||||
<input
|
||||
bind:this={searchInput}
|
||||
type="text"
|
||||
<EditWithIcon
|
||||
icon={IconSearch}
|
||||
size={'large'}
|
||||
width={'100%'}
|
||||
focus={!$deviceOptionsStore.isMobile}
|
||||
bind:value={search}
|
||||
placeholder={presentation.string.Search}
|
||||
on:change={() => {
|
||||
getValues(search)
|
||||
}}
|
||||
placeholder={phTraslate}
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="menu-space" />
|
||||
{/if}
|
||||
<div class="scroll">
|
||||
<div class="box">
|
||||
@ -188,7 +185,7 @@
|
||||
{:else}
|
||||
{#each sortFilterValues(values, (v) => isSelected(v, filter.value)) as value}
|
||||
<button
|
||||
class="menu-item no-focus"
|
||||
class="menu-item no-focus content-pointer-events-none"
|
||||
on:click={() => {
|
||||
handleFilterToggle(value)
|
||||
}}
|
||||
@ -215,4 +212,5 @@
|
||||
{/await}
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
@ -13,10 +13,9 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { translate } from '@hcengineering/platform'
|
||||
import { Button, resizeObserver, deviceOptionsStore } from '@hcengineering/ui'
|
||||
import { Button, resizeObserver, deviceOptionsStore, EditWithIcon, IconSearch } from '@hcengineering/ui'
|
||||
import { Filter } from '@hcengineering/view'
|
||||
import { onMount, createEventDispatcher } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import view from '../../plugin'
|
||||
|
||||
export let filter: Filter
|
||||
@ -24,9 +23,7 @@
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let searchInput: HTMLInputElement
|
||||
let search = filter.value[0] ?? ''
|
||||
let phTraslate = ''
|
||||
|
||||
filter.modes = [view.filter.FilterContains]
|
||||
filter.mode ??= filter.modes[0]
|
||||
@ -49,19 +46,19 @@
|
||||
onChange(filter)
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
$: translate(filter.key.label, {}).then((res) => {
|
||||
phTraslate = res
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
if (searchInput && !$deviceOptionsStore.isMobile) searchInput.focus()
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')} on:keydown={onKeyDown}>
|
||||
<div class="header">
|
||||
<input bind:this={searchInput} bind:value={search} type="text" placeholder={phTraslate} />
|
||||
<div class="header no-border">
|
||||
<EditWithIcon
|
||||
icon={IconSearch}
|
||||
size={'large'}
|
||||
width={'100%'}
|
||||
focus={!$deviceOptionsStore.isMobile}
|
||||
bind:value={search}
|
||||
placeholder={filter.key.label}
|
||||
on:change
|
||||
/>
|
||||
</div>
|
||||
<Button shape="filter" label={view.string.Apply} on:click={save} />
|
||||
</div>
|
||||
|
@ -14,11 +14,19 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core, { Class, Doc, FindResult, getObjectValue, Ref, SortingOrder, Space } from '@hcengineering/core'
|
||||
import { translate } from '@hcengineering/platform'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import ui, { Icon, IconCheck, Label, Loading, resizeObserver, deviceOptionsStore } from '@hcengineering/ui'
|
||||
import ui, {
|
||||
EditWithIcon,
|
||||
Icon,
|
||||
IconSearch,
|
||||
IconCheck,
|
||||
Label,
|
||||
Loading,
|
||||
resizeObserver,
|
||||
deviceOptionsStore
|
||||
} from '@hcengineering/ui'
|
||||
import { Filter } from '@hcengineering/view'
|
||||
import { onMount, createEventDispatcher } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { getPresenter } from '../../utils'
|
||||
import { FILTER_DEBOUNCE_MS, sortFilterValues } from '../../filter'
|
||||
import view from '../../plugin'
|
||||
@ -127,34 +135,29 @@
|
||||
}
|
||||
|
||||
let search: string = ''
|
||||
let phTraslate: string = ''
|
||||
let searchInput: HTMLInputElement
|
||||
$: translate(presentation.string.Search, {}).then((res) => {
|
||||
phTraslate = res
|
||||
})
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
onMount(() => {
|
||||
if (searchInput && !$deviceOptionsStore.isMobile) searchInput.focus()
|
||||
})
|
||||
|
||||
getValues(search)
|
||||
</script>
|
||||
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
{#if isSearchable}
|
||||
<div class="header">
|
||||
<input
|
||||
bind:this={searchInput}
|
||||
type="text"
|
||||
<EditWithIcon
|
||||
icon={IconSearch}
|
||||
size={'large'}
|
||||
width={'100%'}
|
||||
focus={!$deviceOptionsStore.isMobile}
|
||||
bind:value={search}
|
||||
placeholder={presentation.string.Search}
|
||||
on:change={() => {
|
||||
getValues(search)
|
||||
}}
|
||||
placeholder={phTraslate}
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="menu-space" />
|
||||
{/if}
|
||||
<div class="scroll">
|
||||
<div class="box">
|
||||
@ -165,29 +168,27 @@
|
||||
{#each sortFilterValues([...values.keys()], (v) => isSelected(v, selectedValues)) as value}
|
||||
{@const realValue = [...(realValues.get(value) ?? [])][0]}
|
||||
<button
|
||||
class="menu-item no-focus"
|
||||
class="menu-item no-focus content-pointer-events-none"
|
||||
on:click={() => {
|
||||
handleFilterToggle(value)
|
||||
}}
|
||||
>
|
||||
<div class="flex-between w-full">
|
||||
<div class="flex-row-center">
|
||||
{#if value !== undefined}
|
||||
<svelte:component
|
||||
this={attribute.presenter}
|
||||
value={typeof value === 'string' ? realValue : value}
|
||||
{...attribute.props}
|
||||
oneLine
|
||||
/>
|
||||
{:else}
|
||||
<Label label={ui.string.NotSelected} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="pointer-events-none">
|
||||
{#if isSelected(value, selectedValues)}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
{#if value !== undefined}
|
||||
<div class="clear-mins flex-grow">
|
||||
<svelte:component
|
||||
this={attribute.presenter}
|
||||
value={typeof value === 'string' ? realValue : value}
|
||||
{...attribute.props}
|
||||
oneLine
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<span class="overflow-label flex-grow"><Label label={ui.string.NotSelected} /></span>
|
||||
{/if}
|
||||
<div class="check pointer-events-none">
|
||||
{#if isSelected(value, selectedValues)}
|
||||
<Icon icon={IconCheck} size={'small'} />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
@ -195,4 +196,5 @@
|
||||
{/await}
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user