mirror of
https://github.com/hcengineering/platform.git
synced 2026-10-01 22:15:04 +02:00
Add date difference calculation functionality (#10673)
* Add date difference calculation functionality Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> * Fix Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> * Fix formatting Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> --------- Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
@@ -610,6 +610,20 @@ export function defineFunctions (builder: Builder): void {
|
||||
process.function.DateFromNumber
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
process.class.ProcessFunction,
|
||||
core.space.Model,
|
||||
{
|
||||
of: core.class.TypeDate,
|
||||
to: core.class.TypeNumber,
|
||||
category: 'attribute',
|
||||
label: process.string.DateDifference,
|
||||
type: 'convert',
|
||||
editor: process.transformEditor.DateDifferenceEditor
|
||||
},
|
||||
process.function.DateDifference
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
process.class.ProcessFunction,
|
||||
core.space.Model,
|
||||
|
||||
@@ -211,6 +211,10 @@ export function createModel (builder: Builder): void {
|
||||
func: serverProcess.transform.DayFromDate
|
||||
})
|
||||
|
||||
builder.mixin(process.function.DateDifference, process.class.ProcessFunction, serverProcess.mixin.FuncImpl, {
|
||||
func: serverProcess.transform.DateDifference
|
||||
})
|
||||
|
||||
builder.mixin(process.function.Random, process.class.ProcessFunction, serverProcess.mixin.FuncImpl, {
|
||||
func: serverProcess.transform.Random
|
||||
})
|
||||
|
||||
@@ -162,7 +162,8 @@
|
||||
"DateFromText": "Datum ze stringu",
|
||||
"YearFromDate": "Rok z data",
|
||||
"MonthFromDate": "Měsíc z data",
|
||||
"DayFromDate": "Den z data"
|
||||
"DayFromDate": "Den z data",
|
||||
"DateDifference": "Rozdíl dat"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Metoda nenalezena: {methodId}",
|
||||
|
||||
@@ -162,7 +162,8 @@
|
||||
"DateFromText": "Datum aus Text",
|
||||
"YearFromDate": "Jahr aus Datum",
|
||||
"MonthFromDate": "Monat aus Datum",
|
||||
"DayFromDate": "Tag aus Datum"
|
||||
"DayFromDate": "Tag aus Datum",
|
||||
"DateDifference": "Datumsdifferenz"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Methode nicht gefunden: {methodId}",
|
||||
|
||||
@@ -167,7 +167,8 @@
|
||||
"DateFromText": "Date from text",
|
||||
"YearFromDate": "Year from date",
|
||||
"MonthFromDate": "Month from date",
|
||||
"DayFromDate": "Day from date"
|
||||
"DayFromDate": "Day from date",
|
||||
"DateDifference": "Date difference"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Method not found: {methodId}",
|
||||
|
||||
@@ -167,7 +167,8 @@
|
||||
"DateFromText": "Fecha desde texto",
|
||||
"YearFromDate": "Año desde fecha",
|
||||
"MonthFromDate": "Mes desde fecha",
|
||||
"DayFromDate": "Día desde fecha"
|
||||
"DayFromDate": "Día desde fecha",
|
||||
"DateDifference": "Diferencia de fechas"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Método no encontrado: {methodId}",
|
||||
|
||||
@@ -167,7 +167,8 @@
|
||||
"DateFromText": "Date depuis texte",
|
||||
"YearFromDate": "Année depuis date",
|
||||
"MonthFromDate": "Mois depuis date",
|
||||
"DayFromDate": "Jour depuis date"
|
||||
"DayFromDate": "Jour depuis date",
|
||||
"DateDifference": "Différence de dates"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Méthode introuvable : {methodId}",
|
||||
|
||||
@@ -167,7 +167,8 @@
|
||||
"DateFromText": "Data da testo",
|
||||
"YearFromDate": "Anno da data",
|
||||
"MonthFromDate": "Mese da data",
|
||||
"DayFromDate": "Giorno da data"
|
||||
"DayFromDate": "Giorno da data",
|
||||
"DateDifference": "Differenza di date"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Metodo non trovato: {methodId}",
|
||||
|
||||
@@ -166,7 +166,8 @@
|
||||
"DateFromText": "テキストから日付",
|
||||
"YearFromDate": "日付から年",
|
||||
"MonthFromDate": "日付から月",
|
||||
"DayFromDate": "日付から日"
|
||||
"DayFromDate": "日付から日",
|
||||
"DateDifference": "日付の差"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "メソッドが見つかりません: {methodId}",
|
||||
|
||||
@@ -155,7 +155,8 @@
|
||||
"DateFromText": "Data de texto",
|
||||
"YearFromDate": "Ano de data",
|
||||
"MonthFromDate": "Mês de data",
|
||||
"DayFromDate": "Dia de data"
|
||||
"DayFromDate": "Dia de data",
|
||||
"DateDifference": "Diferença de datas"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Método não encontrado: {methodId}",
|
||||
|
||||
@@ -167,7 +167,8 @@
|
||||
"DateFromText": "Data de texto",
|
||||
"YearFromDate": "Ano de data",
|
||||
"MonthFromDate": "Mês de data",
|
||||
"DayFromDate": "Dia de data"
|
||||
"DayFromDate": "Dia de data",
|
||||
"DateDifference": "Diferença de datas"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Método não encontrado: {methodId}",
|
||||
|
||||
@@ -163,11 +163,12 @@
|
||||
"TextFromCheckbox": "Строка из чекбокса",
|
||||
"NumberFromDate": "Число из даты",
|
||||
"DateFromNumber": "Дата из числа",
|
||||
"NumberFromString": "Число из строки",
|
||||
"DateFromString": "Дата из строки",
|
||||
"NumberFromText": "Число из текста",
|
||||
"DateFromText": "Дата из текста",
|
||||
"YearFromDate": "Год из даты",
|
||||
"MonthFromDate": "Месяц из даты",
|
||||
"DayFromDate": "День из даты"
|
||||
"DayFromDate": "День из даты",
|
||||
"DateDifference": "Разница дат"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Метод не найден: {methodId}",
|
||||
|
||||
@@ -162,7 +162,8 @@
|
||||
"DateFromText": "Metinden tarih",
|
||||
"YearFromDate": "Tarihten yıl",
|
||||
"MonthFromDate": "Tarihten ay",
|
||||
"DayFromDate": "Tarihten gün"
|
||||
"DayFromDate": "Tarihten gün",
|
||||
"DateDifference": "Tarih farkı"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "Metod bulunamadı: {methodId}",
|
||||
|
||||
@@ -167,7 +167,8 @@
|
||||
"DateFromText": "文本到日期",
|
||||
"YearFromDate": "日期到年份",
|
||||
"MonthFromDate": "日期到月份",
|
||||
"DayFromDate": "日期到天"
|
||||
"DayFromDate": "日期到天",
|
||||
"DateDifference": "日期差异"
|
||||
},
|
||||
"error": {
|
||||
"MethodNotFound": "找不到方法:{methodId}",
|
||||
|
||||
+66
-22
@@ -165,8 +165,12 @@
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
bind:this={elements[0]}
|
||||
on:keydown={(event) => keyDown(event, 0)}
|
||||
on:mouseover={() => elements[0]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, 0)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[0]?.focus()
|
||||
}}
|
||||
on:click={() => {
|
||||
onUserRequest()
|
||||
}}
|
||||
@@ -183,8 +187,12 @@
|
||||
{#if func.editor !== undefined}
|
||||
<Submenu
|
||||
bind:element={elements[functionsOffset + i]}
|
||||
on:keydown={(event) => keyDown(event, functionsOffset + i)}
|
||||
on:mouseover={() => elements[functionsOffset + i]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, functionsOffset + i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[functionsOffset + i]?.focus()
|
||||
}}
|
||||
label={func.label}
|
||||
props={{
|
||||
masterTag,
|
||||
@@ -199,8 +207,12 @@
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
bind:this={elements[functionsOffset + i]}
|
||||
on:keydown={(event) => keyDown(event, functionsOffset + i)}
|
||||
on:mouseover={() => elements[functionsOffset + i]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, functionsOffset + i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[functionsOffset + i]?.focus()
|
||||
}}
|
||||
on:click={() => {
|
||||
onFunc(func._id)
|
||||
}}
|
||||
@@ -219,8 +231,12 @@
|
||||
{#if pc.attributes.length > 0}
|
||||
<Submenu
|
||||
bind:element={elements[processContextOffset + i]}
|
||||
on:keydown={(event) => keyDown(event, processContextOffset + i)}
|
||||
on:mouseover={() => elements[processContextOffset + i]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, processContextOffset + i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[processContextOffset + i]?.focus()
|
||||
}}
|
||||
component={ExecutionContextPresenter}
|
||||
props={{
|
||||
context: pc,
|
||||
@@ -236,8 +252,12 @@
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
bind:this={elements[processContextOffset + i]}
|
||||
on:keydown={(event) => keyDown(event, processContextOffset + i)}
|
||||
on:mouseover={() => elements[processContextOffset + i]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, processContextOffset + i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[processContextOffset + i]?.focus()
|
||||
}}
|
||||
on:click={() => {
|
||||
onProcessContext(pc)
|
||||
}}
|
||||
@@ -254,8 +274,12 @@
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
bind:this={elements[attributesOffset + i]}
|
||||
on:keydown={(event) => keyDown(event, attributesOffset + i)}
|
||||
on:mouseover={() => elements[attributesOffset + i]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, attributesOffset + i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[attributesOffset + i]?.focus()
|
||||
}}
|
||||
on:click={() => {
|
||||
onAttribute(attr)
|
||||
}}
|
||||
@@ -272,8 +296,12 @@
|
||||
{#each nested as object, i}
|
||||
<Submenu
|
||||
bind:element={elements[nestedOffset + i]}
|
||||
on:keydown={(event) => keyDown(event, nestedOffset + i)}
|
||||
on:mouseover={() => elements[nestedOffset + i]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, nestedOffset + i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[nestedOffset + i]?.focus()
|
||||
}}
|
||||
label={object.attribute.label}
|
||||
props={{
|
||||
context: object,
|
||||
@@ -292,8 +320,12 @@
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
bind:this={elements[relationsOffset + i]}
|
||||
on:keydown={(event) => keyDown(event, relationsOffset + i)}
|
||||
on:mouseover={() => elements[relationsOffset + i]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, relationsOffset + i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[relationsOffset + i]?.focus()
|
||||
}}
|
||||
on:click={() => {
|
||||
onRelation(object[1])
|
||||
}}
|
||||
@@ -306,8 +338,12 @@
|
||||
{:else}
|
||||
<Submenu
|
||||
bind:element={elements[relationsOffset + i]}
|
||||
on:keydown={(event) => keyDown(event, relationsOffset + i)}
|
||||
on:mouseover={() => elements[relationsOffset + i]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, relationsOffset + i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[relationsOffset + i]?.focus()
|
||||
}}
|
||||
text={object[1].name}
|
||||
props={{
|
||||
context: object[1],
|
||||
@@ -324,8 +360,12 @@
|
||||
{#each convertible as conv, i}
|
||||
<Submenu
|
||||
bind:element={elements[convertibleOffset + i]}
|
||||
on:keydown={(event) => keyDown(event, convertibleOffset + i)}
|
||||
on:mouseover={() => elements[convertibleOffset + i]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, convertibleOffset + i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[convertibleOffset + i]?.focus()
|
||||
}}
|
||||
label={getFunc(conv.func).label}
|
||||
props={{
|
||||
process,
|
||||
@@ -344,8 +384,12 @@
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
bind:this={elements[customValueIndex]}
|
||||
on:keydown={(event) => keyDown(event, customValueIndex)}
|
||||
on:mouseover={() => elements[customValueIndex]?.focus()}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, customValueIndex)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[customValueIndex]?.focus()
|
||||
}}
|
||||
on:click={onConst}
|
||||
class="menu-item"
|
||||
>
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
<!--
|
||||
// Copyright © 2025 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 { MasterTag, Tag } from '@hcengineering/card'
|
||||
import core, { AnyAttribute, Ref } from '@hcengineering/core'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import presentation, { Card, getClient } from '@hcengineering/presentation'
|
||||
import { Context, Process, ProcessFunction } from '@hcengineering/process'
|
||||
import ui, { AnySvelteComponent, DropdownIntlItem, DropdownLabelsIntl } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import ProcessAttribute from '../ProcessAttribute.svelte'
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
|
||||
export let func: ProcessFunction
|
||||
export let process: Process
|
||||
export let masterTag: Ref<MasterTag | Tag>
|
||||
export let context: Context
|
||||
export let attribute: AnyAttribute
|
||||
export let props: Record<string, any> = {}
|
||||
|
||||
let otherDate = props?.otherDate
|
||||
let unit = props?.unit ?? 'days'
|
||||
|
||||
const items: DropdownIntlItem[] = [
|
||||
{ id: 'hours', label: ui.string.Hours },
|
||||
{ id: 'days', label: ui.string.Days },
|
||||
{ id: 'weeks', label: ui.string.Weeks },
|
||||
{ id: 'months', label: ui.string.Months },
|
||||
{ id: 'years', label: ui.string.Years }
|
||||
]
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
const h = client.getHierarchy()
|
||||
|
||||
function save (): void {
|
||||
dispatch('close', { otherDate, unit })
|
||||
}
|
||||
|
||||
let editor: AnySvelteComponent | undefined
|
||||
|
||||
function getEditor (): void {
|
||||
try {
|
||||
const inlineEditor = h.as(h.getClass(core.class.TypeDate), view.mixin.AttributeEditor).inlineEditor
|
||||
void getResource(inlineEditor)
|
||||
.then((p) => {
|
||||
editor = p
|
||||
})
|
||||
.catch((e: any) => {
|
||||
Analytics.handleError(e)
|
||||
})
|
||||
} catch (e: any) {
|
||||
Analytics.handleError(e)
|
||||
}
|
||||
}
|
||||
|
||||
getEditor()
|
||||
</script>
|
||||
|
||||
<Card on:close width={'small'} label={func.label} canSave okAction={save} okLabel={presentation.string.Save}>
|
||||
<div class="grid">
|
||||
<ProcessAttribute
|
||||
{process}
|
||||
{masterTag}
|
||||
{context}
|
||||
attribute={{ ...attribute, label: ui.string.TargetDate }}
|
||||
presenterClass={{
|
||||
attrClass: core.class.TypeDate,
|
||||
category: 'attribute'
|
||||
}}
|
||||
value={otherDate}
|
||||
{editor}
|
||||
on:change={(e) => {
|
||||
otherDate = e.detail
|
||||
}}
|
||||
/>
|
||||
<div class="flex-row-center flex-gap-2">
|
||||
<DropdownLabelsIntl {items} bind:selected={unit} />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<style lang="scss">
|
||||
.grid {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-template-columns: 1fr;
|
||||
grid-auto-rows: minmax(1rem, max-content);
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
row-gap: 0.75rem;
|
||||
height: min-content;
|
||||
}
|
||||
</style>
|
||||
@@ -112,7 +112,8 @@ export default mergeIds(processId, process, {
|
||||
ReplaceEditor: '' as AnyComponent,
|
||||
SplitEditor: '' as AnyComponent,
|
||||
CutEditor: '' as AnyComponent,
|
||||
FilterEditor: '' as AnyComponent
|
||||
FilterEditor: '' as AnyComponent,
|
||||
DateDifferenceEditor: '' as AnyComponent
|
||||
},
|
||||
transformPresenter: {
|
||||
NumberPresenter: '' as AnyComponent,
|
||||
@@ -272,7 +273,8 @@ export default mergeIds(processId, process, {
|
||||
DateFromText: '' as IntlString,
|
||||
YearFromDate: '' as IntlString,
|
||||
MonthFromDate: '' as IntlString,
|
||||
DayFromDate: '' as IntlString
|
||||
DayFromDate: '' as IntlString,
|
||||
DateDifference: '' as IntlString
|
||||
},
|
||||
permission: {
|
||||
RunProcess: '' as Ref<Permission>,
|
||||
|
||||
@@ -320,7 +320,7 @@ function getContextFunctions (
|
||||
const matched: Array<Ref<ProcessFunction>> = []
|
||||
const hierarchy = client.getHierarchy()
|
||||
const funcs = client.getModel().findAllSync(process.class.ProcessFunction, { type: 'context' })
|
||||
for (const func of (funcs as unknown as ProcessFunction[])) {
|
||||
for (const func of funcs as unknown as ProcessFunction[]) {
|
||||
switch (category) {
|
||||
case 'array': {
|
||||
if (func.category === 'array') {
|
||||
|
||||
@@ -385,6 +385,7 @@ export default plugin(processId, {
|
||||
YearFromDate: '' as Ref<ProcessFunction>,
|
||||
MonthFromDate: '' as Ref<ProcessFunction>,
|
||||
DayFromDate: '' as Ref<ProcessFunction>,
|
||||
DateDifference: '' as Ref<ProcessFunction>,
|
||||
ExportProcess: '' as Resource<ExportFunc>,
|
||||
CheckProcessSectionVisibility: '' as Resource<(doc: Card) => Promise<boolean>>
|
||||
}
|
||||
|
||||
@@ -378,7 +378,7 @@
|
||||
: resultQuery[groupByKey]?.$in?.length !== 0
|
||||
? undefined
|
||||
: []
|
||||
: category ?? null
|
||||
: (category ?? null)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -97,7 +97,8 @@ import {
|
||||
DateFromString,
|
||||
YearFromDate,
|
||||
MonthFromDate,
|
||||
DayFromDate
|
||||
DayFromDate,
|
||||
DateDifference
|
||||
} from './transform'
|
||||
import {
|
||||
RunSubProcess,
|
||||
@@ -663,7 +664,8 @@ export default async () => ({
|
||||
DateFromString,
|
||||
YearFromDate,
|
||||
MonthFromDate,
|
||||
DayFromDate
|
||||
DayFromDate,
|
||||
DateDifference
|
||||
},
|
||||
rollbacks: {
|
||||
ToDoCloseRollback,
|
||||
|
||||
@@ -246,6 +246,34 @@ export function Offset (val: Timestamp, props: Record<string, any>): Timestamp {
|
||||
return val
|
||||
}
|
||||
|
||||
export async function DateDifference (
|
||||
value: Timestamp,
|
||||
props: Record<string, any>,
|
||||
control: ProcessControl,
|
||||
execution: Execution
|
||||
): Promise<number> {
|
||||
if (typeof value !== 'number') return 0
|
||||
const otherDate = await getContextValue(props.otherDate, control, execution)
|
||||
if (typeof otherDate !== 'number') return 0
|
||||
|
||||
const diff = value - otherDate
|
||||
const v = new Date(value)
|
||||
const o = new Date(otherDate)
|
||||
switch (props.unit) {
|
||||
case 'hours':
|
||||
return Math.floor(diff / (1000 * 60 * 60))
|
||||
case 'weeks':
|
||||
return Math.floor(diff / (1000 * 60 * 60 * 24 * 7))
|
||||
case 'months':
|
||||
return (v.getUTCFullYear() - o.getUTCFullYear()) * 12 + (v.getUTCMonth() - o.getUTCMonth())
|
||||
case 'years':
|
||||
return v.getUTCFullYear() - o.getUTCFullYear()
|
||||
case 'days':
|
||||
default:
|
||||
return Math.floor(diff / (1000 * 60 * 60 * 24))
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Numbers
|
||||
@@ -508,4 +536,3 @@ export function DayFromDate (value: Date): number {
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
|
||||
@@ -123,7 +123,8 @@ export default plugin(serverProcessId, {
|
||||
DateFromString: '' as Resource<TransformFunc>,
|
||||
YearFromDate: '' as Resource<TransformFunc>,
|
||||
MonthFromDate: '' as Resource<TransformFunc>,
|
||||
DayFromDate: '' as Resource<TransformFunc>
|
||||
DayFromDate: '' as Resource<TransformFunc>,
|
||||
DateDifference: '' as Resource<TransformFunc>
|
||||
},
|
||||
trigger: {
|
||||
OnTransition: '' as Resource<TriggerFunc>,
|
||||
|
||||
Reference in New Issue
Block a user