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.

205 lines
5.6 KiB

3 years ago
3 years ago
3 years ago
3 years ago
  1. <template>
  2. <v-card>
  3. <v-card-title>Create a Label Type</v-card-title>
  4. <v-card-text>
  5. <v-form
  6. ref="form"
  7. v-model="valid"
  8. >
  9. <v-row>
  10. <v-col cols="12" sm="6">
  11. <v-text-field
  12. :value="text"
  13. :counter="100"
  14. :label="$t('labels.labelName')"
  15. :rules="[rules.required, rules.counter, rules.nameDuplicated]"
  16. outlined
  17. required
  18. @input="$emit('update:text', $event)"
  19. />
  20. </v-col>
  21. <v-col cols="12" sm="6">
  22. <v-select
  23. :value="suffixKey"
  24. :items="availableSuffixKeys"
  25. :label="$t('labels.key')"
  26. :rules="[rules.keyDuplicated]"
  27. outlined
  28. @input="$emit('update:suffixKey', $event)"
  29. />
  30. </v-col>
  31. </v-row>
  32. <v-row>
  33. <v-col cols="12" sm="12">
  34. <v-text-field
  35. :value="backgroundColor"
  36. :rules="[rules.validColor]"
  37. label="Color"
  38. hide-details="auto"
  39. outlined
  40. required
  41. @input="$emit('update:backgroundColor', $event)"
  42. />
  43. <v-chip-group
  44. v-model="selectedColorIndex"
  45. column
  46. mandatory
  47. >
  48. <v-chip
  49. v-for="color in predefinedColors"
  50. :key="color"
  51. :color="color"
  52. filter
  53. label
  54. style="height: 32px; width: 32px;"
  55. />
  56. <v-tooltip bottom>
  57. <template #activator="{ on, attrs }">
  58. <v-chip
  59. label
  60. v-bind="attrs"
  61. v-on="on"
  62. @click="setRandomColor"
  63. >
  64. <v-icon>{{ mdiReload }}</v-icon>
  65. </v-chip>
  66. </template>
  67. <span>Random color</span>
  68. </v-tooltip>
  69. </v-chip-group>
  70. </v-col>
  71. </v-row>
  72. <v-row>
  73. <v-col>
  74. <div class="title black--text mb-2">Preview</div>
  75. <v-chip
  76. :color="backgroundColor"
  77. :text-color="textColor"
  78. >
  79. {{ text }}
  80. <v-avatar
  81. v-if="suffixKey"
  82. right
  83. color="white"
  84. class="black--text font-weight-bold"
  85. >
  86. {{ suffixKey }}
  87. </v-avatar>
  88. </v-chip>
  89. </v-col>
  90. </v-row>
  91. <v-row>
  92. <v-col cols="12" sm="12">
  93. <slot :valid="valid" />
  94. </v-col>
  95. </v-row>
  96. </v-form>
  97. </v-card-text>
  98. </v-card>
  99. </template>
  100. <script lang="ts">
  101. import Vue, { PropType } from 'vue'
  102. import { mdiReload } from '@mdi/js';
  103. import { LabelDTO } from '~/services/application/label/labelData'
  104. export default Vue.extend({
  105. props: {
  106. items: {
  107. type: Array as PropType<LabelDTO[]>,
  108. default: () => [],
  109. required: true
  110. },
  111. id: {
  112. type: Number as () => number | undefined,
  113. default: undefined
  114. },
  115. text: {
  116. type: String,
  117. required: true,
  118. },
  119. backgroundColor: {
  120. type: String,
  121. required: true,
  122. },
  123. suffixKey: {
  124. type: String as () => string | null,
  125. default: null
  126. }
  127. },
  128. data() {
  129. return {
  130. selectedColorIndex: 0,
  131. valid: false,
  132. rules: {
  133. required: (v: string) => !!v || 'Required',
  134. // @ts-ignore
  135. counter: (v: string) => (v && v.length <= 100) || this.$t('rules.labelNameRules').labelLessThan100Chars,
  136. // @ts-ignore
  137. nameDuplicated: (v: string) => (!this.isUsedName(v)) || this.$t('rules.labelNameRules').duplicated,
  138. // @ts-ignore
  139. keyDuplicated: (v: string) => (!this.isUsedSuffixKey(v)) || this.$t('rules.keyNameRules').duplicated,
  140. validColor: (v: string) => (/^#[0-9A-F]{6}$/i.test(v)) || 'This string is NOT a valid hex color.'
  141. },
  142. mdiReload
  143. }
  144. },
  145. computed: {
  146. availableSuffixKeys(): string[] {
  147. const usedSuffixKeys = this.items.map(item => item.suffixKey).filter(item => item !== this.suffixKey)
  148. const allSuffixKeys = '0123456789abcdefghijklmnopqrstuvwxyz'.split('')
  149. return allSuffixKeys.filter(item => !usedSuffixKeys.includes(item))
  150. },
  151. predefinedColors(): string[] {
  152. return [
  153. '#73D8FF', '#009CE0', '#0062B1',
  154. '#AEA1FF', '#7B64FF', '#653294',
  155. '#FDA1FF', '#FA28FF', '#AB149E',
  156. '#68CCCA', '#16A5A5', '#0C797D',
  157. '#A4DD00', '#68BC00', '#194D33',
  158. '#FCDC00', '#FCC400', '#FB9E00',
  159. '#F44E3B', '#D33115', '#9F0500'
  160. ]
  161. },
  162. textColor(): string {
  163. return this.$contrastColor(this.backgroundColor)
  164. }
  165. },
  166. watch: {
  167. selectedColorIndex(value) {
  168. if (value < this.predefinedColors.length) {
  169. this.$emit('update:backgroundColor', this.predefinedColors[this.selectedColorIndex])
  170. }
  171. }
  172. },
  173. methods: {
  174. isUsedName(text: string): boolean {
  175. return this.items.filter(item => item.id !== this.id && item.text === text).length > 0
  176. },
  177. isUsedSuffixKey(key: string) {
  178. if (key === null) {
  179. return false
  180. }
  181. return this.items.filter(item => item.id !== this.id && item.suffixKey === key).length > 0
  182. },
  183. setRandomColor() {
  184. const maxVal = 0xFFFFFF
  185. const randomNumber = Math.floor(Math.random() * maxVal)
  186. const randomString = randomNumber.toString(16)
  187. const randColor = randomString.padStart(6, '0')
  188. this.$emit('update:backgroundColor', `#${randColor.toUpperCase()}`)
  189. }
  190. }
  191. })
  192. </script>