diff options
Diffstat (limited to 'app/assets/javascripts/blob/filepath_form/components/template_selector.vue')
-rw-r--r-- | app/assets/javascripts/blob/filepath_form/components/template_selector.vue | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/app/assets/javascripts/blob/filepath_form/components/template_selector.vue b/app/assets/javascripts/blob/filepath_form/components/template_selector.vue new file mode 100644 index 00000000000..51c69590796 --- /dev/null +++ b/app/assets/javascripts/blob/filepath_form/components/template_selector.vue @@ -0,0 +1,161 @@ +<script> +import { GlCollapsibleListbox } from '@gitlab/ui'; +import SuggestGitlabCiYml from '~/blob/suggest_gitlab_ci_yml/components/popover.vue'; +import { __ } from '~/locale'; + +const templateSelectors = [ + { + key: 'gitignore_names', + name: '.gitignore', + pattern: /(.gitignore)/, + type: 'gitignores', + }, + { + key: 'gitlab_ci_ymls', + name: '.gitlab-ci.yml', + pattern: /(.gitlab-ci.yml)/, + type: 'gitlab_ci_ymls', + }, + { + key: 'dockerfile_names', + name: __('Dockerfile'), + pattern: /(Dockerfile)/, + type: 'dockerfiles', + }, + { + key: 'licenses', + name: 'LICENSE', + pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i, + type: 'licenses', + }, +]; + +export default { + name: 'TemplateSelector', + components: { + SuggestGitlabCiYml, + GlCollapsibleListbox, + }, + props: { + filename: { + type: String, + required: true, + }, + templates: { + type: Object, + required: true, + }, + initialTemplate: { + type: String, + required: false, + default: undefined, + }, + suggestCiYmlData: { + type: Object, + required: false, + default: undefined, + }, + }, + data() { + return { + loading: false, + searchTerm: '', + selectedTemplate: undefined, + types: templateSelectors, + }; + }, + computed: { + activeType() { + return templateSelectors.find((selector) => selector.pattern.test(this.filename)); + }, + activeTemplatesList() { + return this.templates[this.activeType?.key]; + }, + selectedTemplateKey() { + return this.selectedTemplate?.key; + }, + dropdownToggleText() { + return this.selectedTemplate?.name || this.$options.i18n.templateSelectorTxt; + }, + dropdownItems() { + return Object.entries(this.activeTemplatesList) + .map(([key, items]) => ({ + text: key, + options: items + .filter((item) => item.name.toLowerCase().includes(this.searchTerm)) + .map((item) => ({ + text: item.name, + value: item.key, + })), + })) + .filter((group) => group.options.length > 0); + }, + templateItems() { + return Object.values(this.activeTemplatesList).reduce((acc, items) => [...acc, ...items], []); + }, + showDropdown() { + return this.activeType && this.templateItems.length > 0; + }, + showPopover() { + return this.activeType?.key === 'gitlab_ci_ymls' && this.suggestCiYmlData; + }, + }, + beforeMount() { + if (this.activeType) this.applyTemplate(this.initialTemplate); + }, + methods: { + applyTemplate(templateKey) { + this.selectedTemplate = this.templateItems.find((item) => item.key === templateKey); + if (this.selectedTemplate) { + this.loading = true; + this.$emit('selected', { + template: this.selectedTemplate, + type: this.activeType, + clearSelectedTemplate: this.clearSelectedTemplate, + stopLoading: this.stopLoading, + }); + } + }, + stopLoading() { + this.loading = false; + }, + clearSelectedTemplate() { + this.selectedTemplate = undefined; + }, + onSearch(searchTerm) { + this.searchTerm = searchTerm.trim().toLowerCase(); + }, + }, + i18n: { + templateSelectorTxt: __('Apply a template'), + searchPlaceholder: __('Filter'), + }, +}; +</script> +<template> + <div v-if="showDropdown"> + <suggest-gitlab-ci-yml + v-if="showPopover" + target="template-selector" + :track-label="suggestCiYmlData.trackLabel" + :dismiss-key="suggestCiYmlData.dismissKey" + :merge-request-path="suggestCiYmlData.mergeRequestPath" + :human-access="suggestCiYmlData.humanAccess" + /> + <gl-collapsible-listbox + id="template-selector" + searchable + block + class="gl-font-regular" + data-testid="template-selector" + data-qa-selector="template_selector" + :toggle-text="dropdownToggleText" + :search-placeholder="$options.i18n.searchPlaceholder" + :items="dropdownItems" + :selected="selectedTemplateKey" + :loading="loading" + @select="applyTemplate" + @search="onSearch" + /> + </div> +</template> |