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.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 Vue, { PropType } from 'vue'
  82. import { mdiReload } from '@mdi/js'
  83. import { LabelDTO } from '~/services/application/label/labelData'
  84. export default Vue.extend({
  85. props: {
  86. items: {
  87. type: Array as PropType<LabelDTO[]>,
  88. default: () => [],
  89. required: true
  90. },
  91. id: {
  92. type: Number as () => number | undefined,
  93. default: undefined
  94. },
  95. text: {
  96. type: String,
  97. required: true
  98. },
  99. backgroundColor: {
  100. type: String,
  101. required: true
  102. },
  103. suffixKey: {
  104. type: String as () => string | null,
  105. default: null
  106. }
  107. },
  108. data() {
  109. return {
  110. selectedColorIndex: 0,
  111. valid: false,
  112. rules: {
  113. required: (v: string) => !!v || 'Required',
  114. counter: (
  115. v: string // @ts-ignore
  116. ) => (v && v.length <= 100) || this.$t('rules.labelNameRules').labelLessThan100Chars,
  117. nameDuplicated: (
  118. v: string // @ts-ignore
  119. ) => !this.isUsedName(v) || this.$t('rules.labelNameRules').duplicated,
  120. keyDuplicated: (
  121. v: string // @ts-ignore
  122. ) => !this.isUsedSuffixKey(v) || this.$t('rules.keyNameRules').duplicated,
  123. validColor: (v: string) =>
  124. /^#[0-9A-F]{6}$/i.test(v) || 'This string is NOT a valid hex color.'
  125. },
  126. mdiReload
  127. }
  128. },
  129. computed: {
  130. availableSuffixKeys(): string[] {
  131. const usedSuffixKeys = this.items
  132. .map((item) => item.suffixKey)
  133. .filter((item) => item !== this.suffixKey)
  134. const allSuffixKeys = '0123456789abcdefghijklmnopqrstuvwxyz'.split('')
  135. return allSuffixKeys.filter((item) => !usedSuffixKeys.includes(item))
  136. },
  137. predefinedColors(): string[] {
  138. return [
  139. '#73D8FF',
  140. '#009CE0',
  141. '#0062B1',
  142. '#AEA1FF',
  143. '#7B64FF',
  144. '#653294',
  145. '#FDA1FF',
  146. '#FA28FF',
  147. '#AB149E',
  148. '#68CCCA',
  149. '#16A5A5',
  150. '#0C797D',
  151. '#A4DD00',
  152. '#68BC00',
  153. '#194D33',
  154. '#FCDC00',
  155. '#FCC400',
  156. '#FB9E00',
  157. '#F44E3B',
  158. '#D33115',
  159. '#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>