Add Vue linting (#13447)
* Add Vue linting Turns out the .vue files were not linted at all, so I added that as well as re-indented the file to 2-space and fixed all reasonable issues that cam up except one case of a unintended side effect for which I have no idea how to fix it, so the rule was disabled. * misc tweaks * update lockfile * use overrides to include .vue files * treat warnings as errors on lint-frontend * also treat stylelint warnings as errors * use equal sign syntax Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
		
							parent
							
								
									ed47da2e29
								
							
						
					
					
						commit
						7c47e24093
					
				
					 7 changed files with 295 additions and 243 deletions
				
			
		
							
								
								
									
										11
									
								
								.eslintrc
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								.eslintrc
									
									
									
									
									
								
							|  | @ -11,6 +11,10 @@ parserOptions: | ||||||
| plugins: | plugins: | ||||||
|   - eslint-plugin-unicorn |   - eslint-plugin-unicorn | ||||||
|   - eslint-plugin-import |   - eslint-plugin-import | ||||||
|  |   - eslint-plugin-vue | ||||||
|  | 
 | ||||||
|  | extends: | ||||||
|  |   - plugin:vue/recommended | ||||||
| 
 | 
 | ||||||
| env: | env: | ||||||
|   es2021: true |   es2021: true | ||||||
|  | @ -24,7 +28,7 @@ globals: | ||||||
|   u2fApi: false |   u2fApi: false | ||||||
| 
 | 
 | ||||||
| overrides: | overrides: | ||||||
|   - files: ["web_src/**/*.js"] |   - files: ["web_src/**/*.js", "web_src/**/*.vue"] | ||||||
|     env: |     env: | ||||||
|       browser: true |       browser: true | ||||||
|       jquery: true |       jquery: true | ||||||
|  | @ -387,6 +391,11 @@ rules: | ||||||
|   use-isnan: [2] |   use-isnan: [2] | ||||||
|   valid-typeof: [2, {requireStringLiterals: true}] |   valid-typeof: [2, {requireStringLiterals: true}] | ||||||
|   vars-on-top: [0] |   vars-on-top: [0] | ||||||
|  |   vue/attributes-order: [0] | ||||||
|  |   vue/component-definition-name-casing: [0] | ||||||
|  |   vue/html-closing-bracket-spacing: [0] | ||||||
|  |   vue/max-attributes-per-line: [0] | ||||||
|  |   vue/one-component-per-file: [0] | ||||||
|   wrap-iife: [2, inside] |   wrap-iife: [2, inside] | ||||||
|   wrap-regex: [0] |   wrap-regex: [0] | ||||||
|   yield-star-spacing: [2, after] |   yield-star-spacing: [2, after] | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							|  | @ -312,8 +312,8 @@ lint: lint-frontend lint-backend | ||||||
| 
 | 
 | ||||||
| .PHONY: lint-frontend | .PHONY: lint-frontend | ||||||
| lint-frontend: node_modules | lint-frontend: node_modules | ||||||
| 	npx eslint web_src/js build webpack.config.js | 	npx eslint --max-warnings=0 web_src/js build webpack.config.js | ||||||
| 	npx stylelint web_src/less | 	npx stylelint --max-warnings=0 web_src/less | ||||||
| 
 | 
 | ||||||
| .PHONY: lint-backend | .PHONY: lint-backend | ||||||
| lint-backend: golangci-lint revive vet | lint-backend: golangci-lint revive vet | ||||||
|  |  | ||||||
							
								
								
									
										63
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										63
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							|  | @ -5195,6 +5195,26 @@ | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "eslint-plugin-vue": { | ||||||
|  |       "version": "7.1.0", | ||||||
|  |       "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-7.1.0.tgz", | ||||||
|  |       "integrity": "sha512-9dW7kj8/d2IkDdgNpvIhJdJ3XzU3x4PThXYMzWt49taktYnGyrTY6/bXCYZ/VtQKU9kXPntPrZ41+8Pw0Nxblg==", | ||||||
|  |       "dev": true, | ||||||
|  |       "requires": { | ||||||
|  |         "eslint-utils": "^2.1.0", | ||||||
|  |         "natural-compare": "^1.4.0", | ||||||
|  |         "semver": "^7.3.2", | ||||||
|  |         "vue-eslint-parser": "^7.1.1" | ||||||
|  |       }, | ||||||
|  |       "dependencies": { | ||||||
|  |         "semver": { | ||||||
|  |           "version": "7.3.2", | ||||||
|  |           "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", | ||||||
|  |           "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", | ||||||
|  |           "dev": true | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "eslint-scope": { |     "eslint-scope": { | ||||||
|       "version": "4.0.3", |       "version": "4.0.3", | ||||||
|       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", |       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", | ||||||
|  | @ -14005,6 +14025,49 @@ | ||||||
|         "v-tooltip": "^2.0.0-rc.32" |         "v-tooltip": "^2.0.0-rc.32" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "vue-eslint-parser": { | ||||||
|  |       "version": "7.1.1", | ||||||
|  |       "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz", | ||||||
|  |       "integrity": "sha512-8FdXi0gieEwh1IprIBafpiJWcApwrU+l2FEj8c1HtHFdNXMd0+2jUSjBVmcQYohf/E72irwAXEXLga6TQcB3FA==", | ||||||
|  |       "dev": true, | ||||||
|  |       "requires": { | ||||||
|  |         "debug": "^4.1.1", | ||||||
|  |         "eslint-scope": "^5.0.0", | ||||||
|  |         "eslint-visitor-keys": "^1.1.0", | ||||||
|  |         "espree": "^6.2.1", | ||||||
|  |         "esquery": "^1.0.1", | ||||||
|  |         "lodash": "^4.17.15" | ||||||
|  |       }, | ||||||
|  |       "dependencies": { | ||||||
|  |         "acorn": { | ||||||
|  |           "version": "7.4.1", | ||||||
|  |           "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", | ||||||
|  |           "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", | ||||||
|  |           "dev": true | ||||||
|  |         }, | ||||||
|  |         "eslint-scope": { | ||||||
|  |           "version": "5.1.1", | ||||||
|  |           "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", | ||||||
|  |           "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "esrecurse": "^4.3.0", | ||||||
|  |             "estraverse": "^4.1.1" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "espree": { | ||||||
|  |           "version": "6.2.1", | ||||||
|  |           "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", | ||||||
|  |           "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", | ||||||
|  |           "dev": true, | ||||||
|  |           "requires": { | ||||||
|  |             "acorn": "^7.1.1", | ||||||
|  |             "acorn-jsx": "^5.2.0", | ||||||
|  |             "eslint-visitor-keys": "^1.1.0" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "vue-hot-reload-api": { |     "vue-hot-reload-api": { | ||||||
|       "version": "2.3.4", |       "version": "2.3.4", | ||||||
|       "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", |       "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", | ||||||
|  |  | ||||||
|  | @ -54,6 +54,7 @@ | ||||||
|     "eslint": "7.11.0", |     "eslint": "7.11.0", | ||||||
|     "eslint-plugin-import": "2.22.1", |     "eslint-plugin-import": "2.22.1", | ||||||
|     "eslint-plugin-unicorn": "23.0.0", |     "eslint-plugin-unicorn": "23.0.0", | ||||||
|  |     "eslint-plugin-vue": "7.1.0", | ||||||
|     "stylelint": "13.7.2", |     "stylelint": "13.7.2", | ||||||
|     "stylelint-config-standard": "20.0.0", |     "stylelint-config-standard": "20.0.0", | ||||||
|     "svgo": "1.3.2", |     "svgo": "1.3.2", | ||||||
|  |  | ||||||
|  | @ -1,39 +1,41 @@ | ||||||
| <template> | <template> | ||||||
|   <div> |   <div> | ||||||
|     <div v-show="isLoading"> |     <div v-show="isLoading"> | ||||||
|             <slot name="loading"></slot> |       <slot name="loading"/> | ||||||
|     </div> |     </div> | ||||||
|         <h4 class="total-contributions" v-if="!isLoading"> |     <h4 v-if="!isLoading" class="total-contributions"> | ||||||
|             {{ totalContributions }} total contributions in the last 12 months |       {{ values.length }} total contributions in the last 12 months | ||||||
|     </h4> |     </h4> | ||||||
|         <calendar-heatmap v-show="!isLoading" :locale="locale" :no-data-text="locale.no_contributions" :tooltip-unit="locale.contributions" :end-date="endDate" :values="values" :range-color="colorRange"/> |     <calendar-heatmap | ||||||
|  |       v-show="!isLoading" | ||||||
|  |       :locale="locale" | ||||||
|  |       :no-data-text="locale.no_contributions" | ||||||
|  |       :tooltip-unit="locale.contributions" | ||||||
|  |       :end-date="endDate" | ||||||
|  |       :values="values" | ||||||
|  |       :range-color="colorRange" | ||||||
|  |     /> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| 
 |  | ||||||
| <script> | <script> | ||||||
| import {CalendarHeatmap} from 'vue-calendar-heatmap'; | import {CalendarHeatmap} from 'vue-calendar-heatmap'; | ||||||
| const {AppSubUrl, heatmapUser} = window.config; | const {AppSubUrl, heatmapUser} = window.config; | ||||||
| 
 | 
 | ||||||
| export default { | export default { | ||||||
|     name: "ActivityHeatmap", |   name: 'ActivityHeatmap', | ||||||
|     components: { |   components: {CalendarHeatmap}, | ||||||
|         CalendarHeatmap |   data: () => ({ | ||||||
|     }, |  | ||||||
|     data() { |  | ||||||
|         return { |  | ||||||
|     isLoading: true, |     isLoading: true, | ||||||
|     colorRange: [], |     colorRange: [], | ||||||
|     endDate: null, |     endDate: null, | ||||||
|     values: [], |     values: [], | ||||||
|             totalContributions: 0, |  | ||||||
|     suburl: AppSubUrl, |     suburl: AppSubUrl, | ||||||
|     user: heatmapUser, |     user: heatmapUser, | ||||||
|     locale: { |     locale: { | ||||||
|       contributions: 'contributions', |       contributions: 'contributions', | ||||||
|       no_contributions: 'No contributions', |       no_contributions: 'No contributions', | ||||||
|     }, |     }, | ||||||
|         }; |   }), | ||||||
|     }, |  | ||||||
|   mounted() { |   mounted() { | ||||||
|     this.colorRange = [ |     this.colorRange = [ | ||||||
|       this.getColor(0), |       this.getColor(0), | ||||||
|  | @ -47,33 +49,23 @@ export default { | ||||||
|     this.loadHeatmap(this.user); |     this.loadHeatmap(this.user); | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|         loadHeatmap(userName) { |     async loadHeatmap(userName) { | ||||||
|             const self = this; |       const res = await fetch(`${this.suburl}/api/v1/users/${userName}/heatmap`); | ||||||
|             $.get(`${this.suburl}/api/v1/users/${userName}/heatmap`, (chartRawData) => { |       const data = await res.json(); | ||||||
|                 const chartData = []; |       this.values = data.map(({contributions, timestamp}) => { | ||||||
|                 for (let i = 0; i < chartRawData.length; i++) { |         return {date: new Date(timestamp * 1000), count: contributions}; | ||||||
|                     self.totalContributions += chartRawData[i].contributions; |  | ||||||
|                     chartData[i] = {date: new Date(chartRawData[i].timestamp * 1000), count: chartRawData[i].contributions}; |  | ||||||
|                 } |  | ||||||
|                 self.values = chartData; |  | ||||||
|                 self.isLoading = false; |  | ||||||
|       }); |       }); | ||||||
|  |       this.isLoading = false; | ||||||
|     }, |     }, | ||||||
|     getColor(idx) { |     getColor(idx) { | ||||||
|       const el = document.createElement('div'); |       const el = document.createElement('div'); | ||||||
|       el.className = `heatmap-color-${idx}`; |       el.className = `heatmap-color-${idx}`; | ||||||
|       document.body.appendChild(el); |       document.body.appendChild(el); | ||||||
| 
 |  | ||||||
|       const color = getComputedStyle(el).backgroundColor; |       const color = getComputedStyle(el).backgroundColor; | ||||||
| 
 |  | ||||||
|       document.body.removeChild(el); |       document.body.removeChild(el); | ||||||
| 
 |  | ||||||
|       return color; |       return color; | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
| } | }; | ||||||
| </script> | </script> | ||||||
| 
 | <style scoped/> | ||||||
| <style scoped> |  | ||||||
| 
 |  | ||||||
| </style> |  | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| <template> | <template> | ||||||
|   <div> |   <div> | ||||||
|         <div class="activity-bar-graph" ref="style" style="width:0px;height:0px"></div> |     <div class="activity-bar-graph" ref="style" style="width:0px;height:0px"/> | ||||||
|         <div class="activity-bar-graph-alt" ref="altStyle" style="width:0px;height:0px"></div> |     <div class="activity-bar-graph-alt" ref="altStyle" style="width:0px;height:0px"/> | ||||||
|     <vue-bar-graph |     <vue-bar-graph | ||||||
|       :points="graphData" |       :points="graphData" | ||||||
|       :show-x-axis="true" |       :show-x-axis="true" | ||||||
|  | @ -14,7 +14,7 @@ | ||||||
|       :height="100" |       :height="100" | ||||||
|       :label-height="20" |       :label-height="20" | ||||||
|     > |     > | ||||||
|             <template v-slot:label="opt"> |       <template #label="opt"> | ||||||
|         <g v-for="(author, idx) in authors" :key="author.position"> |         <g v-for="(author, idx) in authors" :key="author.position"> | ||||||
|           <a |           <a | ||||||
|             v-if="opt.bar.index === idx && author.home_link !== ''" |             v-if="opt.bar.index === idx && author.home_link !== ''" | ||||||
|  | @ -38,40 +38,31 @@ | ||||||
|           /> |           /> | ||||||
|         </g> |         </g> | ||||||
|       </template> |       </template> | ||||||
|             <template v-slot:title="opt"> |       <template #title="opt"> | ||||||
|                 <tspan v-for="(author, idx) in authors" :key="author.position"><tspan v-if="opt.bar.index === idx">{{ author.name }}</tspan></tspan> |         <tspan v-for="(author, idx) in authors" :key="author.position"> | ||||||
|  |           <tspan v-if="opt.bar.index === idx"> | ||||||
|  |             {{ author.name }} | ||||||
|  |           </tspan> | ||||||
|  |         </tspan> | ||||||
|       </template> |       </template> | ||||||
|     </vue-bar-graph> |     </vue-bar-graph> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| 
 |  | ||||||
| <script> | <script> | ||||||
| import VueBarGraph from 'vue-bar-graph'; | import VueBarGraph from 'vue-bar-graph'; | ||||||
| 
 | 
 | ||||||
| export default { | export default { | ||||||
|     components: { |   components: {VueBarGraph}, | ||||||
|         VueBarGraph, |  | ||||||
|     }, |  | ||||||
|   props: { |   props: { | ||||||
|         data: { type: Array, default: () => [] }, |     data: {type: Array, default: () => []}, | ||||||
|   }, |   }, | ||||||
|     mounted() { |   data: () => ({ | ||||||
|         const st = window.getComputedStyle(this.$refs.style); |  | ||||||
|         const stalt = window.getComputedStyle(this.$refs.altStyle); |  | ||||||
| 
 |  | ||||||
|         this.colors.barColor = st.backgroundColor; |  | ||||||
|         this.colors.textColor = st.color; |  | ||||||
|         this.colors.textAltColor = stalt.color; |  | ||||||
|     }, |  | ||||||
|     data() { |  | ||||||
|         return { |  | ||||||
|     colors: { |     colors: { | ||||||
|       barColor: 'green', |       barColor: 'green', | ||||||
|       textColor: 'black', |       textColor: 'black', | ||||||
|       textAltColor: 'white', |       textAltColor: 'white', | ||||||
|     }, |     }, | ||||||
|         }; |   }), | ||||||
|     }, |  | ||||||
|   computed: { |   computed: { | ||||||
|     graphData() { |     graphData() { | ||||||
|       return this.data.map((item) => { |       return this.data.map((item) => { | ||||||
|  | @ -84,19 +75,27 @@ export default { | ||||||
|     authors() { |     authors() { | ||||||
|       return this.data.map((item, idx) => { |       return this.data.map((item, idx) => { | ||||||
|         return { |         return { | ||||||
|                     position: idx+1, |           position: idx + 1, | ||||||
|           ...item, |           ...item, | ||||||
|                 } |         }; | ||||||
|       }); |       }); | ||||||
|     }, |     }, | ||||||
|     graphWidth() { |     graphWidth() { | ||||||
|       return this.data.length * 40; |       return this.data.length * 40; | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|  |   mounted() { | ||||||
|  |     const st = window.getComputedStyle(this.$refs.style); | ||||||
|  |     const stalt = window.getComputedStyle(this.$refs.altStyle); | ||||||
|  | 
 | ||||||
|  |     this.colors.barColor = st.backgroundColor; | ||||||
|  |     this.colors.textColor = st.color; | ||||||
|  |     this.colors.textAltColor = stalt.color; | ||||||
|  |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     hasHomeLink(i) { |     hasHomeLink(i) { | ||||||
|       return this.graphData[i].homeLink !== '' && this.graphData[i].homeLink !== null; |       return this.graphData[i].homeLink !== '' && this.graphData[i].homeLink !== null; | ||||||
|     }, |     }, | ||||||
|   } |   } | ||||||
| } | }; | ||||||
| </script> | </script> | ||||||
|  | @ -2687,7 +2687,15 @@ function initVueComponents() { | ||||||
|       .replace(/height="[0-9]+"/, 'v-bind:height="size"') |       .replace(/height="[0-9]+"/, 'v-bind:height="size"') | ||||||
|       .replace(/width="[0-9]+"/, 'v-bind:width="size"'); |       .replace(/width="[0-9]+"/, 'v-bind:width="size"'); | ||||||
| 
 | 
 | ||||||
|     Vue.component(name, {props: ['size'], template}); |     Vue.component(name, { | ||||||
|  |       props: { | ||||||
|  |         size: { | ||||||
|  |           type: String, | ||||||
|  |           default: '16', | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |       template, | ||||||
|  |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const vueDelimeters = ['${', '}']; |   const vueDelimeters = ['${', '}']; | ||||||
|  | @ -2710,7 +2718,7 @@ function initVueComponents() { | ||||||
|       }, |       }, | ||||||
|       organizations: { |       organizations: { | ||||||
|         type: Array, |         type: Array, | ||||||
|         default: [] |         default: () => [], | ||||||
|       }, |       }, | ||||||
|       isOrganization: { |       isOrganization: { | ||||||
|         type: Boolean, |         type: Boolean, | ||||||
|  | @ -3050,16 +3058,18 @@ function initVueApp() { | ||||||
|   initVueComponents(); |   initVueComponents(); | ||||||
| 
 | 
 | ||||||
|   new Vue({ |   new Vue({ | ||||||
|     delimiters: ['${', '}'], |  | ||||||
|     el, |     el, | ||||||
|     data: { |     delimiters: ['${', '}'], | ||||||
|  |     components: { | ||||||
|  |       ActivityTopAuthors, | ||||||
|  |     }, | ||||||
|  |     data: () => { | ||||||
|  |       return { | ||||||
|         searchLimit: Number((document.querySelector('meta[name=_search_limit]') || {}).content), |         searchLimit: Number((document.querySelector('meta[name=_search_limit]') || {}).content), | ||||||
|         suburl: AppSubUrl, |         suburl: AppSubUrl, | ||||||
|         uid: Number((document.querySelector('meta[name=_context_uid]') || {}).content), |         uid: Number((document.querySelector('meta[name=_context_uid]') || {}).content), | ||||||
|         activityTopAuthors: window.ActivityTopAuthors || [], |         activityTopAuthors: window.ActivityTopAuthors || [], | ||||||
|     }, |       }; | ||||||
|     components: { |  | ||||||
|       ActivityTopAuthors, |  | ||||||
|     }, |     }, | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  | @ -3105,24 +3115,30 @@ function initFilterBranchTagDropdown(selector) { | ||||||
|     }); |     }); | ||||||
|     $data.remove(); |     $data.remove(); | ||||||
|     new Vue({ |     new Vue({ | ||||||
|       delimiters: ['${', '}'], |  | ||||||
|       el: this, |       el: this, | ||||||
|  |       delimiters: ['${', '}'], | ||||||
|       data, |       data, | ||||||
| 
 |       computed: { | ||||||
|       beforeMount() { |         filteredItems() { | ||||||
|         const vm = this; |           const items = this.items.filter((item) => { | ||||||
| 
 |             return ((this.mode === 'branches' && item.branch) || (this.mode === 'tags' && item.tag)) && | ||||||
|         this.noResults = vm.$el.getAttribute('data-no-results'); |               (!this.searchTerm || item.name.toLowerCase().includes(this.searchTerm.toLowerCase())); | ||||||
|         this.canCreateBranch = vm.$el.getAttribute('data-can-create-branch') === 'true'; |  | ||||||
| 
 |  | ||||||
|         document.body.addEventListener('click', (event) => { |  | ||||||
|           if (vm.$el.contains(event.target)) { |  | ||||||
|             return; |  | ||||||
|           } |  | ||||||
|           if (vm.menuVisible) { |  | ||||||
|             Vue.set(vm, 'menuVisible', false); |  | ||||||
|           } |  | ||||||
|           }); |           }); | ||||||
|  | 
 | ||||||
|  |           // no idea how to fix this so linting rule is disabled instead
 | ||||||
|  |           this.active = (items.length === 0 && this.showCreateNewBranch ? 0 : -1); // eslint-disable-line vue/no-side-effects-in-computed-properties
 | ||||||
|  |           return items; | ||||||
|  |         }, | ||||||
|  |         showNoResults() { | ||||||
|  |           return this.filteredItems.length === 0 && !this.showCreateNewBranch; | ||||||
|  |         }, | ||||||
|  |         showCreateNewBranch() { | ||||||
|  |           if (!this.canCreateBranch || !this.searchTerm || this.mode === 'tags') { | ||||||
|  |             return false; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           return this.items.filter((item) => item.name.toLowerCase() === this.searchTerm.toLowerCase()).length === 0; | ||||||
|  |         } | ||||||
|       }, |       }, | ||||||
| 
 | 
 | ||||||
|       watch: { |       watch: { | ||||||
|  | @ -3133,30 +3149,16 @@ function initFilterBranchTagDropdown(selector) { | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
| 
 | 
 | ||||||
|       computed: { |       beforeMount() { | ||||||
|         filteredItems() { |         this.noResults = this.$el.getAttribute('data-no-results'); | ||||||
|           const vm = this; |         this.canCreateBranch = this.$el.getAttribute('data-can-create-branch') === 'true'; | ||||||
| 
 | 
 | ||||||
|           const items = vm.items.filter((item) => { |         document.body.addEventListener('click', (event) => { | ||||||
|             return ((vm.mode === 'branches' && item.branch) || (vm.mode === 'tags' && item.tag)) && |           if (this.$el.contains(event.target)) return; | ||||||
|               (!vm.searchTerm || item.name.toLowerCase().includes(vm.searchTerm.toLowerCase())); |           if (this.menuVisible) { | ||||||
|  |             Vue.set(this, 'menuVisible', false); | ||||||
|  |           } | ||||||
|         }); |         }); | ||||||
| 
 |  | ||||||
|           vm.active = (items.length === 0 && vm.showCreateNewBranch ? 0 : -1); |  | ||||||
| 
 |  | ||||||
|           return items; |  | ||||||
|         }, |  | ||||||
|         showNoResults() { |  | ||||||
|           return this.filteredItems.length === 0 && !this.showCreateNewBranch; |  | ||||||
|         }, |  | ||||||
|         showCreateNewBranch() { |  | ||||||
|           const vm = this; |  | ||||||
|           if (!this.canCreateBranch || !vm.searchTerm || vm.mode === 'tags') { |  | ||||||
|             return false; |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           return vm.items.filter((item) => item.name.toLowerCase() === vm.searchTerm.toLowerCase()).length === 0; |  | ||||||
|         } |  | ||||||
|       }, |       }, | ||||||
| 
 | 
 | ||||||
|       methods: { |       methods: { | ||||||
|  | @ -3169,15 +3171,12 @@ function initFilterBranchTagDropdown(selector) { | ||||||
|           window.location.href = item.url; |           window.location.href = item.url; | ||||||
|         }, |         }, | ||||||
|         createNewBranch() { |         createNewBranch() { | ||||||
|           if (!this.showCreateNewBranch) { |           if (!this.showCreateNewBranch) return; | ||||||
|             return; |  | ||||||
|           } |  | ||||||
|           $(this.$refs.newBranchForm).trigger('submit'); |           $(this.$refs.newBranchForm).trigger('submit'); | ||||||
|         }, |         }, | ||||||
|         focusSearchField() { |         focusSearchField() { | ||||||
|           const vm = this; |  | ||||||
|           Vue.nextTick(() => { |           Vue.nextTick(() => { | ||||||
|             vm.$refs.searchField.focus(); |             this.$refs.searchField.focus(); | ||||||
|           }); |           }); | ||||||
|         }, |         }, | ||||||
|         getSelected() { |         getSelected() { | ||||||
|  | @ -3194,15 +3193,12 @@ function initFilterBranchTagDropdown(selector) { | ||||||
|         }, |         }, | ||||||
|         scrollToActive() { |         scrollToActive() { | ||||||
|           let el = this.$refs[`listItem${this.active}`]; |           let el = this.$refs[`listItem${this.active}`]; | ||||||
|           if (!el || el.length === 0) { |           if (!el || !el.length) return; | ||||||
|             return; |  | ||||||
|           } |  | ||||||
|           if (Array.isArray(el)) { |           if (Array.isArray(el)) { | ||||||
|             el = el[0]; |             el = el[0]; | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           const cont = this.$refs.scrollContainer; |           const cont = this.$refs.scrollContainer; | ||||||
| 
 |  | ||||||
|           if (el.offsetTop < cont.scrollTop) { |           if (el.offsetTop < cont.scrollTop) { | ||||||
|             cont.scrollTop = el.offsetTop; |             cont.scrollTop = el.offsetTop; | ||||||
|           } else if (el.offsetTop + el.clientHeight > cont.scrollTop + cont.clientHeight) { |           } else if (el.offsetTop + el.clientHeight > cont.scrollTop + cont.clientHeight) { | ||||||
|  | @ -3210,49 +3206,41 @@ function initFilterBranchTagDropdown(selector) { | ||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|         keydown(event) { |         keydown(event) { | ||||||
|           const vm = this; |           if (event.keyCode === 40) { // arrow down
 | ||||||
|           if (event.keyCode === 40) { |  | ||||||
|             // arrow down
 |  | ||||||
|             event.preventDefault(); |             event.preventDefault(); | ||||||
| 
 | 
 | ||||||
|             if (vm.active === -1) { |             if (this.active === -1) { | ||||||
|               vm.active = vm.getSelectedIndexInFiltered(); |               this.active = this.getSelectedIndexInFiltered(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (vm.active + (vm.showCreateNewBranch ? 0 : 1) >= vm.filteredItems.length) { |             if (this.active + (this.showCreateNewBranch ? 0 : 1) >= this.filteredItems.length) { | ||||||
|               return; |               return; | ||||||
|             } |             } | ||||||
|             vm.active++; |             this.active++; | ||||||
|             vm.scrollToActive(); |             this.scrollToActive(); | ||||||
|           } |           } else if (event.keyCode === 38) { // arrow up
 | ||||||
|           if (event.keyCode === 38) { |  | ||||||
|             // arrow up
 |  | ||||||
|             event.preventDefault(); |             event.preventDefault(); | ||||||
| 
 | 
 | ||||||
|             if (vm.active === -1) { |             if (this.active === -1) { | ||||||
|               vm.active = vm.getSelectedIndexInFiltered(); |               this.active = this.getSelectedIndexInFiltered(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (vm.active <= 0) { |             if (this.active <= 0) { | ||||||
|               return; |               return; | ||||||
|             } |             } | ||||||
|             vm.active--; |             this.active--; | ||||||
|             vm.scrollToActive(); |             this.scrollToActive(); | ||||||
|           } |           } else if (event.keyCode === 13) { // enter
 | ||||||
|           if (event.keyCode === 13) { |  | ||||||
|             // enter
 |  | ||||||
|             event.preventDefault(); |             event.preventDefault(); | ||||||
| 
 | 
 | ||||||
|             if (vm.active >= vm.filteredItems.length) { |             if (this.active >= this.filteredItems.length) { | ||||||
|               vm.createNewBranch(); |               this.createNewBranch(); | ||||||
|             } else if (vm.active >= 0) { |             } else if (this.active >= 0) { | ||||||
|               vm.selectItem(vm.filteredItems[vm.active]); |               this.selectItem(this.filteredItems[this.active]); | ||||||
|             } |             } | ||||||
|           } |           } else if (event.keyCode === 27) { // escape
 | ||||||
|           if (event.keyCode === 27) { |  | ||||||
|             // escape
 |  | ||||||
|             event.preventDefault(); |             event.preventDefault(); | ||||||
|             vm.menuVisible = false; |             this.menuVisible = false; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue