You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SettingsField.vue 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <template>
  2. <MenuItem
  3. :label="fieldLabel"
  4. :description="fieldDescription"
  5. :data-id="field.id">
  6. <slot>
  7. <div v-if="!readonly" class="flex-1">
  8. <!-- Select -->
  9. <select v-if="field.input === 'select'"
  10. v-model="localValue"
  11. class="input"
  12. v-bind="inputAttrs">
  13. <option v-for="(option, index) in selectOptions" :key="index" :value="option.value">
  14. {{ option.label }}
  15. </option>
  16. </select>
  17. <!-- Input -->
  18. <input v-if="field.input === 'input'"
  19. v-model="localValue"
  20. class="input"
  21. v-bind="inputAttrs">
  22. </div>
  23. <span v-else>{{ valueLabel }}</span>
  24. </slot>
  25. </MenuItem>
  26. </template>
  27. <script>
  28. import { get, set, find } from 'lodash'
  29. import { VModel } from '~/mixins'
  30. export default {
  31. mixins: [VModel],
  32. props: {
  33. fieldId: {
  34. type: String,
  35. required: true,
  36. },
  37. label: {
  38. type: String,
  39. default: null,
  40. },
  41. description: {
  42. type: String,
  43. default: null,
  44. },
  45. options: {
  46. type: Array,
  47. default: null,
  48. },
  49. optionsField: {
  50. type: String,
  51. default: 'options',
  52. },
  53. attrs: {
  54. type: Object,
  55. default: null,
  56. },
  57. readonly: {
  58. type: Boolean,
  59. default: false,
  60. },
  61. ignoreHardcoded: {
  62. type: Boolean,
  63. defalt: false,
  64. },
  65. },
  66. data: () => ({
  67. localValue: null,
  68. field: null,
  69. firstWatchIgnored: false,
  70. }),
  71. computed: {
  72. selectOptions() {
  73. if (this.options) {
  74. return this.options
  75. }
  76. return this.field[this.optionsField]
  77. },
  78. valueLabel() {
  79. if (this.field.input === 'select') {
  80. const option = find(this.selectOptions, { value: this.localValue })
  81. return option.label
  82. }
  83. return this.localValue
  84. },
  85. localFieldId() {
  86. let fieldId = this.field.id
  87. // FIXME: HARD CODED!
  88. if (!this.ignoreHardcoded && fieldId.includes('preferences.')) {
  89. fieldId = fieldId.substring('preferences.'.length)
  90. }
  91. return fieldId
  92. },
  93. fieldLabel() {
  94. if (this.label) {
  95. return this.label
  96. }
  97. return this.field.label
  98. },
  99. fieldDescription() {
  100. if (this.description) {
  101. return this.description
  102. }
  103. return this.field.description
  104. },
  105. inputAttrs() {
  106. if (this.attrs) {
  107. return this.attrs
  108. }
  109. return this.field.attrs || {}
  110. },
  111. },
  112. watch: {
  113. localValue(value) {
  114. if (!this.firstWatchIgnored) {
  115. this.firstWatchIgnored = true
  116. return
  117. }
  118. if (this.value$) {
  119. this.value$ = set(this.value$, this.localFieldId, value)
  120. } else {
  121. this.$settings.set(this.field.id, value)
  122. }
  123. this.$emit('change')
  124. },
  125. },
  126. created() {
  127. this.field = this.$settings.getField(this.fieldId)
  128. if (!this.field) {
  129. throw new Error(`Invalid field ID: ${this.fieldId}`)
  130. }
  131. if (this.value) {
  132. this.localValue = get(this.value, this.localFieldId)
  133. } else {
  134. this.localValue = this.$settings.get(this.fieldId)
  135. }
  136. },
  137. }
  138. </script>
  139. <style lang="scss" scoped>
  140. .item {
  141. &::v-deep {
  142. .item__action {
  143. @apply flex items-center justify-center;
  144. //max-width: 300px;
  145. }
  146. }
  147. }
  148. </style>