1<script> 2import { 3 GlButton, 4 GlDropdown, 5 GlFormGroup, 6 GlIcon, 7 GlSearchBoxByType, 8 GlSkeletonLoader, 9} from '@gitlab/ui'; 10import { mapActions } from 'vuex'; 11import { __ } from '~/locale'; 12 13export default { 14 i18n: { 15 add: __('Add to board'), 16 cancel: __('Cancel'), 17 newList: __('New list'), 18 noResults: __('No matching results'), 19 scope: __('Scope'), 20 scopeDescription: __('Issues must match this scope to appear in this list.'), 21 selected: __('Selected'), 22 }, 23 components: { 24 GlButton, 25 GlDropdown, 26 GlFormGroup, 27 GlIcon, 28 GlSearchBoxByType, 29 GlSkeletonLoader, 30 }, 31 props: { 32 loading: { 33 type: Boolean, 34 required: true, 35 }, 36 searchLabel: { 37 type: String, 38 required: false, 39 default: null, 40 }, 41 noneSelected: { 42 type: String, 43 required: true, 44 }, 45 searchPlaceholder: { 46 type: String, 47 required: true, 48 }, 49 selectedId: { 50 type: [Number, String], 51 required: false, 52 default: null, 53 }, 54 }, 55 data() { 56 return { 57 searchValue: '', 58 }; 59 }, 60 watch: { 61 selectedId(val) { 62 if (val) { 63 this.$refs.dropdown.hide(true); 64 } 65 }, 66 }, 67 methods: { 68 ...mapActions(['setAddColumnFormVisibility']), 69 setFocus() { 70 this.$refs.searchBox.focusInput(); 71 }, 72 onHide() { 73 this.searchValue = ''; 74 this.$emit('filter-items', ''); 75 this.$emit('hide'); 76 }, 77 }, 78}; 79</script> 80 81<template> 82 <div 83 class="board-add-new-list board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal gl-flex-shrink-0" 84 data-testid="board-add-new-column" 85 data-qa-selector="board_add_new_list" 86 > 87 <div 88 class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base gl-bg-white" 89 > 90 <h3 91 class="gl-font-size-h2 gl-px-5 gl-py-4 gl-m-0 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100" 92 data-testid="board-add-column-form-title" 93 > 94 {{ $options.i18n.newList }} 95 </h3> 96 97 <div 98 class="gl-display-flex gl-flex-direction-column gl-h-full gl-overflow-y-auto gl-align-items-flex-start" 99 > 100 <div class="gl-px-5"> 101 <h3 class="gl-font-lg gl-mt-5 gl-mb-2"> 102 {{ $options.i18n.scope }} 103 </h3> 104 <p class="gl-mb-3">{{ $options.i18n.scopeDescription }}</p> 105 </div> 106 107 <slot name="select-list-type"></slot> 108 109 <gl-form-group class="gl-px-5 lg-mb-3 gl-max-w-full" :label="searchLabel"> 110 <gl-dropdown 111 ref="dropdown" 112 class="gl-mb-3 gl-max-w-full" 113 toggle-class="gl-max-w-full gl-display-flex gl-align-items-center gl-text-trunate" 114 boundary="viewport" 115 @shown="setFocus" 116 @hide="onHide" 117 > 118 <template #button-content> 119 <slot name="selected"> 120 <div>{{ noneSelected }}</div> 121 </slot> 122 <gl-icon class="dropdown-chevron gl-flex-shrink-0" name="chevron-down" /> 123 </template> 124 125 <template #header> 126 <gl-search-box-by-type 127 ref="searchBox" 128 v-model="searchValue" 129 debounce="250" 130 class="gl-mt-0!" 131 :placeholder="searchPlaceholder" 132 @input="$emit('filter-items', $event)" 133 /> 134 </template> 135 136 <div v-if="loading" class="gl-px-5"> 137 <gl-skeleton-loader :width="400" :height="172"> 138 <rect width="380" height="20" x="10" y="15" rx="4" /> 139 <rect width="280" height="20" x="10" y="50" rx="4" /> 140 <rect width="330" height="20" x="10" y="85" rx="4" /> 141 </gl-skeleton-loader> 142 </div> 143 144 <slot v-else name="items"> 145 <p class="gl-mx-5">{{ $options.i18n.noResults }}</p> 146 </slot> 147 </gl-dropdown> 148 </gl-form-group> 149 </div> 150 <div 151 class="gl-display-flex gl-p-3 gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-rounded-bottom-left-base gl-rounded-bottom-right-base" 152 > 153 <gl-button 154 data-testid="cancelAddNewColumn" 155 class="gl-ml-auto gl-mr-3" 156 @click="setAddColumnFormVisibility(false)" 157 >{{ $options.i18n.cancel }}</gl-button 158 > 159 <gl-button 160 data-testid="addNewColumnButton" 161 :disabled="!selectedId" 162 variant="confirm" 163 class="gl-mr-4" 164 @click="$emit('add-list')" 165 >{{ $options.i18n.add }}</gl-button 166 > 167 </div> 168 </div> 169 </div> 170</template> 171