From 16da75f6d8eea85433da986921e9ec04bd34bb2c Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Mon, 8 May 2023 21:52:49 +0600 Subject: [PATCH] =?UTF-8?q?TSK-1411=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=20=D1=81=20=D0=B4=D0=B0=D1=82=D0=B0=D0=BC=D0=B8=20(#3151?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Denis Bykhov --- models/tracker/src/index.ts | 4 - models/view/src/index.ts | 91 ++++- models/view/src/plugin.ts | 8 + .../components/calendar/DateInputBox.svelte | 366 ++++++++++++++++++ .../src/components/calendar/DatePopup.svelte | 360 ++--------------- .../components/calendar/MonthSquare.svelte | 48 ++- .../components/calendar/RangeDatePopup.svelte | 209 ++++++++++ packages/ui/src/index.ts | 1 + plugins/view-assets/lang/en.json | 10 +- plugins/view-assets/lang/ru.json | 10 +- .../src/components/filter/DateFilter.svelte | 178 +++------ .../components/filter/FilterSection.svelte | 21 +- .../src/components/filter/ModeSelector.svelte | 40 ++ plugins/view-resources/src/filter.ts | 62 +++ plugins/view-resources/src/index.ts | 18 +- plugins/view-resources/src/plugin.ts | 10 +- plugins/view/src/index.ts | 10 +- 17 files changed, 964 insertions(+), 482 deletions(-) create mode 100644 packages/ui/src/components/calendar/DateInputBox.svelte create mode 100644 packages/ui/src/components/calendar/RangeDatePopup.svelte create mode 100644 plugins/view-resources/src/components/filter/ModeSelector.svelte diff --git a/models/tracker/src/index.ts b/models/tracker/src/index.ts index b56e59998d..9a3478d603 100644 --- a/models/tracker/src/index.ts +++ b/models/tracker/src/index.ts @@ -914,10 +914,6 @@ export function createModel (builder: Builder): void { component: view.component.ValueFilter }) - builder.mixin(core.class.TypeDate, core.class.Class, view.mixin.AttributeFilter, { - component: view.component.DateFilter - }) - builder.mixin(tracker.class.TypeIssuePriority, core.class.Class, view.mixin.AttributePresenter, { presenter: tracker.component.PriorityRefPresenter }) diff --git a/models/view/src/index.ts b/models/view/src/index.ts index f2beedf910..87ec8ab4e0 100644 --- a/models/view/src/index.ts +++ b/models/view/src/index.ts @@ -669,7 +669,7 @@ export function createModel (builder: Builder): void { }) builder.mixin(core.class.TypeDate, core.class.Class, view.mixin.AttributeFilter, { - component: view.component.ValueFilter + component: view.component.DateFilter }) builder.mixin(core.class.EnumOf, core.class.Class, view.mixin.AttributeFilter, { @@ -681,7 +681,7 @@ export function createModel (builder: Builder): void { }) builder.mixin(core.class.TypeTimestamp, core.class.Class, view.mixin.AttributeFilter, { - component: view.component.TimestampFilter + component: view.component.DateFilter }) builder.createDoc( @@ -764,6 +764,93 @@ export function createModel (builder: Builder): void { view.filter.FilterNestedDontMatch ) + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.Overdue, + result: view.function.FilterDateOutdated, + disableValueSelector: true + }, + view.filter.FilterDateOutdated + ) + + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.Today, + result: view.function.FilterDateToday, + disableValueSelector: true + }, + view.filter.FilterDateToday + ) + + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.ThisWeek, + result: view.function.FilterDateWeek, + disableValueSelector: true + }, + view.filter.FilterDateWeek + ) + + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.NextWeek, + result: view.function.FilterDateNextWeek, + disableValueSelector: true + }, + view.filter.FilterDateNextW + ) + + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.ThisMonth, + result: view.function.FilterDateMonth, + disableValueSelector: true + }, + view.filter.FilterDateM + ) + + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.NextMonth, + result: view.function.FilterDateNextMonth, + disableValueSelector: true + }, + view.filter.FilterDateNextM + ) + + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.CustomDate, + result: view.function.FilterDateCustom + }, + view.filter.FilterDateCustom + ) + + builder.createDoc( + view.class.FilterMode, + core.space.Model, + { + label: view.string.NotSpecified, + result: view.function.FilterDateNotSpecified, + disableValueSelector: true + }, + view.filter.FilterDateNotSpecified + ) + classPresenter(builder, core.class.EnumOf, view.component.EnumPresenter, view.component.EnumEditor) // createAction( diff --git a/models/view/src/plugin.ts b/models/view/src/plugin.ts index 7c2a2998a0..fc8be053c9 100644 --- a/models/view/src/plugin.ts +++ b/models/view/src/plugin.ts @@ -104,6 +104,14 @@ export default mergeIds(viewId, view, { FilterAfterResult: '' as FilterFunction, FilterNestedMatchResult: '' as FilterFunction, FilterNestedDontMatchResult: '' as FilterFunction, + FilterDateOutdated: '' as FilterFunction, + FilterDateToday: '' as FilterFunction, + FilterDateWeek: '' as FilterFunction, + FilterDateNextWeek: '' as FilterFunction, + FilterDateMonth: '' as FilterFunction, + FilterDateNextMonth: '' as FilterFunction, + FilterDateNotSpecified: '' as FilterFunction, + FilterDateCustom: '' as FilterFunction, ShowEmptyGroups: '' as ViewCategoryAction } }) diff --git a/packages/ui/src/components/calendar/DateInputBox.svelte b/packages/ui/src/components/calendar/DateInputBox.svelte new file mode 100644 index 0000000000..2625e0928d --- /dev/null +++ b/packages/ui/src/components/calendar/DateInputBox.svelte @@ -0,0 +1,366 @@ + + + +
+
+ keyDown(ev, edits[0].id)} + on:focus={() => focused(edits[0].id)} + on:blur={() => (selected = null)} + > + {#if edits[0].value > -1} + {edits[0].value.toString().padStart(2, '0')} + {:else} + . + keyDown(ev, edits[1].id)} + on:focus={() => focused(edits[1].id)} + on:blur={() => (selected = null)} + > + {#if edits[1].value > -1} + {edits[1].value.toString().padStart(2, '0')} + {:else} + . + keyDown(ev, edits[2].id)} + on:focus={() => focused(edits[2].id)} + on:blur={() => (selected = null)} + > + {#if edits[2].value > -1} + {edits[2].value.toString().padStart(4, '0')} + {:else} + {#if withTime} +
+ keyDown(ev, edits[3].id)} + on:focus={() => focused(edits[3].id)} + on:blur={() => (selected = null)} + > + {#if edits[3].value > -1} + {edits[3].value.toString().padStart(2, '0')} + {:else} + : + keyDown(ev, edits[4].id)} + on:focus={() => focused(edits[4].id)} + on:blur={() => (selected = null)} + > + {#if edits[4].value > -1} + {edits[4].value.toString().padStart(2, '0')} + {:else} + {/if} +
+ {#if currentDate} +
{ + selected = 'day' + startTyping = true + currentDate = null + clearEdits() + }} + on:blur={() => (selected = null)} + > + +
+ {/if} +
+ + diff --git a/packages/ui/src/components/calendar/DatePopup.svelte b/packages/ui/src/components/calendar/DatePopup.svelte index c85cb5dfef..61f25f3811 100644 --- a/packages/ui/src/components/calendar/DatePopup.svelte +++ b/packages/ui/src/components/calendar/DatePopup.svelte @@ -1,30 +1,29 @@
@@ -254,91 +99,13 @@ {/if}
-
-
- keyDown(ev, edits[0].id)} - on:focus={() => focused(edits[0].id)} - on:blur={() => (selected = null)} - > - {#if edits[0].value > -1} - {edits[0].value.toString().padStart(2, '0')} - {:else} - . - keyDown(ev, edits[1].id)} - on:focus={() => focused(edits[1].id)} - on:blur={() => (selected = null)} - > - {#if edits[1].value > -1} - {edits[1].value.toString().padStart(2, '0')} - {:else} - . - keyDown(ev, edits[2].id)} - on:focus={() => focused(edits[2].id)} - on:blur={() => (selected = null)} - > - {#if edits[2].value > -1} - {edits[2].value.toString().padStart(4, '0')} - {:else} - {#if withTime} -
- keyDown(ev, edits[3].id)} - on:focus={() => focused(edits[3].id)} - on:blur={() => (selected = null)} - > - {#if edits[3].value > -1} - {edits[3].value.toString().padStart(2, '0')} - {:else} - : - keyDown(ev, edits[4].id)} - on:focus={() => focused(edits[4].id)} - on:blur={() => (selected = null)} - > - {#if edits[4].value > -1} - {edits[4].value.toString().padStart(2, '0')} - {:else} - {/if} -
- {#if currentDate} -
{ - selected = 'day' - startTyping = true - currentDate = null - clearEdits() - }} - on:blur={() => (selected = null)} - > - -
- {/if} -
+ closeDP(withTime)} + on:save={() => saveDate(withTime)} + />
diff --git a/packages/ui/src/components/calendar/MonthSquare.svelte b/packages/ui/src/components/calendar/MonthSquare.svelte index c65146307a..ce7c2678b6 100644 --- a/packages/ui/src/components/calendar/MonthSquare.svelte +++ b/packages/ui/src/components/calendar/MonthSquare.svelte @@ -25,6 +25,7 @@ export let hideNavigator: boolean = false export let viewUpdate: boolean = true export let displayedWeeksCount = 6 + export let selectedTo: Date | null | undefined = undefined const dispatch = createEventDispatcher() @@ -33,14 +34,24 @@ const today: Date = new Date(Date.now()) const capitalizeFirstLetter = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1) - if (viewDate === undefined) viewDate = currentDate ?? today afterUpdate(() => { - if (currentDate && viewUpdate) viewDate = currentDate - if (viewDate) { - monthYear = capitalizeFirstLetter(getMonthName(viewDate)) + ' ' + viewDate.getFullYear() - firstDayOfCurrentMonth = firstDay(viewDate, mondayStart) - } + monthYear = capitalizeFirstLetter(getMonthName(viewDate)) + ' ' + viewDate.getFullYear() + firstDayOfCurrentMonth = firstDay(viewDate, mondayStart) }) + + function inRange (currentDate: Date | null, selectedTo: Date | null | undefined, target: Date): boolean { + if (currentDate == null || selectedTo == null) return false + if (areDatesEqual(currentDate, selectedTo)) return false + const startDate = currentDate < selectedTo ? currentDate : selectedTo + const endDate = currentDate > selectedTo ? currentDate : selectedTo + return target > startDate && target < endDate + } + + function isSelected (currentDate: Date | null, selectedTo: Date | null | undefined, target: Date): boolean { + if (currentDate != null && areDatesEqual(currentDate, target)) return true + if (selectedTo != null && areDatesEqual(selectedTo, target)) return true + return false + }
@@ -52,7 +63,7 @@ class="btn" on:click={() => { if (viewUpdate) viewDate.setMonth(viewDate.getMonth() - 1) - dispatch('navigation', '-m') + dispatch('navigation', -1) }} >
@@ -61,7 +72,7 @@ class="btn" on:click={() => { if (viewUpdate) viewDate.setMonth(viewDate.getMonth() + 1) - dispatch('navigation', '+m') + dispatch('navigation', 1) }} >
@@ -80,14 +91,14 @@ {#each [...Array(displayedWeeksCount).keys()] as weekIndex} {#each [...Array(7).keys()] as dayOfWeek} - {@const wrongM = weekday(firstDayOfCurrentMonth, weekIndex, dayOfWeek).getMonth() !== viewDate.getMonth()} + {@const date = weekday(firstDayOfCurrentMonth, weekIndex, dayOfWeek)} + {@const wrongM = date.getMonth() !== viewDate.getMonth()}
{ @@ -95,7 +106,7 @@ ev.preventDefault() return } - viewDate = weekday(firstDayOfCurrentMonth, weekIndex, dayOfWeek) + viewDate = new Date(date) if (currentDate) { viewDate.setHours(currentDate.getHours()) viewDate.setMinutes(currentDate.getMinutes()) @@ -103,7 +114,7 @@ dispatch('update', viewDate) }} > - {weekday(firstDayOfCurrentMonth, weekIndex, dayOfWeek).getDate()} + {date.getDate()}
{/each} {/each} @@ -213,6 +224,11 @@ background-color: var(--primary-bg-color); } + &.range:not(.wrongMonth) { + color: var(--caption-color); + background-color: var(--primary-button-disabled); + } + &:before { content: ''; position: absolute; diff --git a/packages/ui/src/components/calendar/RangeDatePopup.svelte b/packages/ui/src/components/calendar/RangeDatePopup.svelte new file mode 100644 index 0000000000..b7c2ff8d02 --- /dev/null +++ b/packages/ui/src/components/calendar/RangeDatePopup.svelte @@ -0,0 +1,209 @@ + + + +
+
+ + { + dispatch('close', {}) + }} + /> +
+
+
+
+ +
+
+ +
+
+ +
+ updateDate(result.detail)} + /> + updateDate(result.detail)} + on:navigation={(result) => navigateMonth(result.detail)} + /> +
+
+ +
+ + diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index aecfded413..7a05a65c3c 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -67,6 +67,7 @@ export { default as Section } from './components/Section.svelte' export { default as DatePicker } from './components/calendar/DatePicker.svelte' export { default as DateRangePicker } from './components/calendar/DateRangePicker.svelte' export { default as DatePopup } from './components/calendar/DatePopup.svelte' +export { default as RangeDatePopup } from './components/calendar/RangeDatePopup.svelte' export { default as DateRangePopup } from './components/calendar/DateRangePopup.svelte' export { default as TimePopup } from './components/calendar/TimePopup.svelte' export { default as DateRangePresenter } from './components/calendar/DateRangePresenter.svelte' diff --git a/plugins/view-assets/lang/en.json b/plugins/view-assets/lang/en.json index 6adedec38e..5bc5cc6702 100644 --- a/plugins/view-assets/lang/en.json +++ b/plugins/view-assets/lang/en.json @@ -67,6 +67,14 @@ "ShowPreviewOnClick": "Please click to show document index preview...", "Shown": "Shown", "Total": "Total", - "ShowEmptyGroups": "Show empty groups" + "ShowEmptyGroups": "Show empty groups", + "Overdue": "Overdue", + "Today": "Today", + "ThisWeek": "This week", + "NextWeek": "Next week", + "ThisMonth": "This month", + "NextMonth": "Next month", + "NotSpecified": "Not specified", + "CustomDate": "Custom date" } } diff --git a/plugins/view-assets/lang/ru.json b/plugins/view-assets/lang/ru.json index 59ba4560ff..ff46c26ee4 100644 --- a/plugins/view-assets/lang/ru.json +++ b/plugins/view-assets/lang/ru.json @@ -64,6 +64,14 @@ "ShowPreviewOnClick": "Пожалуйста нажмите чтобы увидеть предпросмотр...", "Shown": "Показано", "Total": "Всего", - "ShowEmptyGroups": "Показывать пустые группы" + "ShowEmptyGroups": "Показывать пустые группы", + "Overdue": "Overdue", + "Today": "Сегодня", + "ThisWeek": "Эта неделя", + "NextWeek": "Следующая неделя", + "ThisMonth": "Этот месяц", + "NextMonth": "Следующий месяц", + "NotSpecified": "Не указана", + "CustomDate": "Выбранная дата" } } diff --git a/plugins/view-resources/src/components/filter/DateFilter.svelte b/plugins/view-resources/src/components/filter/DateFilter.svelte index 13ed6e6927..16392ac76c 100644 --- a/plugins/view-resources/src/components/filter/DateFilter.svelte +++ b/plugins/view-resources/src/components/filter/DateFilter.svelte @@ -13,138 +13,82 @@ // limitations under the License. --> -
dispatch('changeContent')}> -
-
- {#await promise then attribute} - {#if objectsPromise} - - {:else} - {#each Array.from(values.keys()) as value} - {@const realValue = [...(realValues.get(value) ?? [])][0]} - - {/each} - {/if} - {/await} -
-
-
+{/if} diff --git a/plugins/view-resources/src/components/filter/FilterSection.svelte b/plugins/view-resources/src/components/filter/FilterSection.svelte index 06a27e01b7..c005ae2b86 100644 --- a/plugins/view-resources/src/components/filter/FilterSection.svelte +++ b/plugins/view-resources/src/components/filter/FilterSection.svelte @@ -22,6 +22,7 @@ import { Filter, FilterMode } from '@hcengineering/view' import { createEventDispatcher, onDestroy } from 'svelte' import view from '../../plugin' + import ModeSelector from './ModeSelector.svelte' export let filter: Filter @@ -89,6 +90,22 @@ $: modeValuePromise = getMode(filter.mode) $: nestedModeValuePromise = filter.nested ? getMode(filter.nested.mode) : undefined + + function clickHandler (e: MouseEvent, nested: boolean) { + const curr = nested && filter.nested ? filter.nested : filter + if (curr.modes.length <= 2) { + toggle() + } else { + showPopup(ModeSelector, { filter: curr }, eventToHTMLElement(e), (res) => { + if (nested && filter.nested) { + filter.nested.mode = res + } else { + filter.mode = res + } + dispatch('change') + }) + } + }
@@ -102,8 +119,8 @@