From b96d7775d33113aa0d00bc1355e09fc58d16c483 Mon Sep 17 00:00:00 2001 From: Jay Cammarano <67079013+jaycammarano@users.noreply.github.com> Date: Thu, 20 Jan 2022 15:58:57 -0500 Subject: [PATCH] Add soft character limit to various inputs (#11009) * added soft_length to lang * added softLength option to input interface * softLength => textarea, md, wysiwyg * really broken but counting characters * return 0 not null oops * characters remaining displaying * percentageRemaining => shared * placeholders => string * markdown inputs need to change preview css * account for multiple md inputs * works for multiple inputs on a page * let it breathe * text area but no warning color (yet) * newline is 1 char * null => undefined * shows with 0 hard limit left * softlength tied to maxlength * preview displaying md * using share util * Replace shared "interface" with util * Add test setup * Lock package versions Co-authored-by: rijkvanzanten --- app/jest.config.js | 5 + app/package.json | 7 +- app/src/interfaces/input-multiline/index.ts | 13 + .../input-multiline/input-multiline.vue | 71 +- .../interfaces/input-rich-text-html/index.ts | 13 + .../input-rich-text-html.vue | 71 +- .../interfaces/input-rich-text-md/index.ts | 13 + .../input-rich-text-md/input-rich-text-md.vue | 61 +- app/src/interfaces/input/index.ts | 14 + app/src/interfaces/input/input.vue | 27 +- app/src/lang/translations/en-US.yaml | 1 + app/src/utils/percentage.ts | 5 + app/tests/utils/percentage.test.ts | 15 + app/tsconfig.json | 2 +- package-lock.json | 2444 ++++++++++++----- 15 files changed, 2077 insertions(+), 685 deletions(-) create mode 100644 app/jest.config.js create mode 100644 app/src/utils/percentage.ts create mode 100644 app/tests/utils/percentage.test.ts diff --git a/app/jest.config.js b/app/jest.config.js new file mode 100644 index 0000000000..d59a9936d4 --- /dev/null +++ b/app/jest.config.js @@ -0,0 +1,5 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', +}; diff --git a/app/package.json b/app/package.json index b9e9f326dd..10fada407c 100644 --- a/app/package.json +++ b/app/package.json @@ -24,7 +24,9 @@ "scripts": { "dev": "vite", "build": "vite build", - "serve": "vite preview" + "serve": "vite preview", + "test": "jest --coverage", + "test:watch": "jest --coverage --watchAll" }, "gitHead": "24621f3934dc77eb23441331040ed13c676ceffd", "devDependencies": { @@ -55,6 +57,7 @@ "@types/diff": "5.0.1", "@types/dompurify": "2.3.1", "@types/geojson": "7946.0.8", + "@types/jest": "27.4.0", "@types/lodash": "4.14.177", "@types/mapbox__mapbox-gl-draw": "1.2.3", "@types/mapbox__mapbox-gl-geocoder": "4.7.1", @@ -80,6 +83,7 @@ "flatpickr": "4.6.9", "front-matter": "4.0.2", "html-entities": "2.3.2", + "jest": "27.4.7", "jsonlint-mod": "1.7.6", "maplibre-gl": "1.15.2", "marked": "4.0.10", @@ -95,6 +99,7 @@ "rimraf": "3.0.2", "sass": "1.43.4", "tinymce": "5.10.2", + "ts-jest": "27.1.3", "typescript": "4.5.2", "vite": "2.6.14", "vite-plugin-md": "0.11.4", diff --git a/app/src/interfaces/input-multiline/index.ts b/app/src/interfaces/input-multiline/index.ts index 7fb7442e5a..2fe06275e5 100644 --- a/app/src/interfaces/input-multiline/index.ts +++ b/app/src/interfaces/input-multiline/index.ts @@ -23,6 +23,19 @@ export default defineInterface({ }, }, }, + { + field: 'softLength', + name: '$t:soft_length', + type: 'integer', + meta: { + width: 'half', + interface: 'input', + options: { + placeholder: '255', + min: 1, + }, + }, + }, { field: 'trim', name: '$t:interfaces.input.trim', diff --git a/app/src/interfaces/input-multiline/input-multiline.vue b/app/src/interfaces/input-multiline/input-multiline.vue index df0ba7d00c..b3d07d218c 100644 --- a/app/src/interfaces/input-multiline/input-multiline.vue +++ b/app/src/interfaces/input-multiline/input-multiline.vue @@ -6,11 +6,24 @@ :disabled="disabled" :class="font" @update:model-value="$emit('input', $event)" - /> + > + + @@ -57,4 +100,28 @@ export default defineComponent({ --v-textarea-font-family: var(--family-sans-serif); } } + +.remaining { + position: absolute; + right: 10px; + bottom: 5px; + width: 24px; + color: var(--foreground-subdued); + font-weight: 600; + text-align: right; + vertical-align: middle; + font-feature-settings: 'tnum'; +} + +.v-input:focus-within .remaining { + display: block; +} + +.v-input:focus-within .hide { + display: none; +} + +.warning { + color: var(--warning); +} diff --git a/app/src/interfaces/input-rich-text-html/index.ts b/app/src/interfaces/input-rich-text-html/index.ts index 75cd30c4a3..91af08c538 100644 --- a/app/src/interfaces/input-rich-text-html/index.ts +++ b/app/src/interfaces/input-rich-text-html/index.ts @@ -268,6 +268,19 @@ export default defineInterface({ }, ], advanced: [ + { + field: 'softLength', + name: '$t:soft_length', + type: 'integer', + meta: { + width: 'half', + interface: 'input', + options: { + placeholder: '255', + min: 1, + }, + }, + }, { field: 'customFormats', name: '$t:interfaces.input-rich-text-html.custom_formats', diff --git a/app/src/interfaces/input-rich-text-html/input-rich-text-html.vue b/app/src/interfaces/input-rich-text-html/input-rich-text-html.vue index 98f3b33704..e7cf2f3a27 100644 --- a/app/src/interfaces/input-rich-text-html/input-rich-text-html.vue +++ b/app/src/interfaces/input-rich-text-html/input-rich-text-html.vue @@ -1,5 +1,5 @@