summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2018-01-03 23:14:55 +0000
committerFilipa Lacerda <filipa@gitlab.com>2018-01-03 23:14:55 +0000
commitb299198e1eb5e1f26d5267f4a64944e600086d6b (patch)
tree441412c739e7dace4c2ba34099d19677d52e0314
parentfb583c4b1839af16c50e27105a300695aa50bcad (diff)
downloadgitlab-ce-b299198e1eb5e1f26d5267f4a64944e600086d6b.tar.gz
Adds `eslint-plugin-vue`, fixes linter errors and adds docs
-rw-r--r--.eslintrc9
-rw-r--r--app/assets/javascripts/blob/notebook/index.js76
-rw-r--r--app/assets/javascripts/blob/pdf/index.js6
-rw-r--r--app/assets/javascripts/boards/boards_bundle.js18
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue32
-rw-r--r--app/assets/javascripts/commit/image_file.js194
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js20
-rw-r--r--app/assets/javascripts/deploy_keys/index.js6
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue3
-rw-r--r--app/assets/javascripts/filtered_search/recent_searches_root.js6
-rw-r--r--app/assets/javascripts/groups/components/group_folder.vue6
-rw-r--r--app/assets/javascripts/groups/components/item_stats.vue7
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue4
-rw-r--r--app/assets/javascripts/ide/index.js10
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue6
-rw-r--r--app/assets/javascripts/jobs/job_details_bundle.js12
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js2
-rw-r--r--app/assets/javascripts/monitoring/components/empty_state.vue6
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue14
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue3
-rw-r--r--app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue3
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_url.vue12
-rw-r--r--app/assets/javascripts/pipelines/components/stage.vue4
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js12
-rw-r--r--app/assets/javascripts/pipelines/pipelines_bundle.js6
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue3
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue5
-rw-r--r--app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue3
-rw-r--r--doc/development/fe_guide/style_guide_js.md14
-rw-r--r--package.json1
-rw-r--r--spec/javascripts/boards/issue_card_spec.js6
-rw-r--r--spec/javascripts/vue_shared/components/markdown/field_spec.js6
-rw-r--r--yarn.lock44
33 files changed, 333 insertions, 226 deletions
diff --git a/.eslintrc b/.eslintrc
index 44ad6a4896c..a419dc521e8 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -4,7 +4,10 @@
"browser": true,
"es6": true
},
- "extends": "airbnb-base",
+ "extends": [
+ "airbnb-base",
+ "plugin:vue/recommended"
+ ],
"globals": {
"__webpack_public_path__": true,
"_": false,
@@ -12,7 +15,9 @@
"gon": false,
"localStorage": false
},
- "parser": "babel-eslint",
+ "parserOptions": {
+ "parser": "babel-eslint"
+ },
"plugins": [
"filenames",
"import",
diff --git a/app/assets/javascripts/blob/notebook/index.js b/app/assets/javascripts/blob/notebook/index.js
index 57b031956e8..6f1350e80fc 100644
--- a/app/assets/javascripts/blob/notebook/index.js
+++ b/app/assets/javascripts/blob/notebook/index.js
@@ -8,6 +8,9 @@ export default () => {
new Vue({
el,
+ components: {
+ notebookLab,
+ },
data() {
return {
error: false,
@@ -16,8 +19,41 @@ export default () => {
json: {},
};
},
- components: {
- notebookLab,
+ mounted() {
+ if (gon.katex_css_url) {
+ const katexStyles = document.createElement('link');
+ katexStyles.setAttribute('rel', 'stylesheet');
+ katexStyles.setAttribute('href', gon.katex_css_url);
+ document.head.appendChild(katexStyles);
+ }
+
+ if (gon.katex_js_url) {
+ const katexScript = document.createElement('script');
+ katexScript.addEventListener('load', () => {
+ this.loadFile();
+ });
+ katexScript.setAttribute('src', gon.katex_js_url);
+ document.head.appendChild(katexScript);
+ } else {
+ this.loadFile();
+ }
+ },
+ methods: {
+ loadFile() {
+ axios.get(el.dataset.endpoint)
+ .then(res => res.data)
+ .then((data) => {
+ this.json = data;
+ this.loading = false;
+ })
+ .catch((e) => {
+ if (e.status !== 200) {
+ this.loadError = true;
+ }
+
+ this.error = true;
+ });
+ },
},
template: `
<div class="container-fluid md prepend-top-default append-bottom-default">
@@ -46,41 +82,5 @@ export default () => {
</p>
</div>
`,
- methods: {
- loadFile() {
- axios.get(el.dataset.endpoint)
- .then(res => res.data)
- .then((data) => {
- this.json = data;
- this.loading = false;
- })
- .catch((e) => {
- if (e.status !== 200) {
- this.loadError = true;
- }
-
- this.error = true;
- });
- },
- },
- mounted() {
- if (gon.katex_css_url) {
- const katexStyles = document.createElement('link');
- katexStyles.setAttribute('rel', 'stylesheet');
- katexStyles.setAttribute('href', gon.katex_css_url);
- document.head.appendChild(katexStyles);
- }
-
- if (gon.katex_js_url) {
- const katexScript = document.createElement('script');
- katexScript.addEventListener('load', () => {
- this.loadFile();
- });
- katexScript.setAttribute('src', gon.katex_js_url);
- document.head.appendChild(katexScript);
- } else {
- this.loadFile();
- }
- },
});
};
diff --git a/app/assets/javascripts/blob/pdf/index.js b/app/assets/javascripts/blob/pdf/index.js
index 7109f356540..70136cc4087 100644
--- a/app/assets/javascripts/blob/pdf/index.js
+++ b/app/assets/javascripts/blob/pdf/index.js
@@ -7,6 +7,9 @@ export default () => {
return new Vue({
el,
+ components: {
+ pdfLab,
+ },
data() {
return {
error: false,
@@ -15,9 +18,6 @@ export default () => {
pdf: el.dataset.endpoint,
};
},
- components: {
- pdfLab,
- },
methods: {
onLoad() {
this.loading = false;
diff --git a/app/assets/javascripts/boards/boards_bundle.js b/app/assets/javascripts/boards/boards_bundle.js
index 679c883cdcf..90166b3d3d1 100644
--- a/app/assets/javascripts/boards/boards_bundle.js
+++ b/app/assets/javascripts/boards/boards_bundle.js
@@ -171,19 +171,14 @@ $(() => {
});
gl.IssueBoardsModalAddBtn = new Vue({
- mixins: [gl.issueBoards.ModalMixins],
el: document.getElementById('js-add-issues-btn'),
+ mixins: [gl.issueBoards.ModalMixins],
data() {
return {
modal: ModalStore.store,
store: Store.state,
};
},
- watch: {
- disabled() {
- this.updateTooltip();
- },
- },
computed: {
disabled() {
if (!this.store) {
@@ -199,6 +194,14 @@ $(() => {
return '';
},
},
+ watch: {
+ disabled() {
+ this.updateTooltip();
+ },
+ },
+ mounted() {
+ this.updateTooltip();
+ },
methods: {
updateTooltip() {
const $tooltip = $(this.$refs.addIssuesButton);
@@ -217,9 +220,6 @@ $(() => {
}
},
},
- mounted() {
- this.updateTooltip();
- },
template: `
<div class="board-extra-actions">
<button
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index cd58b88db69..1b0bbffe37e 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -21,7 +21,9 @@ export default {
computed: {
generalApplicationDescription() {
return sprintf(
- _.escape(s__('ClusterIntegration|Install applications on your cluster. Read more about %{helpLink}')), {
+ _.escape(s__(`ClusterIntegration|Install applications on your cluster.
+Read more about %{helpLink}`)),
+ {
helpLink: `<a href="${this.helpPath}">
${_.escape(s__('ClusterIntegration|installing applications'))}
</a>`,
@@ -43,12 +45,15 @@ export default {
));
const extraCostParagraph = sprintf(
- _.escape(s__('ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which incur additional costs. See %{pricingLink}')), {
- boldNotice: `<strong>${_.escape(s__('ClusterIntegration|Note:'))}</strong>`,
- pricingLink: `<a href="https://cloud.google.com/compute/pricing#lb" target="_blank" rel="noopener noreferrer">
- ${_.escape(s__('ClusterIntegration|GKE pricing'))}
- </a>`,
- },
+ _.escape(s__(`ClusterIntegration|%{boldNotice} This will add some
+extra resources like a load balancer,
+which incur additional costs. See %{pricingLink}`)),
+ {
+ boldNotice: `<strong>${_.escape(s__('ClusterIntegration|Note:'))}</strong>`,
+ pricingLink: `<a href="https://cloud.google.com/compute/pricing#lb" target="_blank" rel="noopener noreferrer">
+ ${_.escape(s__('ClusterIntegration|GKE pricing'))}
+ </a>`,
+ },
false,
);
@@ -69,11 +74,14 @@ export default {
},
prometheusDescription() {
return sprintf(
- _.escape(s__('ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications.')), {
- gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html", target="_blank" rel="noopener noreferrer">
- ${_.escape(s__('ClusterIntegration|Gitlab Integration'))}
- </a>`,
- },
+ _.escape(s__(`ClusterIntegration|Prometheus is an open-source monitoring system
+with %{gitlabIntegrationLink} to monitor deployed applications.`)),
+ {
+ gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
+target="_blank" rel="noopener noreferrer">
+ ${_.escape(s__('ClusterIntegration|Gitlab Integration'))}
+ </a>`,
+ },
false,
);
},
diff --git a/app/assets/javascripts/commit/image_file.js b/app/assets/javascripts/commit/image_file.js
index b6a0ece7907..485d81882d2 100644
--- a/app/assets/javascripts/commit/image_file.js
+++ b/app/assets/javascripts/commit/image_file.js
@@ -23,6 +23,103 @@ export default class ImageFile {
});
};
})(this));
+
+ this.views = {
+ 'two-up': function() {
+ return $('.two-up.view .wrap', this.file).each((function(_this) {
+ return function(index, wrap) {
+ $('img', wrap).each(function() {
+ var currentWidth;
+ currentWidth = $(this).width();
+ if (currentWidth > availWidth / 2) {
+ return $(this).width(availWidth / 2);
+ }
+ });
+ return _this.requestImageInfo($('img', wrap), function(width, height) {
+ $('.image-info .meta-width', wrap).text(width + "px");
+ $('.image-info .meta-height', wrap).text(height + "px");
+ return $('.image-info', wrap).removeClass('hide');
+ });
+ };
+ })(this));
+ },
+ 'swipe': function() {
+ var maxHeight, maxWidth;
+ maxWidth = 0;
+ maxHeight = 0;
+ return $('.swipe.view', this.file).each((function(_this) {
+ return function(index, view) {
+ var $swipeWrap, $swipeBar, $swipeFrame, wrapPadding, ref;
+ ref = _this.prepareFrames(view), maxWidth = ref[0], maxHeight = ref[1];
+ $swipeFrame = $('.swipe-frame', view);
+ $swipeWrap = $('.swipe-wrap', view);
+ $swipeBar = $('.swipe-bar', view);
+
+ $swipeFrame.css({
+ width: maxWidth + 16,
+ height: maxHeight + 28
+ });
+ $swipeWrap.css({
+ width: maxWidth + 1,
+ height: maxHeight + 2
+ });
+ // Set swipeBar left position to match image frame
+ $swipeBar.css({
+ left: 1
+ });
+
+ wrapPadding = parseInt($swipeWrap.css('right').replace('px', ''), 10);
+
+ _this.initDraggable($swipeBar, wrapPadding, function(e, left) {
+ if (left > 0 && left < $swipeFrame.width() - (wrapPadding * 2)) {
+ $swipeWrap.width((maxWidth + 1) - left);
+ $swipeBar.css('left', left);
+ }
+ });
+ };
+ })(this));
+ },
+ 'onion-skin': function() {
+ var dragTrackWidth, maxHeight, maxWidth;
+ maxWidth = 0;
+ maxHeight = 0;
+ dragTrackWidth = $('.drag-track', this.file).width() - $('.dragger', this.file).width();
+ return $('.onion-skin.view', this.file).each((function(_this) {
+ return function(index, view) {
+ var $frame, $track, $dragger, $frameAdded, framePadding, ref, dragging = false;
+ ref = _this.prepareFrames(view), maxWidth = ref[0], maxHeight = ref[1];
+ $frame = $('.onion-skin-frame', view);
+ $frameAdded = $('.frame.added', view);
+ $track = $('.drag-track', view);
+ $dragger = $('.dragger', $track);
+
+ $frame.css({
+ width: maxWidth + 16,
+ height: maxHeight + 28
+ });
+ $('.swipe-wrap', view).css({
+ width: maxWidth + 1,
+ height: maxHeight + 2
+ });
+ $dragger.css({
+ left: dragTrackWidth
+ });
+
+ $frameAdded.css('opacity', 1);
+ framePadding = parseInt($frameAdded.css('right').replace('px', ''), 10);
+
+ _this.initDraggable($dragger, framePadding, function(e, left) {
+ var opacity = left / dragTrackWidth;
+
+ if (opacity >= 0 && opacity <= 1) {
+ $dragger.css('left', left);
+ $frameAdded.css('opacity', opacity);
+ }
+ });
+ };
+ })(this));
+ }
+ };
}
initViewModes() {
@@ -95,103 +192,6 @@ export default class ImageFile {
return [maxWidth, maxHeight];
}
- views = {
- 'two-up': function() {
- return $('.two-up.view .wrap', this.file).each((function(_this) {
- return function(index, wrap) {
- $('img', wrap).each(function() {
- var currentWidth;
- currentWidth = $(this).width();
- if (currentWidth > availWidth / 2) {
- return $(this).width(availWidth / 2);
- }
- });
- return _this.requestImageInfo($('img', wrap), function(width, height) {
- $('.image-info .meta-width', wrap).text(width + "px");
- $('.image-info .meta-height', wrap).text(height + "px");
- return $('.image-info', wrap).removeClass('hide');
- });
- };
- })(this));
- },
- 'swipe': function() {
- var maxHeight, maxWidth;
- maxWidth = 0;
- maxHeight = 0;
- return $('.swipe.view', this.file).each((function(_this) {
- return function(index, view) {
- var $swipeWrap, $swipeBar, $swipeFrame, wrapPadding, ref;
- ref = _this.prepareFrames(view), maxWidth = ref[0], maxHeight = ref[1];
- $swipeFrame = $('.swipe-frame', view);
- $swipeWrap = $('.swipe-wrap', view);
- $swipeBar = $('.swipe-bar', view);
-
- $swipeFrame.css({
- width: maxWidth + 16,
- height: maxHeight + 28
- });
- $swipeWrap.css({
- width: maxWidth + 1,
- height: maxHeight + 2
- });
- // Set swipeBar left position to match image frame
- $swipeBar.css({
- left: 1
- });
-
- wrapPadding = parseInt($swipeWrap.css('right').replace('px', ''), 10);
-
- _this.initDraggable($swipeBar, wrapPadding, function(e, left) {
- if (left > 0 && left < $swipeFrame.width() - (wrapPadding * 2)) {
- $swipeWrap.width((maxWidth + 1) - left);
- $swipeBar.css('left', left);
- }
- });
- };
- })(this));
- },
- 'onion-skin': function() {
- var dragTrackWidth, maxHeight, maxWidth;
- maxWidth = 0;
- maxHeight = 0;
- dragTrackWidth = $('.drag-track', this.file).width() - $('.dragger', this.file).width();
- return $('.onion-skin.view', this.file).each((function(_this) {
- return function(index, view) {
- var $frame, $track, $dragger, $frameAdded, framePadding, ref, dragging = false;
- ref = _this.prepareFrames(view), maxWidth = ref[0], maxHeight = ref[1];
- $frame = $('.onion-skin-frame', view);
- $frameAdded = $('.frame.added', view);
- $track = $('.drag-track', view);
- $dragger = $('.dragger', $track);
-
- $frame.css({
- width: maxWidth + 16,
- height: maxHeight + 28
- });
- $('.swipe-wrap', view).css({
- width: maxWidth + 1,
- height: maxHeight + 2
- });
- $dragger.css({
- left: dragTrackWidth
- });
-
- $frameAdded.css('opacity', 1);
- framePadding = parseInt($frameAdded.css('right').replace('px', ''), 10);
-
- _this.initDraggable($dragger, framePadding, function(e, left) {
- var opacity = left / dragTrackWidth;
-
- if (opacity >= 0 && opacity <= 1) {
- $dragger.css('left', left);
- $frameAdded.css('opacity', opacity);
- }
- });
- };
- })(this));
- }
- }
-
requestImageInfo(img, callback) {
const domImg = img.get(0);
if (domImg) {
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
index 49bb6c52180..034f2923b3b 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
@@ -20,6 +20,16 @@ $(() => {
gl.cycleAnalyticsApp = new Vue({
el: '#cycle-analytics',
name: 'CycleAnalytics',
+ components: {
+ banner,
+ 'stage-issue-component': stageComponent,
+ 'stage-plan-component': stagePlanComponent,
+ 'stage-code-component': stageCodeComponent,
+ 'stage-test-component': stageTestComponent,
+ 'stage-review-component': stageReviewComponent,
+ 'stage-staging-component': stageStagingComponent,
+ 'stage-production-component': stageComponent,
+ },
data() {
const cycleAnalyticsEl = document.querySelector('#cycle-analytics');
const cycleAnalyticsService = new CycleAnalyticsService({
@@ -43,16 +53,6 @@ $(() => {
return this.store.currentActiveStage();
},
},
- components: {
- banner,
- 'stage-issue-component': stageComponent,
- 'stage-plan-component': stagePlanComponent,
- 'stage-code-component': stageCodeComponent,
- 'stage-test-component': stageTestComponent,
- 'stage-review-component': stageReviewComponent,
- 'stage-staging-component': stageStagingComponent,
- 'stage-production-component': stageComponent,
- },
created() {
this.fetchCycleAnalyticsData();
},
diff --git a/app/assets/javascripts/deploy_keys/index.js b/app/assets/javascripts/deploy_keys/index.js
index a5f232f950a..ca8798facc9 100644
--- a/app/assets/javascripts/deploy_keys/index.js
+++ b/app/assets/javascripts/deploy_keys/index.js
@@ -3,14 +3,14 @@ import deployKeysApp from './components/app.vue';
document.addEventListener('DOMContentLoaded', () => new Vue({
el: document.getElementById('js-deploy-keys'),
+ components: {
+ deployKeysApp,
+ },
data() {
return {
endpoint: this.$options.el.dataset.endpoint,
};
},
- components: {
- deployKeysApp,
- },
render(createElement) {
return createElement('deploy-keys-app', {
props: {
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index 2f0e397aa45..f647eed6952 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -287,7 +287,8 @@ export default {
if (this.model &&
this.model.last_deployment &&
this.model.last_deployment.deployable) {
- return `${this.model.last_deployment.deployable.name} #${this.model.last_deployment.deployable.id}`;
+ const deployable = this.model.last_deployment.deployable;
+ return `${deployable.name} #${deployable.id}`;
}
return '';
},
diff --git a/app/assets/javascripts/filtered_search/recent_searches_root.js b/app/assets/javascripts/filtered_search/recent_searches_root.js
index 27e49d4fb96..c99ed63c4af 100644
--- a/app/assets/javascripts/filtered_search/recent_searches_root.js
+++ b/app/assets/javascripts/filtered_search/recent_searches_root.js
@@ -32,6 +32,9 @@ class RecentSearchesRoot {
const state = this.store.state;
this.vm = new Vue({
el: this.wrapperElement,
+ components: {
+ 'recent-searches-dropdown-content': RecentSearchesDropdownContent,
+ },
data() { return state; },
template: `
<recent-searches-dropdown-content
@@ -40,9 +43,6 @@ class RecentSearchesRoot {
:allowed-keys="allowedKeys"
/>
`,
- components: {
- 'recent-searches-dropdown-content': RecentSearchesDropdownContent,
- },
});
}
diff --git a/app/assets/javascripts/groups/components/group_folder.vue b/app/assets/javascripts/groups/components/group_folder.vue
index e60221fa08d..1ff984d02e2 100644
--- a/app/assets/javascripts/groups/components/group_folder.vue
+++ b/app/assets/javascripts/groups/components/group_folder.vue
@@ -20,7 +20,11 @@ export default {
return this.parentGroup.childrenCount > MAX_CHILDREN_COUNT;
},
moreChildrenStats() {
- return n__('One more item', '%d more items', this.parentGroup.childrenCount - this.parentGroup.children.length);
+ return n__(
+ 'One more item',
+ '%d more items',
+ this.parentGroup.childrenCount - this.parentGroup.children.length
+ );
},
},
};
diff --git a/app/assets/javascripts/groups/components/item_stats.vue b/app/assets/javascripts/groups/components/item_stats.vue
index 9f8ac138fc3..d9bc0588908 100644
--- a/app/assets/javascripts/groups/components/item_stats.vue
+++ b/app/assets/javascripts/groups/components/item_stats.vue
@@ -1,6 +1,11 @@
<script>
import tooltip from '../../vue_shared/directives/tooltip';
-import { ITEM_TYPE, VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE, PROJECT_VISIBILITY_TYPE } from '../constants';
+import {
+ ITEM_TYPE,
+ VISIBILITY_TYPE_ICON,
+ GROUP_VISIBILITY_TYPE,
+ PROJECT_VISIBILITY_TYPE,
+} from '../constants';
export default {
directives: {
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index 470db2c9650..b1ec82f5209 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -49,7 +49,9 @@ export default {
const createNewBranch = newBranch || this.startNewMR;
const payload = {
- branch: createNewBranch ? `${this.currentBranchId}-${new Date().getTime().toString()}` : this.currentBranchId,
+ branch: createNewBranch ?
+ `${this.currentBranchId}-${new Date().getTime().toString()}` :
+ this.currentBranchId,
commit_message: this.commitMessage,
actions: this.changedFiles.map(f => ({
action: f.tempFile ? 'create' : 'update',
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index a96bd339f51..e7b0794596b 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -18,11 +18,6 @@ function initIde(el) {
components: {
ide,
},
- methods: {
- ...mapActions([
- 'setInitialData',
- ]),
- },
created() {
const data = el.dataset;
@@ -39,6 +34,11 @@ function initIde(el) {
isInitialRoot: convertPermissionToBoolean(data.root),
});
},
+ methods: {
+ ...mapActions([
+ 'setInitialData',
+ ]),
+ },
render(createElement) {
return createElement('ide');
},
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index c3f2bf130bb..317020f25eb 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -88,7 +88,11 @@
if (taskRegexMatches) {
$tasks.text(this.taskStatus);
- $tasksShort.text(`${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ? 's' : ''}`);
+ $tasksShort.text(
+ `${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ?
+ 's' :
+ ''}`
+ );
} else {
$tasks.text('');
$tasksShort.text('');
diff --git a/app/assets/javascripts/jobs/job_details_bundle.js b/app/assets/javascripts/jobs/job_details_bundle.js
index baaf5641200..db53b04de0e 100644
--- a/app/assets/javascripts/jobs/job_details_bundle.js
+++ b/app/assets/javascripts/jobs/job_details_bundle.js
@@ -13,14 +13,14 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line no-new
new Vue({
el: '#js-build-header-vue',
+ components: {
+ jobHeader,
+ },
data() {
return {
mediator,
};
},
- components: {
- jobHeader,
- },
mounted() {
this.mediator.initBuildClass();
},
@@ -38,14 +38,14 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line
new Vue({
el: '#js-details-block-vue',
+ components: {
+ detailsBlock,
+ },
data() {
return {
mediator,
};
},
- components: {
- detailsBlock,
- },
render(createElement) {
return createElement('details-block', {
props: {
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
index 94561d6b7c3..792b7523889 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
@@ -25,12 +25,12 @@ $(() => {
gl.MergeConflictsResolverApp = new Vue({
el: '#conflicts',
- data: mergeConflictsStore.state,
components: {
'diff-file-editor': gl.mergeConflicts.diffFileEditor,
'inline-conflict-lines': gl.mergeConflicts.inlineConflictLines,
'parallel-conflict-lines': gl.mergeConflicts.parallelConflictLines
},
+ data: mergeConflictsStore.state,
computed: {
conflictsCountText() { return mergeConflictsStore.getConflictsCountText(); },
readyToCommit() { return mergeConflictsStore.isReadyToCommit(); },
diff --git a/app/assets/javascripts/monitoring/components/empty_state.vue b/app/assets/javascripts/monitoring/components/empty_state.vue
index a18164482a2..9df7094b6ab 100644
--- a/app/assets/javascripts/monitoring/components/empty_state.vue
+++ b/app/assets/javascripts/monitoring/components/empty_state.vue
@@ -33,13 +33,15 @@
gettingStarted: {
svgUrl: this.emptyGettingStartedSvgPath,
title: 'Get started with performance monitoring',
- description: 'Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments.',
+ description: `Stay updated about the performance and health
+of your environment by configuring Prometheus to monitor your deployments.`,
buttonText: 'Configure Prometheus',
},
loading: {
svgUrl: this.emptyLoadingSvgPath,
title: 'Waiting for performance data',
- description: 'Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available.',
+ description: `Creating graphs uses the data from the Prometheus server.
+If this takes a long time, ensure that data is available.`,
buttonText: 'View documentation',
},
unableToConnect: {
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index e594377bc40..778db2f7132 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -65,7 +65,9 @@
if (this.note.length) {
const actionText = this.isIssueOpen ? 'close' : 'reopen';
- return this.noteType === constants.COMMENT ? `Comment & ${actionText} issue` : `Start discussion & ${actionText} issue`;
+ return this.noteType === constants.COMMENT ?
+ `Comment & ${actionText} issue` :
+ `Start discussion & ${actionText} issue`;
}
return this.isIssueOpen ? 'Close issue' : 'Reopen issue';
@@ -159,7 +161,9 @@
.catch(() => {
this.isSubmitting = false;
this.discard(false);
- const msg = 'Your comment could not be submitted! Please check your network connection and try again.';
+ const msg =
+ `Your comment could not be submitted!
+Please check your network connection and try again.`;
Flash(msg, 'alert', this.$el);
this.note = noteData.data.note.note; // Restore textarea content.
this.removePlaceholderNotes();
@@ -207,7 +211,11 @@
},
initAutoSave() {
if (this.isLoggedIn) {
- this.autosave = new Autosave($(this.$refs.textarea), ['Note', 'Issue', this.getNoteableData.id], 'issue');
+ this.autosave = new Autosave(
+ $(this.$refs.textarea),
+ ['Note', 'Issue', this.getNoteableData.id],
+ 'issue',
+ );
}
},
initTaskList() {
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index 11e8f805635..873c4f1ff96 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -130,7 +130,8 @@
this.removePlaceholderNotes();
this.isReplying = true;
this.$nextTick(() => {
- const msg = 'Your comment could not be submitted! Please check your network connection and try again.';
+ const msg = `Your comment could not be submitted!
+Please check your network connection and try again.`;
Flash(msg, 'alert', this.$el);
this.$refs.noteForm.note = noteText;
callback(err);
diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
index 7006d05e7b2..933d21bf17b 100644
--- a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
@@ -59,7 +59,8 @@
* target the click event of this component.
*/
stopDropdownClickPropagation() {
- $(this.$el.querySelectorAll('.js-grouped-pipeline-dropdown a.mini-pipeline-graph-dropdown-item'))
+ $(this.$el
+ .querySelectorAll('.js-grouped-pipeline-dropdown a.mini-pipeline-graph-dropdown-item'))
.on('click', (e) => {
e.stopPropagation();
});
diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue
index 9da0aac50a1..1e2f45333a5 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue
@@ -30,8 +30,16 @@
html: true,
trigger: 'focus',
placement: 'top',
- title: '<div class="autodevops-title">This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b></div>',
- content: `<a class="autodevops-link" href="${this.autoDevopsHelpPath}" target="_blank" rel="noopener noreferrer nofollow">Learn more about Auto DevOps</a>`,
+ title: `<div class="autodevops-title">
+ This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>
+ </div>`,
+ content: `<a
+ class="autodevops-link"
+ href="${this.autoDevopsHelpPath}"
+ target="_blank"
+ rel="noopener noreferrer nofollow">
+ Learn more about Auto DevOps
+ </a>`,
};
},
},
diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue
index ac9d9c901ca..021f271b267 100644
--- a/app/assets/javascripts/pipelines/components/stage.vue
+++ b/app/assets/javascripts/pipelines/components/stage.vue
@@ -116,7 +116,9 @@ export default {
computed: {
dropdownClass() {
- return this.dropdownContent.length > 0 ? 'js-builds-dropdown-container' : 'js-builds-dropdown-loading';
+ return this.dropdownContent.length > 0 ?
+ 'js-builds-dropdown-container' :
+ 'js-builds-dropdown-loading';
},
triggerButtonClass() {
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 206023d4ddb..d88d280cb3f 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -15,14 +15,14 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line
new Vue({
el: '#js-pipeline-graph-vue',
+ components: {
+ pipelineGraph,
+ },
data() {
return {
mediator,
};
},
- components: {
- pipelineGraph,
- },
render(createElement) {
return createElement('pipeline-graph', {
props: {
@@ -36,14 +36,14 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line
new Vue({
el: '#js-pipeline-header-vue',
+ components: {
+ pipelineHeader,
+ },
data() {
return {
mediator,
};
},
- components: {
- pipelineHeader,
- },
created() {
eventHub.$on('headerPostAction', this.postAction);
},
diff --git a/app/assets/javascripts/pipelines/pipelines_bundle.js b/app/assets/javascripts/pipelines/pipelines_bundle.js
index 3e4b6eeb5bf..ab5596e70f0 100644
--- a/app/assets/javascripts/pipelines/pipelines_bundle.js
+++ b/app/assets/javascripts/pipelines/pipelines_bundle.js
@@ -7,6 +7,9 @@ Vue.use(Translate);
document.addEventListener('DOMContentLoaded', () => new Vue({
el: '#pipelines-list-vue',
+ components: {
+ pipelinesComponent,
+ },
data() {
const store = new PipelinesStore();
@@ -14,9 +17,6 @@ document.addEventListener('DOMContentLoaded', () => new Vue({
store,
};
},
- components: {
- pipelinesComponent,
- },
render(createElement) {
return createElement('pipelines-component', {
props: {
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index 78be6b6e884..67ed7cc0cdf 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -51,7 +51,8 @@
text() {
return sprintf(
s__(`Profiles|
-You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account.
+You are about to permanently delete %{yourAccount}, and all of the issues, merge requests,
+and groups linked to your account.
Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
{
yourAccount: `<strong>${s__('Profiles|your account')}</strong>`,
diff --git a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
index 6ee4d487c0b..80927529ffe 100644
--- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
@@ -39,7 +39,10 @@ export default {
updateConfidentialAttribute(confidential) {
this.service.update('issue', { confidential })
.then(() => location.reload())
- .catch(() => new Flash('Something went wrong trying to change the confidentiality of this issue'));
+ .catch(() => {
+ Flash(`Something went wrong trying to
+change the confidentiality of this issue`);
+ });
},
},
};
diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
index 04c3a96bf74..bded18996eb 100644
--- a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
@@ -54,7 +54,8 @@ export default {
discussion_locked: locked,
})
.then(() => location.reload())
- .catch(() => Flash(this.__(`Something went wrong trying to change the locked state of this ${this.issuableDisplayName}`)));
+ .catch(() => Flash(this.__(`Something went wrong trying to
+change the locked state of this ${this.issuableDisplayName}`)));
},
},
};
diff --git a/doc/development/fe_guide/style_guide_js.md b/doc/development/fe_guide/style_guide_js.md
index 1cd66f27492..3c5d69e1f71 100644
--- a/doc/development/fe_guide/style_guide_js.md
+++ b/doc/development/fe_guide/style_guide_js.md
@@ -101,16 +101,16 @@ followed by any global declarations, then a blank newline prior to any imports o
```
Import statements are following usual naming guidelines, for example object literals use camel case:
-
+
```javascript
// some_object file
export default {
key: 'value',
};
-
+
// bad
import ObjectLiteral from 'some_object';
-
+
// good
import objectLiteral from 'some_object';
```
@@ -255,6 +255,10 @@ A forEach will cause side effects, it will be mutating the array being iterated.
### Vue.js
+#### `eslint-vue-plugin`
+We default to [eslint-vue-plugin][eslint-plugin-vue], with the `plugin:vue/recommended`.
+Please check this [rules][eslint-plugin-vue-rules] for more documentation.
+
#### Basic Rules
1. The service has it's own file
1. The store has it's own file
@@ -513,8 +517,8 @@ On those a default key should not be provided.
1. `props`
1. `mixins`
1. `directives`
- 1. `data`
1. `components`
+ 1. `data`
1. `computedProps`
1. `methods`
1. `beforeCreate`
@@ -582,3 +586,5 @@ The goal of this accord is to make sure we are all on the same page.
[eslintrc]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.eslintrc
[eslint-this]: http://eslint.org/docs/rules/class-methods-use-this
[eslint-new]: http://eslint.org/docs/rules/no-new
+[eslint-plugin-vue]: https://github.com/vuejs/eslint-plugin-vue
+[eslint-plugin-vue-rules]: https://github.com/vuejs/eslint-plugin-vue#bulb-rules
diff --git a/package.json b/package.json
index 8c3932dccfd..f7fa71c2be6 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"dropzone": "^4.2.0",
"emoji-unicode-version": "^0.2.1",
"eslint-plugin-html": "^2.0.1",
+ "eslint-plugin-vue": "^4.0.1",
"exports-loader": "^0.6.4",
"file-loader": "^0.11.1",
"fuzzaldrin-plus": "^0.5.0",
diff --git a/spec/javascripts/boards/issue_card_spec.js b/spec/javascripts/boards/issue_card_spec.js
index 8ef221257be..278155c585e 100644
--- a/spec/javascripts/boards/issue_card_spec.js
+++ b/spec/javascripts/boards/issue_card_spec.js
@@ -45,6 +45,9 @@ describe('Issue card component', () => {
component = new Vue({
el: document.querySelector('.test-container'),
+ components: {
+ 'issue-card': gl.issueBoards.IssueCardInner,
+ },
data() {
return {
list,
@@ -53,9 +56,6 @@ describe('Issue card component', () => {
rootPath: '/',
};
},
- components: {
- 'issue-card': gl.issueBoards.IssueCardInner,
- },
template: `
<issue-card
:issue="issue"
diff --git a/spec/javascripts/vue_shared/components/markdown/field_spec.js b/spec/javascripts/vue_shared/components/markdown/field_spec.js
index 24209be83fe..5f980bbf36c 100644
--- a/spec/javascripts/vue_shared/components/markdown/field_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/field_spec.js
@@ -12,14 +12,14 @@ describe('Markdown field component', () => {
beforeEach((done) => {
vm = new Vue({
+ components: {
+ fieldComponent,
+ },
data() {
return {
text: 'testing\n123',
};
},
- components: {
- fieldComponent,
- },
template: `
<field-component
markdown-preview-path="/preview"
diff --git a/yarn.lock b/yarn.lock
index 381b1a243f8..7e6649db0c7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -97,6 +97,10 @@ acorn@^5.0.0, acorn@^5.0.3, acorn@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75"
+acorn@^5.2.1:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822"
+
after@0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
@@ -2397,6 +2401,24 @@ eslint-plugin-promise@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca"
+eslint-plugin-vue@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-4.0.1.tgz#afda92cfd7e7363b1fbdb1a772dd63359a9ce96a"
+ dependencies:
+ require-all "^2.2.0"
+ vue-eslint-parser "^2.0.1"
+
+eslint-scope@^3.7.1:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
+ dependencies:
+ esrecurse "^4.1.0"
+ estraverse "^4.1.1"
+
+eslint-visitor-keys@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
+
eslint@^3.10.1:
version "3.19.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc"
@@ -2444,6 +2466,13 @@ espree@^3.4.0:
acorn "^5.1.1"
acorn-jsx "^3.0.0"
+espree@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca"
+ dependencies:
+ acorn "^5.2.1"
+ acorn-jsx "^3.0.0"
+
esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1:
version "2.7.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
@@ -5546,6 +5575,10 @@ request@^2.81.0:
tunnel-agent "^0.6.0"
uuid "^3.0.0"
+require-all@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/require-all/-/require-all-2.2.0.tgz#b4420c233ac0282d0ff49b277fb880a8b5de0894"
+
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -6504,6 +6537,17 @@ void-elements@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
+vue-eslint-parser@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.1.tgz#30135771c4fad00fdbac4542a2d59f3b1d776834"
+ dependencies:
+ debug "^3.1.0"
+ eslint-scope "^3.7.1"
+ eslint-visitor-keys "^1.0.0"
+ espree "^3.5.2"
+ esquery "^1.0.0"
+ lodash "^4.17.4"
+
vue-hot-reload-api@^2.2.0:
version "2.2.4"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.2.4.tgz#683bd1d026c0d3b3c937d5875679e9a87ec6cd8f"