Replace some select components with CInputSelect

This commit is contained in:
Emmy Leke
2023-12-20 17:42:49 +01:00
committed by Jože Fortun
parent fdcb27ebe3
commit be5ff4d095
97 changed files with 712 additions and 1095 deletions
+1 -1
View File
@@ -53,7 +53,7 @@
"v-photoswipe": "^1.0.3-1",
"vue-color": "^2.8.1",
"vue-echarts": "^6.2.3",
"vue-select": "^3.4.0",
"vue-select": "3.20.2",
"vue-swatches": "^1.0.4",
"vue2-ace-editor": "^0.0.15",
"vue2-leaflet": "^2.7.1",
+1
View File
@@ -20,6 +20,7 @@ export {
CInputColorPicker,
CAceEditor,
CButtonSubmit,
CInputSelect,
} from './input'
export {
+6 -13
View File
@@ -30,22 +30,13 @@
class="align-middle"
style="min-width: 250px;"
>
<b-form-select
<c-input-select
v-model="column.field"
:options="availableFields"
text-field="label"
value-field="name"
:reduce="o => o.name"
:placeholder="labels.none"
class="rounded"
>
<template #first>
<b-form-select-option
:value="undefined"
disabled
>
{{ labels.none }}
</b-form-select-option>
</template>
</b-form-select>
/>
</td>
<td
@@ -117,10 +108,12 @@
<script>
import Draggable from 'vuedraggable'
import CInputSelect from './CInputSelect.vue'
export default {
components: {
Draggable,
CInputSelect,
},
props: {
@@ -0,0 +1,228 @@
<template>
<vue-select
v-model="_value"
v-bind="$attrs"
:clearable="clearable"
:options="options"
:searchable="searchable"
:calculate-position="calculateDropdownPosition"
:append-to-body="appendToBody"
class="bg-white rounded"
:class="sizeClass"
v-on="$listeners"
>
<template
v-for="(_, name) in $scopedSlots"
v-slot:[name]="data"
>
<slot
:name="name"
v-bind="data"
/>
</template>
</vue-select>
</template>
<script>
import { VueSelect } from 'vue-select'
import { createPopper } from '@popperjs/core'
import 'vue-select/dist/vue-select.css';
export default {
name: 'CInputSelect',
components: {
VueSelect,
},
props: {
value: {
type: [String, Array],
default: () => '',
},
options: {
type: Array,
default: () => {
return []
},
},
clearable: {
type: Boolean,
default: true,
},
searchable: {
type: Boolean,
default: true,
},
appendToBody: {
type: Boolean,
default: true,
},
defaultValue: {
type: [String, Array],
default: () => '',
},
size: {
type: String,
default: 'md',
},
},
computed: {
_value: {
get () {
const fallbackValue = this.$attrs.multiple ? [] : ''
return !!this.defaultValue && (this.value === this.defaultValue) ? fallbackValue : this.value
},
set (v) {
this.$emit('input', !v ? this.defaultValue : v)
}
},
sizeClass () {
return this.size === 'sm' ? 'c-input-sm' : this.size === 'lg' ? 'c-input-lg' : ''
},
},
methods: {
calculateDropdownPosition (dropdownList, component, { width }) {
/**
* We need to explicitly define the dropdown width since
* it is usually inherited from the parent with CSS.
*/
dropdownList.style.width = width
/**
* Here we position the dropdownList relative to the $refs.toggle Element.
*
* The 'offset' modifier aligns the dropdown so that the $refs.toggle and
* the dropdownList overlap by 1 pixel.
*
* The 'toggleClass' modifier adds a 'drop-up' class to the Vue Select
* wrapper so that we can set some styles for when the dropdown is placed
* above.
*/
const popper = createPopper(component.$refs.toggle, dropdownList, {
placement: 'bottom',
modifiers: [
{
name: 'offset',
options: {
offset: [0, -1],
},
},
{
name: 'toggleClass',
enabled: true,
phase: 'write',
fn ({ state }) {
component.$el.classList.toggle('drop-up', state.placement === 'top')
},
}],
})
/**
* To prevent memory leaks Popper needs to be destroyed.
* If you return function, it will be called just before dropdown is removed from DOM.
*/
return () => popper.destroy()
},
},
}
</script>
<style lang="scss">
.v-select {
min-width: auto;
position: relative;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
margin-bottom: 0;
font-size: .9rem;
border-radius: 0.25rem;
.vs__selected-options {
// do not allow growing
width: 0;
}
.vs__selected {
display: block;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 100%;
overflow: hidden;
}
.vs__search {
margin-top: 0.375rem;
}
&:not(.vs--open) .vs__selected + .vs__search {
// force this to not use any space
// we still need it to be rendered for the focus
width: 0;
padding: 0;
margin: 0;
border: none;
height: 0;
}
.vs__dropdown-toggle {
padding: 0.375rem;
padding-top: 0;
border-width: 2px;
border-color: var(--light);
.vs__selected {
margin-top: 0.375rem;
}
.vs__actions {
padding-top: 0.375rem;
}
}
.vs__clear,
.vs__open-indicator {
fill: var(--gray-900);
display: inline-flex;
}
.vs__clear {
padding: 0;
border: 0;
background-color: transparent;
cursor: pointer;
margin-right: 8px
}
}
.vs__dropdown-menu {
z-index: 1090;
}
.c-input-sm {
height: calc(1.5em + .5rem + 2px);
padding-top: .25rem;
padding-bottom: .25rem;
padding-left: .5rem;
font-size: .875rem;
}
.c-input-lg {
height: calc(1.5em + 1rem + 2px);
padding-top: .5rem;
padding-bottom: .5rem;
padding-left: 1rem;
font-size: 1.25rem;
}
</style>
+2 -1
View File
@@ -10,4 +10,5 @@ export { default as CInputColorPicker } from './CInputColorPicker.vue'
export { default as CAceEditor } from './CAceEditor.vue'
export {
CButtonSubmit
} from './button'
} from './button'
export { default as CInputSelect } from './CInputSelect.vue'
@@ -43,17 +43,16 @@
:label="labels.edit.label"
label-class="text-primary"
>
<vue-select
v-model="currentRole"
<c-input-select
v-model="currentRoleID"
data-test-id="select-user-list-roles"
key="roleID"
label="name"
:clearable="false"
:options="roles"
:get-option-key="getOptionRoleKey"
:reduce="o => o.roleID"
append-to-body
:calculate-position="calculateDropdownPosition"
class="h-100 bg-white rounded"
@input="onRoleChange"
/>
</b-form-group>
@@ -75,6 +74,7 @@
>
{{ n }}
</label>
<font-awesome-icon
:icon="['fas', 'plus']"
class="text-secondary rotate mt-1"
@@ -105,6 +105,7 @@
style="min-height: 50vh;"
>
<b-spinner />
<div>
{{ labels.loading }}
</div>
@@ -122,6 +123,7 @@
:rules.sync="rules"
/>
</b-col>
<b-col
v-for="(e, i) in evaluate"
:key="i"
@@ -142,11 +144,13 @@
:icon="['fas', 'question']"
class="text-secondary"
/>
<font-awesome-icon
v-else-if="r.access === 'allow'"
:icon="['fas', 'check']"
class="text-success"
/>
<font-awesome-icon
v-else
:icon="['fas', 'times']"
@@ -191,7 +195,7 @@
label-class="text-primary"
class="mb-0"
>
<vue-select
<c-input-select
data-test-id="select-role"
key="roleID"
v-model="add.roleID"
@@ -202,8 +206,6 @@
clearable
:disabled="!!add.userID"
:placeholder="labels.add.role.placeholder"
:calculate-position="calculateDropdownPosition"
class="bg-white rounded"
/>
</b-form-group>
@@ -212,7 +214,7 @@
label-class="text-primary"
class="mt-3 mb-0"
>
<vue-select
<c-input-select
data-test-id="select-user"
key="userID"
v-model="add.userID"
@@ -220,11 +222,10 @@
:options="userOptions"
:get-option-label="getUserLabel"
:get-option-key="getOptionUserKey"
:reduce="o => o.userID"
label="name"
clearable
:placeholder="labels.add.user.placeholder"
:calculate-position="calculateDropdownPosition"
class="bg-white rounded"
@search="searchUsers"
/>
</b-form-group>
@@ -243,9 +244,8 @@
</template>
<script lang="js">
import { modalOpenEventName, split } from './def.ts'
import { VueSelect } from 'vue-select'
import CInputSelect from '../input/CInputSelect.vue'
import Rules from './form/Rules.vue'
import calculateDropdownPosition from '../../mixins/vue-select-position'
export default {
i18nOptions: {
@@ -254,13 +254,9 @@ export default {
components: {
Rules,
VueSelect,
CInputSelect,
},
mixins: [
calculateDropdownPosition
],
props: {
labels: {
required: false,
@@ -291,8 +287,7 @@ export default {
// List of all available roles
roles: [],
// Current role object
currentRole: undefined,
currentRoleID: undefined,
evaluate: [],
@@ -370,8 +365,8 @@ export default {
this.fetchPermissions().then(() => {
if (!this.roles.length) {
return this.fetchRoles()
} else if (this.currentRole) {
const { roleID } = this.currentRole
} else if (this.currentRoleID) {
const roleID = this.currentRoleID
this.processing = true
return this.fetchRules(roleID).then(() => {
@@ -404,7 +399,7 @@ export default {
this.target = undefined
},
onRoleChange ({ roleID }) {
onRoleChange (roleID) {
this.fetchRules(roleID)
},
@@ -412,7 +407,7 @@ export default {
this.processing = true
const rules = this.collectChangedRules()
const { roleID } = this.currentRole
const roleID = this.currentRoleID
this.api.permissionsUpdate({ roleID, rules }).then(() => {
this.fetchRules(roleID)
@@ -455,8 +450,8 @@ export default {
.sort((a, b) => a.roleID.localeCompare(b.roleID))
if (this.roles.length > 0) {
this.currentRole = this.roles[0]
this.onRoleChange(this.currentRole)
this.currentRoleID = this.roles[0].roleID
this.onRoleChange(this.currentRoleID)
}
}).finally(() => {
this.processing = false
@@ -490,7 +485,7 @@ export default {
},
onAddEval () {
const { userID } = this.add.userID || {}
const userID = this.add.userID || {}
let { roleID = [] } = this.add
roleID = roleID.map(({ roleID }) => roleID)
@@ -513,9 +508,9 @@ export default {
this.evaluate.splice(i, 1)
},
getEvalName ({ roleID, userID }) {
getEvalName ({ userID, roleID }) {
if (userID) {
const { name, username, email, handle } = userID
const { name, username, email, handle } = this.userOptions.find(({ userID: id }) => id === userID) || {}
return [name || username || email || handle || userID || '']
} else {
return roleID.map(({ name }) => name)
@@ -615,7 +610,7 @@ export default {
this.permissions = []
this.rules = []
this.roles = []
this.currentRole = undefined
this.currentRoleID = undefined
this.evaluate = []
this.add = {}
},
@@ -1,5 +1,5 @@
<template>
<vue-select
<c-input-select
data-test-id="select-sens-lvl"
key="type"
:value="_value"
@@ -10,26 +10,19 @@
:placeholder="placeholder"
:reduce="l => l.sensitivityLevelID"
append-to-body
:calculate-position="calculateDropdownPosition"
class="bg-white rounded"
@input="onInput"
/>
</template>
<script>
import { NoID } from '@cortezaproject/corteza-js'
import { VueSelect } from 'vue-select'
import calculateDropdownPosition from '../../mixins/vue-select-position'
import CInputSelect from '../input/CInputSelect.vue'
export default {
components: {
VueSelect,
CInputSelect,
},
mixins: [
calculateDropdownPosition
],
props: {
value: {
type: String,
@@ -6,7 +6,7 @@
<div
class="text-center m-2"
>
<vue-select
<c-input-select
v-model="value"
:options="options"
:get-option-key="getOptionKey"
@@ -17,7 +17,7 @@
option-text="label"
placeholder="Select record"
:filterable="false"
class="bg-white w-100 mb-3 rounded"
class="w-100 mb-3"
@search="search"
>
<c-pagination
@@ -28,7 +28,7 @@
@prev="goToPage(false)"
@next="goToPage(true)"
/>
</vue-select>
</c-input-select>
<b-button
@click="$emit('submit', { value: encodeValue() })"
@@ -43,7 +43,7 @@
import base from './base.vue'
import CPagination from '../common/CPagination.vue'
import { pVal } from '../utils.ts'
import { VueSelect } from 'vue-select'
import CInputSelect from '../../input/CInputSelect.vue'
import { compose, NoID } from '@cortezaproject/corteza-js'
import { createPopper } from '@popperjs/core'
import { debounce } from 'lodash'
@@ -53,7 +53,7 @@ export default {
name: 'c-prompt-compose-record-picker',
components: {
VueSelect,
CInputSelect,
CPagination,
},
+4 -4
View File
@@ -11346,10 +11346,10 @@ vue-runtime-helpers@^1.1.2:
resolved "https://registry.yarnpkg.com/vue-runtime-helpers/-/vue-runtime-helpers-1.1.2.tgz#446b7b820888ab0c5264d2c3a32468e72e4100f3"
integrity sha512-pZfGp+PW/IXEOyETE09xQHR1CKkR9HfHZdnMD/FVLUNI+HxYTa82evx5WrF6Kz4s82qtqHvMZ8MZpbk2zT2E1Q==
vue-select@^3.4.0:
version "3.16.0"
resolved "https://registry.yarnpkg.com/vue-select/-/vue-select-3.16.0.tgz#db2ee2ddf80bd8876ce57738107b8a1a741862f4"
integrity sha512-F0x7HXTUc5eq7YSjR0uX77RGA+Yk2+I8aMW+NePyPqRX9OPSiDtKpezFIFhnhxqrOvMh4uVR0jHkXIDmzs6nYQ==
vue-select@3.20.2:
version "3.20.2"
resolved "https://registry.yarnpkg.com/vue-select/-/vue-select-3.20.2.tgz#eaa15012b032c154d4fb51ac82ebeda2beeae54b"
integrity sha512-ZSzIDzyYsWZULGUxVp1h6u3yi9IZQBWX8r6kSudUI/I5J1HQKpBjRntvkrg6pr87xmm16kdChvHCDN+W84vTKw==
vue-style-loader@^4.1.0, vue-style-loader@^4.1.2:
version "4.1.3"