diff --git a/packages/nc-gui/assets/nc-icons/at-sign.svg b/packages/nc-gui/assets/nc-icons/at-sign.svg new file mode 100644 index 0000000000..3f371823d7 --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/at-sign.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/nc-gui/assets/nc-icons/strike-through.svg b/packages/nc-gui/assets/nc-icons/strike-through.svg new file mode 100644 index 0000000000..26cff0ca23 --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/strike-through.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/nc-gui/components/cell/DatePicker.vue b/packages/nc-gui/components/cell/DatePicker.vue index ab5b0cd2ca..878ab83887 100644 --- a/packages/nc-gui/components/cell/DatePicker.vue +++ b/packages/nc-gui/components/cell/DatePicker.vue @@ -29,6 +29,8 @@ const isGrid = inject(IsGridInj, ref(false)) const isForm = inject(IsFormInj, ref(false)) +const isSurveyForm = inject(IsSurveyFormInj, ref(false)) + const isExpandedForm = inject(IsExpandedFormOpenInj, ref(false)) const isDateInvalid = ref(false) @@ -43,6 +45,8 @@ const isClearedInputMode = ref(false) const open = ref(false) +const tempDate = ref() + const localState = computed({ get() { if (!modelValue || isClearedInputMode.value) { @@ -56,7 +60,9 @@ const localState = computed({ const format = picker.value === 'month' ? dateFormat : 'YYYY-MM-DD' - return dayjs(/^\d+$/.test(modelValue) ? +modelValue : modelValue, format) + const value = dayjs(/^\d+$/.test(modelValue) ? +modelValue : modelValue, format) + + return value }, set(val?: dayjs.Dayjs) { isClearedInputMode.value = false @@ -79,20 +85,36 @@ const localState = computed({ }, }) +watchEffect(() => { + if (localState.value) { + tempDate.value = localState.value + } +}) + const randomClass = `picker_${Math.floor(Math.random() * 99999)}` onClickOutside(datePickerRef, (e) => { - if ((e.target as HTMLElement)?.closest(`.${randomClass}`)) return + if ((e.target as HTMLElement)?.closest(`.${randomClass}, .nc-${randomClass}`)) return + datePickerRef.value?.blur?.() open.value = false }) const onBlur = (e) => { - if ((e?.relatedTarget as HTMLElement)?.closest(`.${randomClass}`)) return + if ( + (e?.relatedTarget as HTMLElement)?.closest(`.${randomClass}, .nc-${randomClass}`) || + (e?.target as HTMLElement)?.closest(`.${randomClass}, .nc-${randomClass}`) + ) { + return + } open.value = false } +const onFocus = () => { + open.value = true +} + watch( open, (next) => { @@ -165,14 +187,20 @@ const clickHandler = () => { cellClickHandler() } -const handleKeydown = (e: KeyboardEvent) => { - if (e.key !== 'Enter') { +const handleKeydown = (e: KeyboardEvent, _open?: boolean) => { + if (e.key !== 'Enter' && e.key !== 'Tab') { e.stopPropagation() } switch (e.key) { case 'Enter': - open.value = !open.value + e.preventDefault() + if (isSurveyForm.value) { + e.stopPropagation() + } + localState.value = tempDate.value + open.value = !_open + if (!open.value) { editable.value = false if (isGrid.value && !isExpandedForm.value && !isEditColumn.value) { @@ -181,7 +209,7 @@ const handleKeydown = (e: KeyboardEvent) => { } return case 'Escape': - if (open.value) { + if (_open) { open.value = false editable.value = false if (isGrid.value && !isExpandedForm.value && !isEditColumn.value) { @@ -193,9 +221,18 @@ const handleKeydown = (e: KeyboardEvent) => { datePickerRef.value?.blur?.() } + return + + case 'Tab': + open.value = false + if (isGrid.value) { + editable.value = false + datePickerRef.value?.blur?.() + } + return default: - if (!open.value && /^[0-9a-z]$/i.test(e.key)) { + if (!_open && /^[0-9a-z]$/i.test(e.key)) { open.value = true } } @@ -232,32 +269,87 @@ useEventListener(document, 'keydown', (e: KeyboardEvent) => { } } }) + +const handleUpdateValue = (e: Event) => { + const targetValue = (e.target as HTMLInputElement).value + if (!targetValue) { + tempDate.value = undefined + return + } + const value = dayjs(targetValue, dateFormat.value) + + if (value.isValid()) { + tempDate.value = value + } +} + +function handleSelectDate(value?: dayjs.Dayjs) { + tempDate.value = value + localState.value = value + open.value = false +} diff --git a/packages/nc-gui/components/cell/DateTimePicker.vue b/packages/nc-gui/components/cell/DateTimePicker.vue index 7a5e3a542c..78cd8e3c1b 100644 --- a/packages/nc-gui/components/cell/DateTimePicker.vue +++ b/packages/nc-gui/components/cell/DateTimePicker.vue @@ -1,6 +1,6 @@ diff --git a/packages/nc-gui/components/cell/TimePicker.vue b/packages/nc-gui/components/cell/TimePicker.vue index d2b273099b..96627b52c2 100644 --- a/packages/nc-gui/components/cell/TimePicker.vue +++ b/packages/nc-gui/components/cell/TimePicker.vue @@ -1,6 +1,6 @@ - - diff --git a/packages/nc-gui/components/cell/YearPicker.vue b/packages/nc-gui/components/cell/YearPicker.vue index d2f3f50aca..e4ae1b5c21 100644 --- a/packages/nc-gui/components/cell/YearPicker.vue +++ b/packages/nc-gui/components/cell/YearPicker.vue @@ -27,6 +27,8 @@ const isGrid = inject(IsGridInj, ref(false)) const isForm = inject(IsFormInj, ref(false)) +const isSurveyForm = inject(IsSurveyFormInj, ref(false)) + const isExpandedForm = inject(IsExpandedFormOpenInj, ref(false)) const isYearInvalid = ref(false) @@ -39,6 +41,8 @@ const { t } = useI18n() const open = ref(false) +const tempDate = ref() + const localState = computed({ get() { if (!modelValue || isClearedInputMode.value) { @@ -69,16 +73,27 @@ const localState = computed({ }, }) +watchEffect(() => { + if (localState.value) { + tempDate.value = localState.value + } +}) + const randomClass = `picker_${Math.floor(Math.random() * 99999)}` onClickOutside(datePickerRef, (e) => { - if ((e.target as HTMLElement)?.closest(`.${randomClass}`)) return + if ((e.target as HTMLElement)?.closest(`.${randomClass}, .nc-${randomClass}`)) return datePickerRef.value?.blur?.() open.value = false }) const onBlur = (e) => { - if ((e?.relatedTarget as HTMLElement)?.closest(`.${randomClass}`)) return + if ( + (e?.relatedTarget as HTMLElement)?.closest(`.${randomClass}, .nc-${randomClass}`) || + (e?.target as HTMLElement)?.closest(`.${randomClass}, .nc-${randomClass}`) + ) { + return + } open.value = false } @@ -136,14 +151,20 @@ const clickHandler = () => { open.value = active.value || editable.value } -const handleKeydown = (e: KeyboardEvent) => { - if (e.key !== 'Enter') { +const handleKeydown = (e: KeyboardEvent, _open?: boolean) => { + if (e.key !== 'Enter' && e.key !== 'Tab') { e.stopPropagation() } switch (e.key) { case 'Enter': - open.value = !open.value + e.preventDefault() + if (isSurveyForm.value) { + e.stopPropagation() + } + + localState.value = tempDate.value + open.value = !_open if (!open.value) { editable.value = false if (isGrid.value && !isExpandedForm.value && !isEditColumn.value) { @@ -151,9 +172,19 @@ const handleKeydown = (e: KeyboardEvent) => { } } + return + + case 'Tab': + open.value = false + + if (isGrid.value) { + editable.value = false + datePickerRef.value?.blur?.() + } + return case 'Escape': - if (open.value) { + if (_open) { open.value = false editable.value = false if (isGrid.value && !isExpandedForm.value && !isEditColumn.value) { @@ -166,7 +197,7 @@ const handleKeydown = (e: KeyboardEvent) => { } return default: - if (!open.value && /^[0-9a-z]$/i.test(e.key)) { + if (!_open && /^[0-9a-z]$/i.test(e.key)) { open.value = true } } @@ -203,31 +234,77 @@ useEventListener(document, 'keydown', (e: KeyboardEvent) => { } } }) + +const handleUpdateValue = (e: Event) => { + const targetValue = (e.target as HTMLInputElement).value + if (!targetValue) { + tempDate.value = undefined + return + } + const value = dayjs(targetValue, 'YYYY') + + if (value.isValid()) { + tempDate.value = value + } +} + +function handleSelectDate(value?: dayjs.Dayjs) { + tempDate.value = value + localState.value = value + open.value = false +} diff --git a/packages/nc-gui/components/cmd-l/index.vue b/packages/nc-gui/components/cmd-l/index.vue index 51669af838..017f07f6d6 100644 --- a/packages/nc-gui/components/cmd-l/index.vue +++ b/packages/nc-gui/components/cmd-l/index.vue @@ -219,7 +219,7 @@ onMounted(() => {
- + -
+
diff --git a/packages/nc-gui/components/dashboard/settings/Metadata.vue b/packages/nc-gui/components/dashboard/settings/Metadata.vue index 604eba5103..7fc4dbc05b 100644 --- a/packages/nc-gui/components/dashboard/settings/Metadata.vue +++ b/packages/nc-gui/components/dashboard/settings/Metadata.vue @@ -108,8 +108,8 @@ const columns = [