summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2018-06-15 09:27:11 +0100
committerPhil Hughes <me@iamphill.com>2018-06-27 10:44:13 +0100
commitf1a01babb19686ef9c152c9bff7b23db4136db22 (patch)
treeeac6d5f159692051574932564c2183e4b62439fe
parentb5f2adf173c37e60943daa80764fb4031ac414d6 (diff)
downloadgitlab-ce-f1a01babb19686ef9c152c9bff7b23db4136db22.tar.gz
make error messages a first class citizen in Web IDE
This is to reduce the dependancy on the flash module which just modifies the DOM, whereas this now correcly uses the vDOM
-rw-r--r--app/assets/javascripts/ide/components/error_message.vue75
-rw-r--r--app/assets/javascripts/ide/components/ide.vue7
-rw-r--r--app/assets/javascripts/ide/stores/actions.js3
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js35
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js2
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js3
-rw-r--r--app/assets/javascripts/ide/stores/state.js1
7 files changed, 107 insertions, 19 deletions
diff --git a/app/assets/javascripts/ide/components/error_message.vue b/app/assets/javascripts/ide/components/error_message.vue
new file mode 100644
index 00000000000..42e57f61361
--- /dev/null
+++ b/app/assets/javascripts/ide/components/error_message.vue
@@ -0,0 +1,75 @@
+<script>
+import { mapActions } from 'vuex';
+import LoadingIcon from '../../vue_shared/components/loading_icon.vue';
+
+export default {
+ components: {
+ LoadingIcon,
+ },
+ props: {
+ message: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isLoading: false,
+ };
+ },
+ methods: {
+ ...mapActions(['setErrorMessage']),
+ clickAction() {
+ if (this.isLoading) return;
+
+ this.isLoading = true;
+
+ this.$store
+ .dispatch(this.message.action, this.message.actionPayload)
+ .then(() => {
+ this.isLoading = false;
+ })
+ .catch(() => {
+ this.isLoading = false;
+ });
+ },
+ clickFlash() {
+ if (!this.message.action) {
+ this.setErrorMessage(null);
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="flash-container flash-container-page"
+ @click="clickFlash"
+ >
+ <div class="flash-alert">
+ <span
+ v-html="message.text"
+ >
+ </span>
+ <a
+ v-if="message.action"
+ href="#"
+ class="flash-action"
+ @click.stop.prevent="clickAction"
+ >
+ {{ message.actionText }}
+ <loading-icon
+ v-show="isLoading"
+ inline
+ />
+ </a>
+ </div>
+ </div>
+</template>
+
+<style scoped>
+.flash-action {
+ color: #fff;
+}
+</style>
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index f5f7f967a92..9f016e0338f 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -7,6 +7,7 @@ import IdeStatusBar from './ide_status_bar.vue';
import RepoEditor from './repo_editor.vue';
import FindFile from './file_finder/index.vue';
import RightPane from './panes/right.vue';
+import ErrorMessage from './error_message.vue';
const originalStopCallback = Mousetrap.stopCallback;
@@ -18,6 +19,7 @@ export default {
RepoEditor,
FindFile,
RightPane,
+ ErrorMessage,
},
computed: {
...mapState([
@@ -28,6 +30,7 @@ export default {
'fileFindVisible',
'emptyStateSvgPath',
'currentProjectId',
+ 'errorMessage',
]),
...mapGetters(['activeFile', 'hasChanges']),
},
@@ -72,6 +75,10 @@ export default {
<template>
<article class="ide">
+ <error-message
+ v-if="errorMessage"
+ :message="errorMessage"
+ />
<div
class="ide-view"
>
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index 3dc365eaead..5e91fa915ff 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -175,6 +175,9 @@ export const setRightPane = ({ commit }, view) => {
export const setLinks = ({ commit }, links) => commit(types.SET_LINKS, links);
+export const setErrorMessage = ({ commit }, errorMessage) =>
+ commit(types.SET_ERROR_MESSAGE, errorMessage);
+
export * from './actions/tree';
export * from './actions/file';
export * from './actions/project';
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index 22942dbeabb..a99ac4fc98c 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -1,3 +1,4 @@
+import _ from 'underscore';
import flash from '~/flash';
import { __, sprintf } from '~/locale';
import service from '../../services';
@@ -89,7 +90,7 @@ export const refreshLastCommitData = ({ commit }, { projectId, branchId } = {})
flash(__('Error loading last commit.'), 'alert', document, null, false, true);
});
-export const createNewBranchFromDefault = ({ state, getters }, branch) => {
+export const createNewBranchFromDefault = ({ state, getters }, branch) =>
api
.createBranch(state.currentProjectId, {
ref: getters.currentProject.default_branch,
@@ -97,27 +98,23 @@ export const createNewBranchFromDefault = ({ state, getters }, branch) => {
})
.then(() => {
location.reload();
+
+ // this forces the loading icon to spin whilst the page is reloading
+ return new Promise(() => {});
})
.catch(() => {});
-};
export const showBranchNotFoundError = ({ dispatch }, branchId) => {
- flash(
- sprintf(__('Branch %{branchName} was not found in project.'), {
- branchName: branchId,
- }),
- 'alert',
- document,
- {
- href: '#',
- title: 'Create branch',
- clickHandler(e) {
- e.stopPropagation();
- e.preventDefault();
- dispatch('createNewBranchFromDefault', branchId);
+ dispatch('setErrorMessage', {
+ text: sprintf(
+ __('Branch %{branchName} was not found in project.'),
+ {
+ branchName: `<strong>${_.escape(branchId)}</strong>`,
},
- },
- false,
- true,
- );
+ false,
+ ),
+ action: 'createNewBranchFromDefault',
+ actionText: 'Create branch',
+ actionPayload: branchId,
+ });
};
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index fda606dbf01..555802e1811 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -72,3 +72,5 @@ export const SET_RIGHT_PANE = 'SET_RIGHT_PANE';
export const CLEAR_PROJECTS = 'CLEAR_PROJECTS';
export const RESET_OPEN_FILES = 'RESET_OPEN_FILES';
+
+export const SET_ERROR_MESSAGE = 'SET_ERROR_MESSAGE';
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 48f1da4eccf..702be2140e2 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -163,6 +163,9 @@ export default {
[types.RESET_OPEN_FILES](state) {
Object.assign(state, { openFiles: [] });
},
+ [types.SET_ERROR_MESSAGE](state, errorMessage) {
+ Object.assign(state, { errorMessage });
+ },
...projectMutations,
...mergeRequestMutation,
...fileMutations,
diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js
index 4aac4696075..be229b2c723 100644
--- a/app/assets/javascripts/ide/stores/state.js
+++ b/app/assets/javascripts/ide/stores/state.js
@@ -25,4 +25,5 @@ export default () => ({
fileFindVisible: false,
rightPane: null,
links: {},
+ errorMessage: null,
});