diff options
author | Joas Schilling <coding@schilljs.com> | 2023-05-10 09:09:03 +0200 |
---|---|---|
committer | Joas Schilling <coding@schilljs.com> | 2023-05-10 11:59:29 +0200 |
commit | c20fd9f91feb071e57f1c64026e737b16bcddec8 (patch) | |
tree | 3ed7ffb9cb037054d231f264b4db11725f01a4b0 /apps/workflowengine/src | |
parent | 14cb58c0e5b4507704755a462a859c407173c21f (diff) | |
download | nextcloud-server-c20fd9f91feb071e57f1c64026e737b16bcddec8.tar.gz nextcloud-server-c20fd9f91feb071e57f1c64026e737b16bcddec8.zip |
fix(workflowengine): Fix multiple UI issues in workflow engine admin settings
Signed-off-by: Joas Schilling <coding@schilljs.com>
Diffstat (limited to 'apps/workflowengine/src')
7 files changed, 174 insertions, 162 deletions
diff --git a/apps/workflowengine/src/components/Check.vue b/apps/workflowengine/src/components/Check.vue index 427835a7ec7..83f823838f7 100644 --- a/apps/workflowengine/src/components/Check.vue +++ b/apps/workflowengine/src/components/Check.vue @@ -1,20 +1,20 @@ <template> <div v-click-outside="hideDelete" class="check" @click="showDelete"> - <NcMultiselect ref="checkSelector" + <NcSelect ref="checkSelector" v-model="currentOption" :options="options" label="name" track-by="class" - :allow-empty="false" + :clearable="false" :placeholder="t('workflowengine', 'Select a filter')" @input="updateCheck" /> - <NcMultiselect v-model="currentOperator" + <NcSelect v-model="currentOperator" :disabled="!currentOption" :options="operators" class="comparator" label="name" track-by="operator" - :allow-empty="false" + :clearable="false" :placeholder="t('workflowengine', 'Select a comparator')" @input="updateCheck" /> <component :is="currentOption.component" @@ -35,15 +35,22 @@ class="option" @input="updateCheck"> <NcActions v-if="deleteVisible || !currentOption"> - <NcActionButton icon="icon-close" @click="$emit('remove')" /> + <NcActionButton :title="t('workflowengine', 'Remove filter')" @click="$emit('remove')"> + <template #icon> + <CloseIcon :size="20" /> + </template> + </NcActionButton> </NcActions> </div> </template> <script> -import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect.js' import NcActions from '@nextcloud/vue/dist/Components/NcActions.js' import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' +import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' + +import CloseIcon from 'vue-material-design-icons/Close.vue' + import ClickOutside from 'vue-click-outside' export default { @@ -51,7 +58,10 @@ export default { components: { NcActionButton, NcActions, - NcMultiselect, + NcSelect, + + // Icons + CloseIcon, }, directives: { ClickOutside, @@ -151,45 +161,36 @@ export default { .check { display: flex; flex-wrap: wrap; + align-items: flex-start; // to not stretch components vertically width: 100%; padding-right: 20px; + & > *:not(.close) { width: 180px; } & > .comparator { - min-width: 130px; - width: 130px; + min-width: 200px; + width: 200px; } & > .option { - min-width: 230px; - width: 230px; + min-width: 260px; + width: 260px; + min-height: 48px; + + & > input[type=text] { + min-height: 48px; + } } - & > .multiselect, + & > .v-select, + & > .button-vue, & > input[type=text] { margin-right: 5px; margin-bottom: 5px; } - - .multiselect::v-deep .multiselect__content-wrapper li>span, - .multiselect::v-deep .multiselect__single { - display: block; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } } input[type=text] { margin: 0; } - ::placeholder { - font-size: 10px; - } - button.action-item.action-item--single.icon-close { - height: 44px; - width: 44px; - margin-top: -5px; - margin-bottom: -5px; - } .invalid { border-color: var(--color-error) !important; } diff --git a/apps/workflowengine/src/components/Checks/FileMimeType.vue b/apps/workflowengine/src/components/Checks/FileMimeType.vue index 472edda613a..941347f0aa2 100644 --- a/apps/workflowengine/src/components/Checks/FileMimeType.vue +++ b/apps/workflowengine/src/components/Checks/FileMimeType.vue @@ -21,48 +21,50 @@ --> <template> <div> - <NcMultiselect :value="currentValue" + <NcSelect :value="currentValue" :placeholder="t('workflowengine', 'Select a file type')" label="label" - track-by="pattern" :options="options" - :multiple="false" - :tagging="false" + :clearable="false" @input="setValue"> - <template slot="singleLabel" slot-scope="props"> - <span v-if="props.option.icon" class="option__icon" :class="props.option.icon" /> - <img v-else - class="option__icon-img" - :src="props.option.iconUrl" - alt=""> - <span class="option__title option__title_single">{{ props.option.label }}</span> + <template #option="option"> + <span v-if="option.icon" class="option__icon" :class="option.icon" /> + <span v-else class="option__icon-img"> + <img :src="option.iconUrl" alt=""> + </span> + <span class="option__title"> + <NcEllipsisedOption :name="String(option.label)" /> + </span> </template> - <template slot="option" slot-scope="props"> - <span v-if="props.option.icon" class="option__icon" :class="props.option.icon" /> - <img v-else - class="option__icon-img" - :src="props.option.iconUrl" - alt=""> - <span class="option__title">{{ props.option.label }}</span> + <template #selected-option="selectedOption"> + <span v-if="selectedOption.icon" class="option__icon" :class="selectedOption.icon" /> + <span v-else class="option__icon-img"> + <img :src="selectedOption.iconUrl" alt=""> + </span> + <span class="option__title"> + <NcEllipsisedOption :name="String(selectedOption.label)" /> + </span> </template> - </NcMultiselect> + </NcSelect> <input v-if="!isPredefined" type="text" - :value="currentValue.pattern" + :value="currentValue.id" :placeholder="t('workflowengine', 'e.g. httpd/unix-directory')" @input="updateCustom"> </div> </template> <script> -import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect.js' +import NcEllipsisedOption from '@nextcloud/vue/dist/Components/NcEllipsisedOption.js' +import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' import valueMixin from './../../mixins/valueMixin.js' import { imagePath } from '@nextcloud/router' export default { name: 'FileMimeType', components: { - NcMultiselect, + NcEllipsisedOption, + NcSelect, }, mixins: [ valueMixin, @@ -73,22 +75,22 @@ export default { { icon: 'icon-folder', label: t('workflowengine', 'Folder'), - pattern: 'httpd/unix-directory', + id: 'httpd/unix-directory', }, { icon: 'icon-picture', label: t('workflowengine', 'Images'), - pattern: '/image\\/.*/', + id: '/image\\/.*/', }, { iconUrl: imagePath('core', 'filetypes/x-office-document'), label: t('workflowengine', 'Office documents'), - pattern: '/(vnd\\.(ms-|openxmlformats-|oasis\\.opendocument).*)$/', + id: '/(vnd\\.(ms-|openxmlformats-|oasis\\.opendocument).*)$/', }, { iconUrl: imagePath('core', 'filetypes/application-pdf'), label: t('workflowengine', 'PDF documents'), - pattern: 'application/pdf', + id: 'application/pdf', }, ], } @@ -98,7 +100,7 @@ export default { return [...this.predefinedTypes, this.customValue] }, isPredefined() { - const matchingPredefined = this.predefinedTypes.find((type) => this.newValue === type.pattern) + const matchingPredefined = this.predefinedTypes.find((type) => this.newValue === type.id) if (matchingPredefined) { return true } @@ -108,18 +110,18 @@ export default { return { icon: 'icon-settings-dark', label: t('workflowengine', 'Custom MIME type'), - pattern: '', + id: '', } }, currentValue() { - const matchingPredefined = this.predefinedTypes.find((type) => this.newValue === type.pattern) + const matchingPredefined = this.predefinedTypes.find((type) => this.newValue === type.id) if (matchingPredefined) { return matchingPredefined } return { icon: 'icon-settings-dark', label: t('workflowengine', 'Custom mimetype'), - pattern: this.newValue, + id: this.newValue, } }, }, @@ -131,7 +133,7 @@ export default { }, setValue(value) { if (value !== null) { - this.newValue = value.pattern + this.newValue = value.id this.$emit('input', this.newValue) } }, @@ -143,24 +145,30 @@ export default { } </script> <style scoped lang="scss"> -.multiselect, input[type='text'] { +.v-select, +input[type='text'] { width: 100%; } -.multiselect::v-deep .multiselect__content-wrapper li > span, -.multiselect::v-deep .multiselect__single { - display: flex; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + +input[type=text] { + min-height: 48px; } -.option__icon { +.option__icon, +.option__icon-img { display: inline-block; min-width: 30px; - background-position: left; + background-position: center; + vertical-align: middle; } .option__icon-img { - margin-right: 14px; + text-align: center; +} + +.option__title { + display: inline-flex; + width: calc(100% - 36px); + vertical-align: middle; } </style> diff --git a/apps/workflowengine/src/components/Checks/RequestTime.vue b/apps/workflowengine/src/components/Checks/RequestTime.vue index 79a91c0e544..36177e6ad65 100644 --- a/apps/workflowengine/src/components/Checks/RequestTime.vue +++ b/apps/workflowengine/src/components/Checks/RequestTime.vue @@ -12,15 +12,16 @@ <p v-if="!valid" class="invalid-hint"> {{ t('workflowengine', 'Please enter a valid time span') }} </p> - <NcMultiselect v-show="valid" + <NcSelect v-show="valid" v-model="newValue.timezone" + :clearable="false" :options="timezones" @input="update" /> </div> </template> <script> -import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect.js' +import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' import moment from 'moment-timezone' import valueMixin from '../../mixins/valueMixin.js' @@ -28,7 +29,7 @@ const zones = moment.tz.names() export default { name: 'RequestTime', components: { - NcMultiselect, + NcSelect, }, mixins: [ valueMixin, @@ -112,6 +113,7 @@ export default { width: 50%; margin: 0; margin-bottom: 5px; + min-height: 48px; &.timeslot--start { margin-right: 5px; diff --git a/apps/workflowengine/src/components/Checks/RequestURL.vue b/apps/workflowengine/src/components/Checks/RequestURL.vue index 28184a52eb5..ce5e009cde9 100644 --- a/apps/workflowengine/src/components/Checks/RequestURL.vue +++ b/apps/workflowengine/src/components/Checks/RequestURL.vue @@ -22,41 +22,43 @@ <template> <div> - <NcMultiselect :value="currentValue" + <NcSelect :value="currentValue" :placeholder="t('workflowengine', 'Select a request URL')" label="label" - track-by="pattern" - group-values="children" - group-label="label" + :clearable="false" :options="options" - :multiple="false" - :tagging="false" @input="setValue"> - <template slot="singleLabel" slot-scope="props"> - <span class="option__icon" :class="props.option.icon" /> - <span class="option__title option__title_single">{{ props.option.label }}</span> + <template #option="option"> + <span class="option__icon" :class="option.icon" /> + <span class="option__title"> + <NcEllipsisedOption :name="String(option.label)" /> + </span> </template> - <template slot="option" slot-scope="props"> - <span class="option__icon" :class="props.option.icon" /> - <span class="option__title">{{ props.option.label }} {{ props.option.$groupLabel }}</span> + <template #selected-option="selectedOption"> + <span class="option__icon" :class="selectedOption.icon" /> + <span class="option__title"> + <NcEllipsisedOption :name="String(selectedOption.label)" /> + </span> </template> - </NcMultiselect> + </NcSelect> <input v-if="!isPredefined" type="text" - :value="currentValue.pattern" + :value="currentValue.id" :placeholder="placeholder" @input="updateCustom"> </div> </template> <script> -import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect.js' +import NcEllipsisedOption from '@nextcloud/vue/dist/Components/NcEllipsisedOption.js' +import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' import valueMixin from '../../mixins/valueMixin.js' export default { name: 'RequestURL', components: { - NcMultiselect, + NcEllipsisedOption, + NcSelect, }, mixins: [ valueMixin, @@ -66,10 +68,9 @@ export default { newValue: '', predefinedTypes: [ { - label: t('workflowengine', 'Predefined URLs'), - children: [ - { pattern: 'webdav', label: t('workflowengine', 'Files WebDAV') }, - ], + icon: 'icon-files-dark', + id: 'webdav', + label: t('workflowengine', 'Files WebDAV'), }, ], } @@ -86,23 +87,16 @@ export default { }, matchingPredefined() { return this.predefinedTypes - .map(groups => groups.children) - .flat() - .find((type) => this.newValue === type.pattern) + .find((type) => this.newValue === type.id) }, isPredefined() { return !!this.matchingPredefined }, customValue() { return { - label: t('workflowengine', 'Others'), - children: [ - { - icon: 'icon-settings-dark', - label: t('workflowengine', 'Custom URL'), - pattern: '', - }, - ], + icon: 'icon-settings-dark', + label: t('workflowengine', 'Custom URL'), + id: '', } }, currentValue() { @@ -112,7 +106,7 @@ export default { return { icon: 'icon-settings-dark', label: t('workflowengine', 'Custom URL'), - pattern: this.newValue, + id: this.newValue, } }, }, @@ -125,7 +119,7 @@ export default { setValue(value) { // TODO: check if value requires a regex and set the check operator according to that if (value !== null) { - this.newValue = value.pattern + this.newValue = value.id this.$emit('input', this.newValue) } }, @@ -137,13 +131,24 @@ export default { } </script> <style scoped lang="scss"> - .multiselect, input[type='text'] { + .v-select, + input[type='text'] { width: 100%; } + input[type='text'] { + min-height: 48px; + } .option__icon { display: inline-block; min-width: 30px; - background-position: left; + background-position: center; + vertical-align: middle; + } + + .option__title { + display: inline-flex; + width: calc(100% - 36px); + vertical-align: middle; } </style> diff --git a/apps/workflowengine/src/components/Checks/RequestUserAgent.vue b/apps/workflowengine/src/components/Checks/RequestUserAgent.vue index 1d00bdc238d..eccf76ae58c 100644 --- a/apps/workflowengine/src/components/Checks/RequestUserAgent.vue +++ b/apps/workflowengine/src/components/Checks/RequestUserAgent.vue @@ -22,28 +22,25 @@ <template> <div> - <NcMultiselect :value="currentValue" + <NcSelect :value="currentValue" :placeholder="t('workflowengine', 'Select a user agent')" label="label" - track-by="pattern" :options="options" - :multiple="false" - :tagging="false" + :clearable="false" @input="setValue"> - <template slot="singleLabel" slot-scope="props"> - <span class="option__icon" :class="props.option.icon" /> - <!-- v-html can be used here as t() always passes our translated strings though DOMPurify.sanitize --> - <!-- eslint-disable-next-line vue/no-v-html --> - <span class="option__title option__title_single" v-html="props.option.label" /> + <template #option="option"> + <span class="option__icon" :class="option.icon" /> + <span class="option__title"> + <NcEllipsisedOption :name="String(option.label)" /> + </span> </template> - <template slot="option" slot-scope="props"> - <span class="option__icon" :class="props.option.icon" /> - <!-- eslint-disable-next-line vue/no-v-html --> - <span v-if="props.option.$groupLabel" class="option__title" v-html="props.option.$groupLabel" /> - <!-- eslint-disable-next-line vue/no-v-html --> - <span v-else class="option__title" v-html="props.option.label" /> + <template #selected-option="selectedOption"> + <span class="option__icon" :class="selectedOption.icon" /> + <span class="option__title"> + <NcEllipsisedOption :name="String(selectedOption.label)" /> + </span> </template> - </NcMultiselect> + </NcSelect> <input v-if="!isPredefined" type="text" :value="currentValue.pattern" @@ -52,13 +49,15 @@ </template> <script> -import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect.js' +import NcEllipsisedOption from '@nextcloud/vue/dist/Components/NcEllipsisedOption.js' +import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' import valueMixin from '../../mixins/valueMixin.js' export default { name: 'RequestUserAgent', components: { - NcMultiselect, + NcEllipsisedOption, + NcSelect, }, mixins: [ valueMixin, @@ -67,10 +66,10 @@ export default { return { newValue: '', predefinedTypes: [ - { pattern: 'android', label: t('workflowengine', 'Android client'), icon: 'icon-phone' }, - { pattern: 'ios', label: t('workflowengine', 'iOS client'), icon: 'icon-phone' }, - { pattern: 'desktop', label: t('workflowengine', 'Desktop client'), icon: 'icon-desktop' }, - { pattern: 'mail', label: t('workflowengine', 'Thunderbird & Outlook addons'), icon: 'icon-mail' }, + { id: 'android', label: t('workflowengine', 'Android client'), icon: 'icon-phone' }, + { id: 'ios', label: t('workflowengine', 'iOS client'), icon: 'icon-phone' }, + { id: 'desktop', label: t('workflowengine', 'Desktop client'), icon: 'icon-desktop' }, + { id: 'mail', label: t('workflowengine', 'Thunderbird & Outlook addons'), icon: 'icon-mail' }, ], } }, @@ -80,7 +79,7 @@ export default { }, matchingPredefined() { return this.predefinedTypes - .find((type) => this.newValue === type.pattern) + .find((type) => this.newValue === type.id) }, isPredefined() { return !!this.matchingPredefined @@ -89,7 +88,7 @@ export default { return { icon: 'icon-settings-dark', label: t('workflowengine', 'Custom user agent'), - pattern: '', + id: '', } }, currentValue() { @@ -99,7 +98,7 @@ export default { return { icon: 'icon-settings-dark', label: t('workflowengine', 'Custom user agent'), - pattern: this.newValue, + id: this.newValue, } }, }, @@ -112,7 +111,7 @@ export default { setValue(value) { // TODO: check if value requires a regex and set the check operator according to that if (value !== null) { - this.newValue = value.pattern + this.newValue = value.id this.$emit('input', this.newValue) } }, @@ -124,31 +123,24 @@ export default { } </script> <style scoped> - .multiselect, input[type='text'] { + .v-select, + input[type='text'] { width: 100%; } - - .multiselect .multiselect__content-wrapper li>span { - display: flex; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - .multiselect::v-deep .multiselect__single { - width: 100%; - display: flex; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + input[type='text'] { + min-height: 48px; } + .option__icon { display: inline-block; min-width: 30px; - background-position: left; + background-position: center; + vertical-align: middle; } + .option__title { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + display: inline-flex; + width: calc(100% - 36px); + vertical-align: middle; } </style> diff --git a/apps/workflowengine/src/components/Checks/RequestUserGroup.vue b/apps/workflowengine/src/components/Checks/RequestUserGroup.vue index cfb9c7dcc98..542fa46765e 100644 --- a/apps/workflowengine/src/components/Checks/RequestUserGroup.vue +++ b/apps/workflowengine/src/components/Checks/RequestUserGroup.vue @@ -22,10 +22,10 @@ <template> <div> - <NcMultiselect :value="currentValue" + <NcSelect :value="currentValue" :loading="status.isLoading && groups.length === 0" :options="groups" - :multiple="false" + :clearable="false" label="displayname" track-by="id" @search-change="searchAsync" @@ -34,7 +34,7 @@ </template> <script> -import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect.js' +import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' import axios from '@nextcloud/axios' import { generateOcsUrl } from '@nextcloud/router' @@ -46,7 +46,7 @@ const status = { export default { name: 'RequestUserGroup', components: { - NcMultiselect, + NcSelect, }, props: { value: { @@ -106,7 +106,7 @@ export default { } </script> <style scoped> - .multiselect { - width: 100%; - } +.v-select { + width: 100%; +} </style> diff --git a/apps/workflowengine/src/components/Rule.vue b/apps/workflowengine/src/components/Rule.vue index 6b0abed88c8..e641d8cffb8 100644 --- a/apps/workflowengine/src/components/Rule.vue +++ b/apps/workflowengine/src/components/Rule.vue @@ -18,7 +18,7 @@ <input v-if="lastCheckComplete" type="button" class="check--add" - value="Add a new filter" + :value="t('workflowengine', 'Add a new filter')" @click="onAddFilter"> </p> </div> @@ -213,10 +213,11 @@ export default { flex-wrap: wrap; border-left: 5px solid var(--color-primary-element); - .trigger, .action { + .trigger, + .action { flex-grow: 1; min-height: 100px; - max-width: 700px; + max-width: 920px; } .action { max-width: 400px; @@ -247,6 +248,9 @@ export default { .trigger p:first-child span { padding-top: 3px; } + .trigger p:last-child { + padding-top: 8px; + } .check--add { background-position: 7px center; |