diff --git a/packages/nc-gui/assets/img/brand/nocodb-logo.svg b/packages/nc-gui/assets/img/brand/nocodb-logo.svg new file mode 100644 index 0000000000..7d18941552 --- /dev/null +++ b/packages/nc-gui/assets/img/brand/nocodb-logo.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/nc-gui/assets/img/form-banner-left.png b/packages/nc-gui/assets/img/form-banner-left.png new file mode 100644 index 0000000000..793bd374fb Binary files /dev/null and b/packages/nc-gui/assets/img/form-banner-left.png differ diff --git a/packages/nc-gui/assets/img/form-banner-right.png b/packages/nc-gui/assets/img/form-banner-right.png new file mode 100644 index 0000000000..09360b21d3 Binary files /dev/null and b/packages/nc-gui/assets/img/form-banner-right.png differ diff --git a/packages/nc-gui/assets/style.scss b/packages/nc-gui/assets/style.scss index c4c43b762b..f3330b1469 100644 --- a/packages/nc-gui/assets/style.scss +++ b/packages/nc-gui/assets/style.scss @@ -613,7 +613,7 @@ a { } .nc-click-transition { - @apply transform transition-transform transition-color !text-gray-400 !hover:(scale-130 !text-gray-500) !active:(scale-100 !text-gray-500); + @apply transform transition-transform transition-colors !text-gray-400 !hover:(scale-130 !text-gray-500) !active:(scale-100 !text-gray-500); } .nc-click-transition-1 { diff --git a/packages/nc-gui/components/cell/Json.vue b/packages/nc-gui/components/cell/Json.vue index 027895e949..e39ff2e06c 100644 --- a/packages/nc-gui/components/cell/Json.vue +++ b/packages/nc-gui/components/cell/Json.vue @@ -185,6 +185,7 @@ watch(isExpanded, () => { :hide-minimap="true" :disable-deep-compare="true" @update:model-value="localValue = $event" + @keydown.enter.stop /> diff --git a/packages/nc-gui/components/cell/TextArea.vue b/packages/nc-gui/components/cell/TextArea.vue index 606fe8c549..42ee3a4a33 100644 --- a/packages/nc-gui/components/cell/TextArea.vue +++ b/packages/nc-gui/components/cell/TextArea.vue @@ -61,7 +61,7 @@ const mousePosition = ref< const isDragging = ref(false) const focus: VNodeRef = (el) => - !isExpandedFormOpen.value && !isEditColumn.value && isForm.value && (el as HTMLTextAreaElement)?.focus() + !isExpandedFormOpen.value && !isEditColumn.value && !isForm.value && (el as HTMLTextAreaElement)?.focus() const height = computed(() => { if (isExpandedFormOpen.value) return 36 * 4 @@ -226,7 +226,7 @@ watch(inputWrapperRef, () => { v-else-if="editEnabled && !isVisible" :ref="focus" v-model="vModel" - rows="4" + :rows="isForm ? 5 : 4" class="h-full w-full outline-none border-none nc-scrollbar-lg" :class="{ 'p-2': editEnabled, @@ -234,7 +234,7 @@ watch(inputWrapperRef, () => { 'px-2': isExpandedFormOpen, }" :style="{ - minHeight: `${height}px`, + minHeight: isForm ? '117px' : `${height}px`, }" :placeholder="isEditColumn ? $t('labels.optional') : ''" :disabled="readOnly" @@ -270,7 +270,7 @@ watch(inputWrapperRef, () => { {{ $t('title.expand') }} @@ -296,6 +296,7 @@ watch(inputWrapperRef, () => { :class="{ 'cursor-move': isDragging, }" + @keydown.enter.stop > { v-if="isEditing" :ref="focusInput" v-model:value="_title" - class="!bg-transparent !border-0 !ring-0 !outline-transparent !border-transparent" + class="!bg-transparent !border-0 !ring-0 !outline-transparent !border-transparent !pl-0" :class="{ 'font-medium': activeView?.id === vModel.id, }" diff --git a/packages/nc-gui/components/dlg/share-and-collaborate/SharePage.vue b/packages/nc-gui/components/dlg/share-and-collaborate/SharePage.vue index 46354817f5..ebc85cc9ca 100644 --- a/packages/nc-gui/components/dlg/share-and-collaborate/SharePage.vue +++ b/packages/nc-gui/components/dlg/share-and-collaborate/SharePage.vue @@ -1,7 +1,6 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/nc-gui/components/general/FormBranding.vue b/packages/nc-gui/components/general/FormBranding.vue new file mode 100644 index 0000000000..2bb11c0f11 --- /dev/null +++ b/packages/nc-gui/components/general/FormBranding.vue @@ -0,0 +1,13 @@ + + + + + + NocoDB Forms + + diff --git a/packages/nc-gui/components/smartsheet/Cell.vue b/packages/nc-gui/components/smartsheet/Cell.vue index 5405586f88..1d3d525be2 100644 --- a/packages/nc-gui/components/smartsheet/Cell.vue +++ b/packages/nc-gui/components/smartsheet/Cell.vue @@ -204,7 +204,7 @@ onUnmounted(() => { 'nc-grid-numeric-cell-right': isGrid && isNumericField && !isEditColumnMenu && !isForm && !isExpandedFormOpen, 'h-10': isForm && !isSurveyForm && !isAttachment(column) && !props.virtual, 'nc-grid-numeric-cell-left': (isForm && isNumericField && isExpandedFormOpen) || isEditColumnMenu, - '!min-h-30 resize-y': isTextArea(column) && (isForm || isSurveyForm), + '!min-h-30': isTextArea(column) && (isForm || isSurveyForm), }, ]" class="nc-cell w-full h-full relative" diff --git a/packages/nc-gui/components/smartsheet/Form.vue b/packages/nc-gui/components/smartsheet/Form.vue index 9418a28734..daba5f6658 100644 --- a/packages/nc-gui/components/smartsheet/Form.vue +++ b/packages/nc-gui/components/smartsheet/Form.vue @@ -1,5 +1,9 @@ - - - - {{ $t('general.available') }}{{ $t('title.inDesktop') }} - - - {{ $t('msg.formViewNotSupportedOnMobile') }} - - - - - - - - - - - {{ formViewData.success_msg || $t('msg.successfullySubmittedFormData') }} - - - - - - {{ - $t('msg.newFormWillBeLoaded', { - seconds: secondsRemain, - }) - }} - - - - {{ $t('activity.submitAnotherForm') }} - + + + + + {{ $t('general.available') }}{{ $t('title.inDesktop') }} - - - - - - - - {{ $t('objects.fields') }} - - - - - - {{ $t('general.addAll') }} - - - - - {{ $t('general.removeAll') }} - - + + {{ $t('msg.formViewNotSupportedOnMobile') }} - - + + + + + + - - - - - + + + + {{ formViewData.heading }} + - + + {{ formViewData.subheading }} + + + + + + + + + {{ formViewData.success_msg || $t('msg.successfullySubmittedFormData') }} + + + + + + {{ + $t('msg.newFormWillBeLoaded', { + seconds: secondsRemain, + }) + }} - - - - - - - {{ $t('msg.info.dragDropHide') }} + + + {{ $t('activity.submitAnotherForm') }} + + + - - - - - - - - {{ $t('activity.addField') }} - - - - - - - - - - - - - - - + + - + + - - - - - - - - - - {{ formViewData.heading }} - - - - - - - - - - - {{ formViewData.subheading || '---' }} - + + + + - - + + + + + + + - - + - - - - - { - element.required = !element.required - updateColMeta(element) - } - " - > - {{ $t('general.required') }} - - - - - - - - { - element.general.enable_scanner = !element.general.enable_scanner - updateColMeta(element) - } - " - > - {{ $t('general.enableScanner') }} - + - - - - - - - - - - - - + + {{ formViewData.heading }} + - - + + + + - + + {{ formViewData.subheading || '---' }} + + - + + - - - - - + + + {{ element.label || element.title }} + + * + + + + {{ element.description }} + + + + + + - - + + + + + + {{ element.title }} + + {{ element.title }} + + + * + + + + { + element.required = !element.required + updateColMeta(element) + } + " + > + {{ $t('general.required') }} + + + + + - - {{ element.description }} + + + + + + + + + + + + + + + { + element.general.enable_scanner = !element.general.enable_scanner + updateColMeta(element) + } + " + > + {{ $t('general.enableScanner') }} + + + + + + + { + isTabPressed = false + if (activeRow !== element.title) { + activeRow = '' + } + } + " + > + + + + + + + + + + + + + + + {{ $t('labels.showOnConditions') }} + {{ $t('labels.showFieldOnConditionsMet') }} + + + + + + + + + {{ $t('title.selectFieldsFromRightPannelToAddHere') }} + + + + + + {{ $t('activity.clearForm') }} + + + {{ $t('general.submit') }} + + + + + + + + + + + + + + + + + + + + + {{ $t('objects.viewType.form') }} {{ $t('objects.fields') }} - + + {{ visibleColumns.length }}/{{ localColumns.length }} {{ $t('objects.field') }} + + - + + + + + {{ $t('activity.addFieldFromFormView') }} + + + + + + + + + + + + + + + + + + + + + {{ $t('title.noFieldsFound') }} + + - {{ $t('activity.dragAndDropFieldsHereToAdd') }} + + + {{ $t('activity.selectAllFields') }} + + + + + + + + + + + + + + + + + {{ field.title }} + + {{ field.title }} + + + + ( + + + {{ field.label }} + + {{ field.label?.trim() }} + + ) + + * + + + + + + + + + {{ $t('title.noFieldsFound') }} with title `{{ searchQuery }}` + + + - - - - - {{ $t('general.submit') }} - - - + + + + + {{ $t('labels.appearanceSettings') }} + + + {{ $t('labels.backgroundColor') }} + + + + - + + + { + (formViewData!.meta as Record).hide_branding = value + updateView() + } + " + /> + + + {{ $t('msg.info.upgradeToEnterpriseEdition', { extraInfo: `to ${$t('labels.hideNocodbBranding')}` }) }} + + + + {{ $t('labels.hideNocodbBranding') }} + + - - - - {{ $t('msg.info.afterFormSubmitted') }} - + + + + {{ $t('msg.info.postFormSubmissionSettings') }} + - - {{ $t('msg.info.showMessage') }}: - + + + + {{ $t('msg.info.formDisplayMessage') }} + + + - - - - - - {{ $t('msg.info.submitAnotherForm') }} - + + + + + + {{ $t('msg.info.submitAnotherForm') }} + - - - - - {{ $t('msg.info.showBlankForm') }} - + + + + + {{ $t('msg.info.showBlankForm') }} + - - - - - - {{ $t('msg.info.emailForm') }} - {{ user?.email }} - + + + + + + {{ $t('msg.info.emailForm') }} + {{ user?.email }} + + + - - - - - - + + + + + + diff --git a/packages/nc-gui/components/smartsheet/calendar/WeekView/DateTimeField.vue b/packages/nc-gui/components/smartsheet/calendar/WeekView/DateTimeField.vue index 4628cca234..409dbcd850 100644 --- a/packages/nc-gui/components/smartsheet/calendar/WeekView/DateTimeField.vue +++ b/packages/nc-gui/components/smartsheet/calendar/WeekView/DateTimeField.vue @@ -458,6 +458,7 @@ const onResizeEnd = () => { document.removeEventListener('mousemove', onResize) document.removeEventListener('mouseup', onResizeEnd) } + const onResizeStart = (direction: 'right' | 'left', event: MouseEvent, record: Row) => { if (!isUIAllowed('dataEdit')) return resizeInProgress.value = true diff --git a/packages/nc-gui/components/tabs/Smartsheet.vue b/packages/nc-gui/components/tabs/Smartsheet.vue index 23fceac8a6..269212f5cc 100644 --- a/packages/nc-gui/components/tabs/Smartsheet.vue +++ b/packages/nc-gui/components/tabs/Smartsheet.vue @@ -171,7 +171,7 @@ watch([activeViewTitleOrId, activeTableId], () => { - + diff --git a/packages/nc-gui/composables/useSharedFormViewStore.ts b/packages/nc-gui/composables/useSharedFormViewStore.ts index 24a75723f5..e60f089657 100644 --- a/packages/nc-gui/composables/useSharedFormViewStore.ts +++ b/packages/nc-gui/composables/useSharedFormViewStore.ts @@ -76,7 +76,8 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share }), ) - const fieldRequired = (fieldName = 'Value') => helpers.withMessage(t('msg.error.fieldRequired', { value: fieldName }), required) + const fieldRequired = (fieldName = 'This field') => + helpers.withMessage(t('msg.error.fieldRequired', { value: fieldName }), required) const formColumns = computed(() => columns.value?.filter((c) => c.show).filter((col) => !isVirtualCol(col) || isLinksOrLTAR(col.uidt)), @@ -158,7 +159,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share !isVirtualCol(column) && ((column.rqd && !column.cdf) || (column.pk && !(column.ai || column.cdf)) || column.required) ) { - obj.localState[column.title!] = { required: fieldRequired(column.label || column.title) } + obj.localState[column.title!] = { required: fieldRequired() } } else if ( isLinksOrLTAR(column) && column.colOptions && @@ -168,13 +169,13 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share if ((col && col.rqd && !col.cdf) || column.required) { if (col) { - obj.virtual[column.title!] = { required: fieldRequired(column.label || column.title) } + obj.virtual[column.title!] = { required: fieldRequired() } } } } else if (isVirtualCol(column) && column.required) { obj.virtual[column.title!] = { minLength: minLength(1), - required: fieldRequired(column.label || column.title), + required: fieldRequired(), } } } @@ -190,6 +191,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share const submitForm = async () => { try { if (!(await v$.value?.$validate())) { + message.error(t('msg.error.someOfTheRequiredFieldsAreEmpty')) return } @@ -226,6 +228,14 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share progress.value = false } + const clearForm = async () => { + formResetHook.trigger() + + additionalState.value = {} + formState.value = {} + v$.value?.$reset() + } + /** reset form if show_blank_form is true */ watch(submitted, (nextVal) => { if (nextVal && sharedFormView.value?.show_blank_form) { @@ -261,6 +271,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share loadSharedView, columns, submitForm, + clearForm, progress, meta, validators, diff --git a/packages/nc-gui/composables/useViewColumns.ts b/packages/nc-gui/composables/useViewColumns.ts index 7771e4e6cd..c7e0889fdd 100644 --- a/packages/nc-gui/composables/useViewColumns.ts +++ b/packages/nc-gui/composables/useViewColumns.ts @@ -54,7 +54,6 @@ const [useProvideViewColumns, useViewColumns] = useInjectionState( const loadViewColumns = async () => { if (!meta || !view) return - let order = 1 if (view.value?.id) { diff --git a/packages/nc-gui/composables/useViewData.ts b/packages/nc-gui/composables/useViewData.ts index ef44dc5cd4..da3c4d105d 100644 --- a/packages/nc-gui/composables/useViewData.ts +++ b/packages/nc-gui/composables/useViewData.ts @@ -278,16 +278,16 @@ export function useViewData( if (!viewMeta?.value?.id) return try { const { columns, ...view } = await $api.dbView.formRead(viewMeta.value.id) - - const fieldById = (columns || []).reduce( - (o: Record, f: Record) => ({ + let order = 1 + const fieldById = (columns || []).reduce((o: Record, f: Record) => { + if (order < f.order) { + order = f.order + } + return { ...o, [f.fk_column_id]: f, - }), - {} as Record, - ) - - let order = 1 + } + }, {} as Record) formViewData.value = view diff --git a/packages/nc-gui/lang/en.json b/packages/nc-gui/lang/en.json index 61b23ad71a..5018386fa2 100644 --- a/packages/nc-gui/lang/en.json +++ b/packages/nc-gui/lang/en.json @@ -421,7 +421,8 @@ "restrict": "Restrict", "setNull": "Set NULL", "setDefault": "Set Default" - } + }, + "selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here" }, "labels": { "selectYear": "Select Year", @@ -683,7 +684,12 @@ "incompleteConfiguration": "Incomplete configuration", "selectField": "Select a field", "selectFieldLabel": "Make changes to field properties by selecting a field from the list" - } + }, + "appearanceSettings":"Appearance Settings", + "backgroundColor":"Background Color", + "hideNocodbBranding":"Hide NocoDB Branding", + "showOnConditions": "Show on condtions", + "showFieldOnConditionsMet":"Shows field only when conditions are met" }, "activity": { "goToToday": "Go to Today", @@ -907,7 +913,10 @@ "openInOpenStreetMap": "OSM" }, "toggleMobileMode": "Toggle Mobile Mode", - "startCommenting": "Start commenting!" + "startCommenting": "Start commenting!", + "clearForm": "Clear Form", + "addFieldFromFormView": "Add Field", + "selectAllFields": "Select all fields" }, "tooltip": { "reachedSourceLimit": "Limited to only one data source for the moment", @@ -1166,14 +1175,14 @@ "afterEnablePwd": "Access is password restricted", "privateLink": "This view is shared via a private link", "privateLinkAdditionalInfo": "People with private link can only see cells visible in this view", - "afterFormSubmitted": "After form is submitted", + "postFormSubmissionSettings": "Post Form Submission Settings", "apiOptions": "Access Base via", "submitAnotherForm": "Show 'Submit Another Form' button", "showBlankForm": "Show a blank form after 5 seconds", "emailForm": "E-mail me at", "showSysFields": "Show system fields", "filterAutoApply": "Auto apply", - "showMessage": "Show this message", + "formDisplayMessage": "Display Message", "viewNotShared": "Current view is not shared!", "showAllViews": "Show all shared views of this table", "collabView": "Collaborators with edit permissions or higher can change the view configuration.", @@ -1283,7 +1292,8 @@ "editingSystemKeyNotSupported": "Editing system key not supported", "notAvailableAtTheMoment": "Not available at the moment", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", - "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" + "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column", + "upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}" }, "error": { "scopesRequired": "Scopes required", @@ -1369,14 +1379,15 @@ "theAcceptedFileTypesAreXlsXlsxXlsmOdsOts": "The accepted file types are .xls, .xlsx, .xlsm, .ods, .ots", "parameterKeyCannotBeEmpty": "Parameter key cannot be empty", "duplicateParameterKeysAreNotAllowed": "Duplicate parameter keys are not allowed", - "fieldRequired": "{value} cannot be empty.", + "fieldRequired": "{value} cannot be empty", "projectNotAccessible": "Base not accessible", "copyToClipboardError": "Failed to copy to clipboard", "pasteFromClipboardError": "Failed to paste from clipboard", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "somethingWentWrong": "Something went wrong", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image", - "fieldToParseImageData": "Field to parse image data" + "fieldToParseImageData": "Field to parse image data", + "someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty" }, "toast": { "exportMetadata": "Base metadata exported successfully", diff --git a/packages/nc-gui/layouts/shared-view.vue b/packages/nc-gui/layouts/shared-view.vue index c6802c92af..85b1f64d29 100644 --- a/packages/nc-gui/layouts/shared-view.vue +++ b/packages/nc-gui/layouts/shared-view.vue @@ -1,5 +1,4 @@ - + + + - - {{ sharedFormView.heading }} - + + + {{ sharedFormView.heading }} + - - {{ sharedFormView.subheading }} - + + {{ sharedFormView.subheading }} + + - + - + @@ -103,7 +117,9 @@ const onDecode = async (scannedCodeValue: string) => { - {{ $t('activity.submitAnotherForm') }} + + {{ $t('activity.submitAnotherForm') }} @@ -124,7 +140,7 @@ const onDecode = async (scannedCodeValue: string) => { - + @@ -132,22 +148,16 @@ const onDecode = async (scannedCodeValue: string) => { - + - - - - + + + {{ field.label || field.title }} + + * + + + {{ field?.description }} @@ -182,34 +192,59 @@ const onDecode = async (scannedCodeValue: string) => { - - - {{ error.$message }} - - - {{ field.description }} + + + + {{ error.$message }} + + + + + {{ error.$message }} + + - - + + + {{ $t('activity.clearForm') }} + + + {{ $t('general.submit') }} + + + + + + - - - - + @@ -221,4 +256,10 @@ const onDecode = async (scannedCodeValue: string) => { @apply h-auto; @apply ml-1; } + +.nc-shared-form-button { + &.nc-button.ant-btn:focus { + box-shadow: 0px 0px 0px 2px #fff, 0px 0px 0px 4px #3069fe; + } +} diff --git a/packages/nc-gui/pages/index/[typeOrId]/form/[viewId]/index/survey.vue b/packages/nc-gui/pages/index/[typeOrId]/form/[viewId]/index/survey.vue index b1647936d1..cc3e0f27a5 100644 --- a/packages/nc-gui/pages/index/[typeOrId]/form/[viewId]/index/survey.vue +++ b/packages/nc-gui/pages/index/[typeOrId]/form/[viewId]/index/survey.vue @@ -242,13 +242,13 @@ onMounted(() => { class="max-w-[max(33%,600px)] mx-auto flex flex-col justify-end" > - + {{ sharedFormView.heading }} {{ sharedFormView?.subheading }} @@ -264,24 +264,21 @@ onMounted(() => { class="color-transition h-full flex flex-col mt-6 gap-4 w-full max-w-[max(33%,600px)] m-auto" > - - - - + + + {{ field.label || field.title }} + + * + + + {{ field?.description }} - + { {{ error.$message }} - - {{ field.description }} - {{ $t('general.shift') }} + {{ $t('general.enter') }} @@ -323,19 +313,18 @@ onMounted(() => { - {{ $t('general.submit') }} - + @@ -357,18 +346,20 @@ onMounted(() => { ]" @click="goNext()" > - - {{ $t('general.ok') }} - - - - - - + + + Ok + + + + + + + @@ -381,19 +372,14 @@ onMounted(() => { - - - {{ sharedFormView?.success_msg }} - - - - - {{ $t('msg.info.thankYou') }} - - {{ $t('msg.info.submittedFormData') }} - - - + @@ -401,7 +387,7 @@ onMounted(() => { - + {{ $t('activity.submitAnotherForm') }} @@ -468,7 +454,9 @@ onMounted(() => { - + + + @@ -494,16 +482,37 @@ onMounted(() => { } .nc-input { - @apply appearance-none w-full rounded px-2 py-2 my-2 border-solid border-1 border-primary border-opacity-50; + @apply appearance-none w-full !bg-white !rounded-lg border-solid border-1 border-gray-200 focus-within:border-brand-500; + &.nc-cell-rating, + &.nc-cell-geodata { + @apply !py-1; + } + + :deep(input) { + @apply !px-1; + } + &.nc-cell-longtext { + @apply p-0 h-auto overflow-hidden; + } + &:not(.nc-cell-longtext) { + @apply px-2 py-2; + :deep(textarea) { + @apply !p-2; + } + } &.nc-cell-checkbox { > * { @apply justify-center flex items-center; } } + } + + .nc-form-data-cell.nc-data-cell { + @apply !border-none rounded-none; - input { - @apply !py-1 !px-1; + &:focus-within { + @apply !border-none; } } } diff --git a/packages/nc-gui/pages/projects/index/list.vue b/packages/nc-gui/pages/projects/index/list.vue index 07e5fe436e..ab612d96fa 100644 --- a/packages/nc-gui/pages/projects/index/list.vue +++ b/packages/nc-gui/pages/projects/index/list.vue @@ -30,7 +30,7 @@ const openProject = async (base: BaseType) => { {{ base.title || 'Untitled' }} diff --git a/packages/nc-gui/utils/iconUtils.ts b/packages/nc-gui/utils/iconUtils.ts index fb265cf04a..5c00652c20 100644 --- a/packages/nc-gui/utils/iconUtils.ts +++ b/packages/nc-gui/utils/iconUtils.ts @@ -121,6 +121,7 @@ import NcArrowUp from '~icons/nc-icons/arrow-up' import NcArrowDown from '~icons/nc-icons/arrow-down' import NcUpload from '~icons/nc-icons/upload' import NcDownload from '~icons/nc-icons/download' +// import NcProjectGray from '~icons/nc-icons/project-gray' import NcPhoneCall from '~icons/nc-icons/phone-call' // keep it for reference diff --git a/packages/nc-gui/windi.config.ts b/packages/nc-gui/windi.config.ts index 43788329ae..f4aa6f022b 100644 --- a/packages/nc-gui/windi.config.ts +++ b/packages/nc-gui/windi.config.ts @@ -43,7 +43,7 @@ export default defineConfig({ }, shortcuts: { - 'color-transition': 'transition-color duration-100 ease-in', + 'color-transition': 'transition-colors duration-100 ease-in', 'scrollbar-thin-primary': 'scrollbar scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-primary scrollbar-track-white', 'scrollbar-thin-dull': 'scrollbar scrollbar-thin scrollbar-thumb-rounded-md scrollbar-thumb-gray-100 scrollbar-track-white', }, diff --git a/tests/playwright/pages/Dashboard/Form/index.ts b/tests/playwright/pages/Dashboard/Form/index.ts index c288acfafb..0b23414f2b 100644 --- a/tests/playwright/pages/Dashboard/Form/index.ts +++ b/tests/playwright/pages/Dashboard/Form/index.ts @@ -22,14 +22,16 @@ export class FormPage extends BasePage { readonly formSubHeading: Locator; readonly afterSubmitMsg: Locator; + readonly formFields: Locator; + constructor(dashboard: DashboardPage) { super(dashboard.rootPage); this.dashboard = dashboard; this.toolbar = new ToolbarPage(this); this.topbar = new TopbarPage(this); - this.addAllButton = dashboard.get().locator('[data-testid="nc-form-add-all"]'); - this.removeAllButton = dashboard.get().locator('[data-testid="nc-form-remove-all"]'); + this.addAllButton = dashboard.get().locator('[data-testid="nc-form-show-all-fields"]').locator('.nc-switch'); + this.removeAllButton = dashboard.get().locator('[data-testid="nc-form-show-all-fields"]').locator('.nc-switch'); this.submitButton = dashboard.get().locator('[data-testid="nc-form-submit"]'); this.showAnotherFormRadioButton = dashboard.get().locator('[data-testid="nc-form-checkbox-submit-another-form"]'); @@ -40,6 +42,8 @@ export class FormPage extends BasePage { this.formHeading = dashboard.get().locator('[data-testid="nc-form-heading"]'); this.formSubHeading = dashboard.get().locator('[data-testid="nc-form-sub-heading"]'); this.afterSubmitMsg = dashboard.get().locator('[data-testid="nc-form-after-submit-msg"]'); + + this.formFields = dashboard.get().locator('.nc-form-fields-list'); } get() { @@ -50,32 +54,20 @@ export class FormPage extends BasePage { return this.dashboard.get().locator('[data-testid="nc-form-wrapper-submit"]'); } - getFormHiddenColumn() { - return this.get().locator('[data-testid="nc-form-hidden-column"]'); - } - getFormFields() { return this.get().locator('[data-testid="nc-form-fields"]'); } - getDragNDropToHide() { - return this.get().locator('[data-testid="nc-drag-n-drop-to-hide"]'); - } - - getFormFieldsRemoveIcon() { - return this.get().locator('[data-testid="nc-field-remove-icon"]'); - } - getFormFieldsRequired() { return this.get().locator('[data-testid="nc-form-input-required"] + button'); } getFormFieldsInputLabel() { - return this.get().locator('input[data-testid="nc-form-input-label"]:visible'); + return this.get().locator('textarea[data-testid="nc-form-input-label"]:visible'); } getFormFieldsInputHelpText() { - return this.get().locator('input[data-testid="nc-form-input-help-text"]:visible'); + return this.get().locator('textarea[data-testid="nc-form-input-help-text"]:visible'); } async verifyFormFieldLabel({ index, label }: { index: number; label: string }) { @@ -83,9 +75,7 @@ export class FormPage extends BasePage { } async verifyFormFieldHelpText({ index, helpText }: { index: number; helpText: string }) { - await expect( - this.getFormFields().nth(index).locator('[data-testid="nc-form-input-help-text-label"]') - ).toContainText(helpText); + await expect(this.getFormFields().nth(index).locator('[data-testid="nc-form-help-text"]')).toContainText(helpText); } async verifyFieldsIsEditable({ index }: { index: number }) { @@ -124,8 +114,8 @@ export class FormPage extends BasePage { const dst = this.get().locator(`[data-testid="nc-drag-n-drop-to-hide"]`); await src.dragTo(dst); } else if (mode === 'hideField') { - const src = this.get().locator(`.nc-form-drag-${field.replace(' ', '')}`); - await src.locator(`[data-testid="nc-field-remove-icon"]`).click(); + // in form-v2, hide field will be using right sidebar + await this.formFields.locator(`[data-testid="nc-form-field-item-${field}"]`).locator('.nc-switch').click(); } } @@ -141,15 +131,11 @@ export class FormPage extends BasePage { await src.dragTo(dst, { trial: true }); await src.dragTo(dst); } else if (mode === 'clickField') { - const src = this.get().locator(`[data-testid="nc-form-hidden-column-${field}"]`); - await src.click(); + await this.formFields.locator(`[data-testid="nc-form-field-item-${field}"]`).locator('.nc-switch').click(); } } async removeAllFields() { - // TODO: Otherwise form input boxes are not visible sometimes - await this.rootPage.waitForTimeout(1000); - await this.removeAllButton.click(); } @@ -214,8 +200,9 @@ export class FormPage extends BasePage { await this.get() .locator(`.nc-form-drag-${field.replace(' ', '')}`) - .locator('div[data-testid="nc-form-input-label"]') + .locator('[data-testid="nc-form-input-label"]') .click(); + await waitForResponse(() => this.getFormFieldsInputLabel().fill(label)); await waitForResponse(() => this.getFormFieldsInputHelpText().fill(helpText)); if (required) { diff --git a/tests/playwright/tests/db/views/viewForm.spec.ts b/tests/playwright/tests/db/views/viewForm.spec.ts index 82fc2db602..2c1e0f746b 100644 --- a/tests/playwright/tests/db/views/viewForm.spec.ts +++ b/tests/playwright/tests/db/views/viewForm.spec.ts @@ -49,18 +49,6 @@ test.describe('Form view', () => { fields: ['LastUpdate', 'Country', 'Cities'], }); - // remove & verify (drag-drop) - await form.removeField({ field: 'Cities', mode: 'dragDrop' }); - await form.verifyFormViewFieldsOrder({ - fields: ['LastUpdate', 'Country'], - }); - - // add & verify (drag-drop) - await form.addField({ field: 'Cities', mode: 'dragDrop' }); - await form.verifyFormViewFieldsOrder({ - fields: ['LastUpdate', 'Country', 'Cities'], - }); - // remove & verify (hide field button) await form.removeField({ field: 'Cities', mode: 'hideField' }); await form.verifyFormViewFieldsOrder({ @@ -88,7 +76,7 @@ test.describe('Form view', () => { }); }); - test('Form elements validation', async ({ page }) => { + test('Form elements validation', async () => { // close 'Team & Auth' tab await dashboard.closeTab({ title: 'Team & Auth' }); await dashboard.treeView.openTable({ title: 'Country' }); @@ -182,7 +170,7 @@ test.describe('Form view', () => { await dashboard.verifyToast({ message: 'Please activate SMTP plugin in App store for enabling email notification', }); - const url = dashboard.rootPage.url(); + // const url = dashboard.rootPage.url(); // activate SMTP plugin // await accountAppStorePage.goto(); @@ -254,7 +242,6 @@ test.describe('Form view with LTAR', () => { let dashboard: DashboardPage; let loginPage: LoginPage; - let wsPage: WorkspacePage; let context: any; let api: Api; @@ -264,7 +251,6 @@ test.describe('Form view with LTAR', () => { context = await setup({ page, isEmptyProject: true }); dashboard = new DashboardPage(page, context.base); loginPage = new LoginPage(page); - wsPage = new WorkspacePage(page); api = new Api({ baseURL: `http://localhost:8080/`,
@@ -103,7 +117,9 @@ const onDecode = async (scannedCodeValue: string) => {
@@ -401,7 +387,7 @@ onMounted(() => {