mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 03:40:48 +00:00
[TSK-1333] Separate filter for TypeString (#3171)
Signed-off-by: Sergei Ogorelkov <sergei.ogorelkov@icloud.com>
This commit is contained in:
parent
bd3c683cde
commit
0473d9eaf9
@ -671,7 +671,7 @@ export function createModel (builder: Builder): void {
|
||||
})
|
||||
|
||||
builder.mixin(core.class.TypeString, core.class.Class, view.mixin.AttributeFilter, {
|
||||
component: view.component.ValueFilter
|
||||
component: view.component.StringFilter
|
||||
})
|
||||
|
||||
builder.mixin(core.class.TypeHyperlink, core.class.Class, view.mixin.AttributeFilter, {
|
||||
@ -762,6 +762,16 @@ export function createModel (builder: Builder): void {
|
||||
view.filter.FilterAfter
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
view.class.FilterMode,
|
||||
core.space.Model,
|
||||
{
|
||||
label: view.string.Contains,
|
||||
result: view.function.FilterContainsResult
|
||||
},
|
||||
view.filter.FilterContains
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
view.class.FilterMode,
|
||||
core.space.Model,
|
||||
|
@ -103,6 +103,7 @@ export default mergeIds(viewId, view, {
|
||||
FilterValueNinResult: '' as FilterFunction,
|
||||
FilterBeforeResult: '' as FilterFunction,
|
||||
FilterAfterResult: '' as FilterFunction,
|
||||
FilterContainsResult: '' as FilterFunction,
|
||||
FilterNestedMatchResult: '' as FilterFunction,
|
||||
FilterNestedDontMatchResult: '' as FilterFunction,
|
||||
FilterDateOutdated: '' as FilterFunction,
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"string": {
|
||||
"Contains": "contains",
|
||||
"MoveClass": "Move {class}",
|
||||
"SelectToMove": "Select the {classLabel} you want to move {class} to.",
|
||||
"Delete": "Delete",
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"string": {
|
||||
"Contains": "содержит",
|
||||
"MoveClass": "Переместить {class}",
|
||||
"SelectToMove": "Выберите {classLabel}, в который вы хотите переместить {class}.",
|
||||
"Delete": "Удалить",
|
||||
|
@ -0,0 +1,67 @@
|
||||
<!--
|
||||
// Copyright © 2023 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 { translate } from '@hcengineering/platform'
|
||||
import { Button, resizeObserver, deviceOptionsStore } from '@hcengineering/ui'
|
||||
import { Filter } from '@hcengineering/view'
|
||||
import { onMount, createEventDispatcher } from 'svelte'
|
||||
import view from '../../plugin'
|
||||
|
||||
export let filter: Filter
|
||||
export let onChange: (e: Filter) => void
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let searchInput: HTMLInputElement
|
||||
let search = filter.value[0] ?? ''
|
||||
let phTraslate = ''
|
||||
|
||||
filter.modes = [view.filter.FilterContains]
|
||||
filter.mode ??= filter.modes[0]
|
||||
|
||||
export function onKeyDown (event: KeyboardEvent): boolean {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
save()
|
||||
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function save () {
|
||||
filter.value = search ? [search] : []
|
||||
|
||||
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>
|
||||
<Button shape="filter" label={view.string.Apply} on:click={save} />
|
||||
</div>
|
@ -57,6 +57,7 @@
|
||||
<div class="scroll">
|
||||
<div class="box">
|
||||
{#each values as value, i}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="menu-item"
|
||||
on:click={() => {
|
||||
|
@ -18,10 +18,9 @@
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import ui, { Icon, IconCheck, Label, Loading, resizeObserver, deviceOptionsStore } from '@hcengineering/ui'
|
||||
import { Filter } from '@hcengineering/view'
|
||||
import { onMount } from 'svelte'
|
||||
import { onMount, createEventDispatcher } from 'svelte'
|
||||
import { getPresenter } from '../../utils'
|
||||
import view from '../../plugin'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let space: Ref<Space> | undefined = undefined
|
||||
@ -31,11 +30,7 @@
|
||||
filter.modes = [view.filter.FilterValueIn, view.filter.FilterValueNin]
|
||||
filter.mode = filter.mode === undefined ? filter.modes[0] : filter.mode
|
||||
|
||||
// TODO: remove "TypeString" from search types after
|
||||
// a separate filter for strings is implemented
|
||||
$: isSearchable = [core.class.TypeNumber, core.class.TypeString, core.class.EnumOf].includes(
|
||||
filter.key.attribute.type._class
|
||||
)
|
||||
$: isSearchable = [core.class.TypeNumber, core.class.EnumOf].includes(filter.key.attribute.type._class)
|
||||
|
||||
const client = getClient()
|
||||
const key = { key: filter.key.key }
|
||||
|
@ -62,6 +62,7 @@
|
||||
<div class="mb-1"><a class="fs-title" {href}>{data.title}</a></div>
|
||||
<div class="mb-1"><a href={data.authorUrl}>{data.author}</a></div>
|
||||
{#if !played}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="container"
|
||||
on:click={() => {
|
||||
|
@ -70,6 +70,12 @@ export async function afterResult (filter: Filter): Promise<ObjQueryType<any>> {
|
||||
return { $gt: filter.value[0] }
|
||||
}
|
||||
|
||||
export async function containsResult (filter: Filter): Promise<ObjQueryType<any>> {
|
||||
const [value] = filter.value
|
||||
|
||||
return typeof value === 'string' ? { $like: `%${value}%` } : {}
|
||||
}
|
||||
|
||||
export async function nestedMatchResult (filter: Filter, onUpdate: () => void): Promise<ObjQueryType<any>> {
|
||||
if (filter.nested === undefined) return {}
|
||||
const result = await getRefs(filter.nested, onUpdate)
|
||||
@ -256,6 +262,12 @@ function getFilterModes (component: AnyComponent): FilterModes | undefined {
|
||||
mode: view.filter.FilterBefore
|
||||
}
|
||||
}
|
||||
if (component === view.component.StringFilter) {
|
||||
return {
|
||||
modes: [view.filter.FilterContains],
|
||||
mode: view.filter.FilterContains
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createFilter (_class: Ref<Class<Doc>>, key: string, value: any[]): Filter | undefined {
|
||||
|
@ -39,6 +39,7 @@ import ObjectFilter from './components/filter/ObjectFilter.svelte'
|
||||
import TimestampFilter from './components/filter/TimestampFilter.svelte'
|
||||
import DateFilter from './components/filter/DateFilter.svelte'
|
||||
import ValueFilter from './components/filter/ValueFilter.svelte'
|
||||
import StringFilter from './components/filter/StringFilter.svelte'
|
||||
import HTMLEditor from './components/HTMLEditor.svelte'
|
||||
import HTMLPresenter from './components/HTMLPresenter.svelte'
|
||||
import HyperlinkPresenter from './components/HyperlinkPresenter.svelte'
|
||||
@ -77,6 +78,7 @@ import ViewletSettingButton from './components/ViewletSettingButton.svelte'
|
||||
import {
|
||||
afterResult,
|
||||
beforeResult,
|
||||
containsResult,
|
||||
dateCustom,
|
||||
dateMonth,
|
||||
dateNextMonth,
|
||||
@ -178,6 +180,7 @@ export default async (): Promise<Resources> => ({
|
||||
ObjectFilter,
|
||||
DateFilter,
|
||||
ValueFilter,
|
||||
StringFilter,
|
||||
TimestampFilter,
|
||||
TableBrowser,
|
||||
SpacePresenter,
|
||||
@ -229,6 +232,7 @@ export default async (): Promise<Resources> => ({
|
||||
FilterValueNinResult: valueNinResult,
|
||||
FilterBeforeResult: beforeResult,
|
||||
FilterAfterResult: afterResult,
|
||||
FilterContainsResult: containsResult,
|
||||
FilterNestedMatchResult: nestedMatchResult,
|
||||
FilterNestedDontMatchResult: nestedDontMatchResult,
|
||||
ShowEmptyGroups: showEmptyGroups,
|
||||
|
@ -23,12 +23,14 @@ export default mergeIds(viewId, view, {
|
||||
ObjectFilter: '' as AnyComponent,
|
||||
DateFilter: '' as AnyComponent,
|
||||
ValueFilter: '' as AnyComponent,
|
||||
StringFilter: '' as AnyComponent,
|
||||
TimestampFilter: '' as AnyComponent,
|
||||
FilterTypePopup: '' as AnyComponent,
|
||||
ActionsPopup: '' as AnyComponent,
|
||||
ProxyPresenter: '' as AnyComponent
|
||||
},
|
||||
string: {
|
||||
Contains: '' as IntlString,
|
||||
LabelYes: '' as IntlString,
|
||||
LabelNo: '' as IntlString,
|
||||
ChooseAColor: '' as IntlString,
|
||||
|
@ -742,6 +742,7 @@ const view = plugin(viewId, {
|
||||
FilterValueNin: '' as Ref<FilterMode>,
|
||||
FilterBefore: '' as Ref<FilterMode>,
|
||||
FilterAfter: '' as Ref<FilterMode>,
|
||||
FilterContains: '' as Ref<FilterMode>,
|
||||
FilterNestedMatch: '' as Ref<FilterMode>,
|
||||
FilterNestedDontMatch: '' as Ref<FilterMode>,
|
||||
FilterDateOutdated: '' as Ref<FilterMode>,
|
||||
|
Loading…
Reference in New Issue
Block a user