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.

206 lines
5.5 KiB

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