Browse Source

Nc fix/form view bug fixes (#8498)

* fix(nc-gui): form view config heading text color

* fix(nc-gui): required field validation issue

* fix(nc-gui): form active field setting subtitle top margin

* fix(nc-gui): add incomplete validation error

* fix(nc-gui): validation input hover state and placehoder color
pull/8517/head
Ramesh Mane 1 month ago committed by GitHub
parent
commit
ecaca0a97b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      packages/nc-gui/assets/style.scss
  2. 19
      packages/nc-gui/components/smartsheet/Form.vue
  3. 4
      packages/nc-gui/components/smartsheet/form/field-settings.vue
  4. 21
      packages/nc-gui/composables/useFormViewStore.ts
  5. 33
      packages/nc-gui/composables/useSharedFormViewStore.ts
  6. 2
      packages/nc-gui/lang/en.json
  7. 31
      packages/nc-gui/utils/formValidations.ts
  8. 3
      packages/nc-gui/windi.config.ts

8
packages/nc-gui/assets/style.scss

@ -19,6 +19,10 @@ body {
--navbar-bg: #fafafa;
--navbar-border: #e0e0e0;
--nc-grid-bg: #fdfdfd;
--ant-primary-color-hover: #5c85ff !important;
--ant-primary-color-active: #3366ff !important;
--ant-primary-color-outline: rgba(51, 102, 255, 0.24) !important;
}
::-moz-selection {
@ -810,6 +814,6 @@ svg.nc-virtual-cell-icon {
box-shadow: 0 0 0 2px #fff, 0 0 0 4px #3366ff;
}
.text-nowrap{
.text-nowrap {
text-wrap: nowrap;
}
}

19
packages/nc-gui/components/smartsheet/Form.vue

@ -1301,7 +1301,7 @@ useEventListener(
<Pane min-size="30" size="50" class="nc-form-right-splitpane-item p-4 flex flex-col space-y-4 !min-h-200px">
<div class="flex flex-wrap justify-between items-center gap-2">
<div class="flex gap-3">
<div class="text-base font-bold text-gray-900">
<div class="text-base font-bold text-gray-600">
{{ $t('objects.viewType.form') }} {{ $t('objects.fields') }}
</div>
<NcBadge color="border-gray-200">
@ -1633,7 +1633,7 @@ useEventListener(
<LazyCellRichText
v-if="!isLocked && isEditable"
v-model:value="formViewData.success_msg"
class="nc-form-after-submit-msg"
class="nc-form-after-submit-msg editable"
is-form-field
:hidden-bubble-menu-options="hiddenBubbleMenuOptions"
data-testid="nc-form-after-submit-msg"
@ -1833,6 +1833,13 @@ useEventListener(
.form-meta-input {
.nc-textarea-rich-editor {
@apply pl-3 pr-4 !rounded-lg !text-sm border-1 border-gray-200 focus-within:border-brand-500;
&:hover {
@apply border-brand-400;
}
&:focus-within {
@apply shadow-selected;
}
}
&.nc-form-input-label .nc-textarea-rich-editor {
@ -1848,6 +1855,14 @@ useEventListener(
.nc-form-after-submit-msg {
.nc-textarea-rich-editor {
@apply pl-1 pr-2 pt-2 pb-1 !rounded-lg !text-sm border-1 border-gray-200 focus-within:border-brand-500;
&:hover {
@apply border-brand-400;
}
&:focus-within {
@apply shadow-selected;
}
.ProseMirror {
min-height: 5rem;
max-height: 7.5rem !important;

4
packages/nc-gui/components/smartsheet/form/field-settings.vue

@ -64,7 +64,7 @@ const columnSupportsScanning = (elementType: UITypes) =>
<div v-if="isSelectTypeCol(activeField.uidt)" class="w-full flex items-start justify-between gap-3">
<div class="flex-1 max-w-[calc(100%_-_40px)]">
<div class="font-medium text-gray-800">{{ $t('labels.limitOptions') }}</div>
<div class="text-gray-500 mt-2">{{ $t('labels.limitOptionsSubtext') }}.</div>
<div class="text-gray-500 mt-1">{{ $t('labels.limitOptionsSubtext') }}.</div>
<div v-if="activeField.meta.isLimitOption" class="mt-3">
<LazySmartsheetFormLimitOptions
v-model:model-value="activeField.meta.limitOptions"
@ -95,7 +95,7 @@ const columnSupportsScanning = (elementType: UITypes) =>
v-if="isSelectTypeCol(activeField.uidt)"
class="nc-form-field-appearance-settings p-4 flex flex-col gap-4 border-b border-gray-200"
>
<div class="text-base font-bold">{{ $t('general.appearance') }}</div>
<div class="text-base font-bold text-gray-600">{{ $t('general.appearance') }}</div>
<div class="flex flex-col gap-6">
<!-- Select type field Options Layout -->
<div>

21
packages/nc-gui/composables/useFormViewStore.ts

@ -48,9 +48,24 @@ const [useProvideFormViewStore, useFormViewStore] = useInjectionState(
for (const column of visibleColumns.value) {
let rules: RuleObject[] = [
{
required: isRequired(column, column.required),
message: t('msg.error.fieldRequired'),
...(column.uidt === UITypes.Checkbox && isRequired(column, column.required) ? { type: 'enum', enum: [1, true] } : {}),
validator: (_rule: RuleObject, value: any) => {
return new Promise((resolve, reject) => {
if (isRequired(column, column.required)) {
if (typeof value === 'string') {
value = value.trim()
}
if (
(column.uidt === UITypes.Checkbox && !value) ||
(column.uidt !== UITypes.Checkbox && !requiredFieldValidatorFn(value))
) {
return reject(t('msg.error.fieldRequired'))
}
}
return resolve()
})
},
},
]

33
packages/nc-gui/composables/useSharedFormViewStore.ts

@ -194,23 +194,28 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
if (!formColumns.value) return rulesObj
for (const column of formColumns.value) {
let rules: RuleObject[] = []
rules.push({
validator: (_rule: RuleObject, value: any) => {
return new Promise((resolve, reject) => {
if (isRequired(column)) {
if (column.uidt === UITypes.Checkbox && !value) {
return reject(t('msg.error.fieldRequired'))
} else if (column.uidt !== UITypes.Checkbox)
if (value === null || !value?.length) {
let rules: RuleObject[] = [
{
validator: (_rule: RuleObject, value: any) => {
return new Promise((resolve, reject) => {
if (isRequired(column)) {
if (typeof value === 'string') {
value = value.trim()
}
if (
(column.uidt === UITypes.Checkbox && !value) ||
(column.uidt !== UITypes.Checkbox && !requiredFieldValidatorFn(value))
) {
return reject(t('msg.error.fieldRequired'))
}
}
return resolve()
})
}
return resolve()
})
},
},
})
]
const additionalRules = extractFieldValidator(parseProp(column.meta).validators ?? [], column)
rules = [...rules, ...additionalRules]

2
packages/nc-gui/lang/en.json

@ -1497,7 +1497,7 @@
"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": "This field cannot be empty.",
"projectNotAccessible": "Base not accessible",
"copyToClipboardError": "Failed to copy to clipboard",
"pasteFromClipboardError": "Failed to paste from clipboard",

31
packages/nc-gui/utils/formValidations.ts

@ -64,6 +64,37 @@ export const formNumberInputValidator = (cal: ColumnType) => {
}
}
export const requiredFieldValidatorFn = (value: unknown) => {
value = unref(value)
if (Array.isArray(value)) return !!value.length
if (value === undefined || value === null) {
return false
}
if (value === false) {
return true
}
if (typeof value === 'object') {
for (let _ in value) return true
return false
}
return !!String(value).length
}
export const isEmptyValidatorValue = (v: Validation) => {
if (v.type === StringValidationType.Regex) {
return v.type && typeof v.regex === 'string' ? !v.regex.trim() : v.regex === null
} else if (v.type && v.value !== undefined) {
return v.type && typeof v.value === 'string' ? !v.value.trim() : v.value === null
}
return false
}
export const extractFieldValidator = (_validators: Validation[], element: ColumnType) => {
const rules: RuleObject[] = []

3
packages/nc-gui/windi.config.ts

@ -111,6 +111,9 @@ export default defineConfig({
primary: 'rgba(var(--color-primary), var(--tw-ring-opacity))',
accent: 'rgba(var(--color-accent), var(--tw-ring-opacity))',
},
boxShadow: {
selected: '0px 0px 0px 2px var(--ant-primary-color-outline)',
},
colors: {
...windiColors,
...themeColors,

Loading…
Cancel
Save