diff options
author | Phil Hughes <me@iamphill.com> | 2018-06-15 09:27:11 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2018-06-27 10:44:13 +0100 |
commit | f1a01babb19686ef9c152c9bff7b23db4136db22 (patch) | |
tree | eac6d5f159692051574932564c2183e4b62439fe | |
parent | b5f2adf173c37e60943daa80764fb4031ac414d6 (diff) | |
download | gitlab-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.vue | 75 | ||||
-rw-r--r-- | app/assets/javascripts/ide/components/ide.vue | 7 | ||||
-rw-r--r-- | app/assets/javascripts/ide/stores/actions.js | 3 | ||||
-rw-r--r-- | app/assets/javascripts/ide/stores/actions/project.js | 35 | ||||
-rw-r--r-- | app/assets/javascripts/ide/stores/mutation_types.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/ide/stores/mutations.js | 3 | ||||
-rw-r--r-- | app/assets/javascripts/ide/stores/state.js | 1 |
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, }); |