diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-14 21:07:45 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-14 21:07:45 +0000 |
commit | 0b12a5312c9701fbfed25fbb334d47900ced736b (patch) | |
tree | a29a27e297134f573fd8e5c298d241f3156c207a /app | |
parent | 92f95ccac81911d1fcc32e999a7f1ce04624a56c (diff) | |
download | gitlab-ce-0b12a5312c9701fbfed25fbb334d47900ced736b.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
19 files changed, 470 insertions, 84 deletions
diff --git a/app/assets/javascripts/deploy_keys/components/key.vue b/app/assets/javascripts/deploy_keys/components/key.vue index 74f1373f144..c856e380c41 100644 --- a/app/assets/javascripts/deploy_keys/components/key.vue +++ b/app/assets/javascripts/deploy_keys/components/key.vue @@ -115,12 +115,10 @@ export default { <div role="rowheader" class="table-mobile-header">{{ s__('DeployKeys|Deploy key') }}</div> <div class="table-mobile-content qa-key"> <strong class="title qa-key-title"> {{ deployKey.title }} </strong> - <div class="fingerprint qa-key-fingerprint"> + <div class="fingerprint" data-qa-selector="key_md5_fingerprint"> {{ __('MD5') }}:{{ deployKey.fingerprint }} </div> - <div class="fingerprint qa-key-fingerprint"> - {{ __('SHA256') }}:{{ deployKey.fingerprint_sha256 }} - </div> + <div class="fingerprint">{{ __('SHA256') }}:{{ deployKey.fingerprint_sha256 }}</div> </div> </div> <div class="table-section section-30 section-wrap"> diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index c6d32ffef34..23b8458aa6b 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -95,6 +95,7 @@ export default { return { treeWidth, + diffFilesLength: 0, }; }, computed: { @@ -241,7 +242,8 @@ export default { fetchData(toggleTree = true) { if (this.glFeatures.diffsBatchLoad) { this.fetchDiffFilesMeta() - .then(() => { + .then(({ real_size }) => { + this.diffFilesLength = parseInt(real_size, 10); if (toggleTree) this.hideTreeListIfJustOneFile(); this.startDiffRendering(); @@ -264,7 +266,8 @@ export default { }); } else { this.fetchDiffFiles() - .then(() => { + .then(({ real_size }) => { + this.diffFilesLength = parseInt(real_size, 10); if (toggleTree) { this.hideTreeListIfJustOneFile(); } @@ -351,6 +354,7 @@ export default { :merge-request-diff="mergeRequestDiff" :target-branch="targetBranch" :is-limited-container="isLimitedContainer" + :diff-files-length="diffFilesLength" /> <hidden-files-warning diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue index 2e57a47f2f7..24542126b07 100644 --- a/app/assets/javascripts/diffs/components/compare_versions.vue +++ b/app/assets/javascripts/diffs/components/compare_versions.vue @@ -42,9 +42,13 @@ export default { required: false, default: false, }, + diffFilesLength: { + type: Number, + required: true, + }, }, computed: { - ...mapGetters('diffs', ['hasCollapsedFile', 'diffFilesLength']), + ...mapGetters('diffs', ['hasCollapsedFile']), ...mapState('diffs', [ 'commit', 'showTreeList', diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js index 6714f4e62b8..b920e041135 100644 --- a/app/assets/javascripts/diffs/store/actions.js +++ b/app/assets/javascripts/diffs/store/actions.js @@ -64,6 +64,7 @@ export const fetchDiffFiles = ({ state, commit }) => { const urlParams = { w: state.showWhitespace ? '0' : '1', }; + let returnData; if (state.useSingleDiffStyle) { urlParams.view = state.diffViewType; @@ -87,9 +88,13 @@ export const fetchDiffFiles = ({ state, commit }) => { worker.postMessage(state.diffFiles); + returnData = res.data; return Vue.nextTick(); }) - .then(handleLocationHash) + .then(() => { + handleLocationHash(); + return returnData; + }) .catch(() => worker.terminate()); }; @@ -147,6 +152,7 @@ export const fetchDiffFilesMeta = ({ commit, state }) => { prepareDiffData(data); worker.postMessage(data.diff_files); + return data; }) .catch(() => worker.terminate()); }; diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js index bc27e263bff..c4737090a70 100644 --- a/app/assets/javascripts/diffs/store/getters.js +++ b/app/assets/javascripts/diffs/store/getters.js @@ -95,8 +95,6 @@ export const allBlobs = (state, getters) => return acc; }, []); -export const diffFilesLength = state => state.diffFiles.length; - export const getCommentFormForDiffFile = state => fileHash => state.commentForms.find(form => form.fileHash === fileHash); diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js index 8cfdded1f9b..1505be1a0b2 100644 --- a/app/assets/javascripts/diffs/store/mutations.js +++ b/app/assets/javascripts/diffs/store/mutations.js @@ -179,16 +179,19 @@ export default { const mapDiscussions = (line, extraCheck = () => true) => ({ ...line, discussions: extraCheck() - ? line.discussions + ? line.discussions && + line.discussions .filter(() => !line.discussions.some(({ id }) => discussion.id === id)) .concat(lineCheck(line) ? discussion : line.discussions) : [], }); const setDiscussionsExpanded = line => { - const isLineNoteTargeted = line.discussions.some( - disc => disc.notes && disc.notes.find(note => hash === `note_${note.id}`), - ); + const isLineNoteTargeted = + line.discussions && + line.discussions.some( + disc => disc.notes && disc.notes.find(note => hash === `note_${note.id}`), + ); return { ...line, diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue index ecafb4e81c4..bf3d736ddf3 100644 --- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue +++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue @@ -67,8 +67,8 @@ export default { if (this.entryModal.type === modalTypes.rename) { if (this.entries[this.entryName] && !this.entries[this.entryName].deleted) { flash( - sprintf(s__('The name %{entryName} is already taken in this directory.'), { - entryName: this.entryName, + sprintf(s__('The name "%{name}" is already taken in this directory.'), { + name: this.entryName, }), 'alert', document, @@ -81,22 +81,11 @@ export default { const entryName = parentPath.pop(); parentPath = parentPath.join('/'); - const createPromise = - parentPath && !this.entries[parentPath] - ? this.createTempEntry({ name: parentPath, type: 'tree' }) - : Promise.resolve(); - - createPromise - .then(() => - this.renameEntry({ - path: this.entryModal.entry.path, - name: entryName, - parentPath, - }), - ) - .catch(() => - flash(__('Error creating a new path'), 'alert', document, null, false, true), - ); + this.renameEntry({ + path: this.entryModal.entry.path, + name: entryName, + parentPath, + }); } } else { this.createTempEntry({ diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js index 7ffb430296b..3445ef7a75f 100644 --- a/app/assets/javascripts/ide/stores/actions.js +++ b/app/assets/javascripts/ide/stores/actions.js @@ -53,60 +53,55 @@ export const setResizingStatus = ({ commit }, resizing) => { export const createTempEntry = ( { state, commit, dispatch }, { name, type, content = '', base64 = false, binary = false, rawPath = '' }, -) => - new Promise(resolve => { - const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name; - - if (state.entries[name] && !state.entries[name].deleted) { - flash( - `The name "${name.split('/').pop()}" is already taken in this directory.`, - 'alert', - document, - null, - false, - true, - ); - - resolve(); - - return null; - } - - const data = decorateFiles({ - data: [fullName], - projectId: state.currentProjectId, - branchId: state.currentBranchId, - type, - tempFile: true, - content, - base64, - binary, - rawPath, - }); - const { file, parentPath } = data; +) => { + const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name; + + if (state.entries[name] && !state.entries[name].deleted) { + flash( + sprintf(__('The name "%{name}" is already taken in this directory.'), { + name: name.split('/').pop(), + }), + 'alert', + document, + null, + false, + true, + ); - commit(types.CREATE_TMP_ENTRY, { - data, - projectId: state.currentProjectId, - branchId: state.currentBranchId, - }); + return; + } - if (type === 'blob') { - commit(types.TOGGLE_FILE_OPEN, file.path); - commit(types.ADD_FILE_TO_CHANGED, file.path); - dispatch('setFileActive', file.path); - dispatch('triggerFilesChange'); - dispatch('burstUnusedSeal'); - } + const data = decorateFiles({ + data: [fullName], + projectId: state.currentProjectId, + branchId: state.currentBranchId, + type, + tempFile: true, + content, + base64, + binary, + rawPath, + }); + const { file, parentPath } = data; - if (parentPath && !state.entries[parentPath].opened) { - commit(types.TOGGLE_TREE_OPEN, parentPath); - } + commit(types.CREATE_TMP_ENTRY, { + data, + projectId: state.currentProjectId, + branchId: state.currentBranchId, + }); - resolve(file); + if (type === 'blob') { + commit(types.TOGGLE_FILE_OPEN, file.path); + commit(types.ADD_FILE_TO_CHANGED, file.path); + dispatch('setFileActive', file.path); + dispatch('triggerFilesChange'); + dispatch('burstUnusedSeal'); + } - return null; - }); + if (parentPath && !state.entries[parentPath].opened) { + commit(types.TOGGLE_TREE_OPEN, parentPath); + } +}; export const scrollToTab = () => { Vue.nextTick(() => { @@ -211,8 +206,9 @@ export const deleteEntry = ({ commit, dispatch, state }, path) => { const entry = state.entries[path]; const { prevPath, prevName, prevParentPath } = entry; const isTree = entry.type === 'tree'; + const prevEntry = prevPath && state.entries[prevPath]; - if (prevPath) { + if (prevPath && (!prevEntry || prevEntry.deleted)) { dispatch('renameEntry', { path, name: prevName, @@ -245,6 +241,11 @@ export const resetOpenFiles = ({ commit }) => commit(types.RESET_OPEN_FILES); export const renameEntry = ({ dispatch, commit, state }, { path, name, parentPath }) => { const entry = state.entries[path]; const newPath = parentPath ? `${parentPath}/${name}` : name; + const existingParent = parentPath && state.entries[parentPath]; + + if (parentPath && (!existingParent || existingParent.deleted)) { + dispatch('createTempEntry', { name: parentPath, type: 'tree' }); + } commit(types.RENAME_ENTRY, { path, name, parentPath }); diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js index 52bf9becd0f..e206f9bee9e 100644 --- a/app/assets/javascripts/ide/stores/actions/project.js +++ b/app/assets/javascripts/ide/stores/actions/project.js @@ -83,8 +83,11 @@ export const showBranchNotFoundError = ({ dispatch }, branchId) => { }); }; -export const showEmptyState = ({ commit, state }, { projectId, branchId }) => { +export const showEmptyState = ({ commit, state, dispatch }, { projectId, branchId }) => { const treePath = `${projectId}/${branchId}`; + + dispatch('setCurrentBranchId', branchId); + commit(types.CREATE_TREE, { treePath }); commit(types.TOGGLE_LOADING, { entry: state.trees[treePath], diff --git a/app/assets/javascripts/pages/admin/application_settings/index.js b/app/assets/javascripts/pages/admin/application_settings/index.js index 47bd70537f1..089dedd14cb 100644 --- a/app/assets/javascripts/pages/admin/application_settings/index.js +++ b/app/assets/javascripts/pages/admin/application_settings/index.js @@ -1,7 +1,11 @@ import initSettingsPanels from '~/settings_panels'; import projectSelect from '~/project_select'; +import selfMonitor from '~/self_monitor'; document.addEventListener('DOMContentLoaded', () => { + if (gon.features && gon.features.selfMonitoringProject) { + selfMonitor(); + } // Initialize expandable settings panels initSettingsPanels(); projectSelect(); diff --git a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue new file mode 100644 index 00000000000..2f364eae67f --- /dev/null +++ b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue @@ -0,0 +1,160 @@ +<script> +import Vue from 'vue'; +import { GlFormGroup, GlButton, GlModal, GlToast, GlToggle } from '@gitlab/ui'; +import { mapState, mapActions } from 'vuex'; +import { __, s__, sprintf } from '~/locale'; +import { visitUrl, getBaseURL } from '~/lib/utils/url_utility'; + +Vue.use(GlToast); + +export default { + components: { + GlFormGroup, + GlButton, + GlModal, + GlToggle, + }, + formLabels: { + createProject: __('Create Project'), + }, + data() { + return { + modalId: 'delete-self-monitor-modal', + }; + }, + computed: { + ...mapState('selfMonitoring', [ + 'projectEnabled', + 'projectCreated', + 'showAlert', + 'projectPath', + 'loading', + 'alertContent', + ]), + selfMonitorEnabled: { + get() { + return this.projectEnabled; + }, + set(projectEnabled) { + this.setSelfMonitor(projectEnabled); + }, + }, + selfMonitorProjectFullUrl() { + return `${getBaseURL()}/${this.projectPath}`; + }, + selfMonitoringFormText() { + if (this.projectCreated) { + return sprintf( + s__( + 'SelfMonitoring|Enabling this feature creates a %{projectLinkStart}project%{projectLinkEnd} that can be used to monitor the health of your instance.', + ), + { + projectLinkStart: `<a href="${this.selfMonitorProjectFullUrl}">`, + projectLinkEnd: '</a>', + }, + false, + ); + } + + return s__( + 'SelfMonitoring|Enabling this feature creates a project that can be used to monitor the health of your instance.', + ); + }, + }, + watch: { + selfMonitorEnabled() { + this.saveChangesSelfMonitorProject(); + }, + showAlert() { + let toastOptions = { + onComplete: () => { + this.resetAlert(); + }, + }; + + if (this.showAlert) { + if (this.alertContent.actionName && this.alertContent.actionName.length > 0) { + toastOptions = { + ...toastOptions, + action: { + text: this.alertContent.actionText, + onClick: (_, toastObject) => { + this[this.alertContent.actionName](); + toastObject.goAway(0); + }, + }, + }; + } + this.$toast.show(this.alertContent.message, toastOptions); + } + }, + }, + methods: { + ...mapActions('selfMonitoring', [ + 'setSelfMonitor', + 'createProject', + 'deleteProject', + 'resetAlert', + ]), + hideSelfMonitorModal() { + this.$root.$emit('bv::hide::modal', this.modalId); + this.setSelfMonitor(true); + }, + showSelfMonitorModal() { + this.$root.$emit('bv::show::modal', this.modalId); + }, + saveChangesSelfMonitorProject() { + if (this.projectCreated && !this.projectEnabled) { + this.showSelfMonitorModal(); + } else { + this.createProject(); + } + }, + viewSelfMonitorProject() { + visitUrl(this.selfMonitorProjectFullUrl); + }, + }, +}; +</script> +<template> + <section class="settings no-animate js-self-monitoring-settings"> + <div class="settings-header"> + <h4 class="js-section-header"> + {{ s__('SelfMonitoring|Self monitoring') }} + </h4> + <gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button> + <p class="js-section-sub-header"> + {{ s__('SelfMonitoring|Enable or disable instance self monitoring') }} + </p> + </div> + <div class="settings-content"> + <form name="self-monitoring-form"> + <p v-html="selfMonitoringFormText"></p> + <gl-form-group :label="$options.formLabels.createProject" label-for="self-monitor-toggle"> + <gl-toggle + v-model="selfMonitorEnabled" + :is-loading="loading" + name="self-monitor-toggle" + /> + </gl-form-group> + </form> + </div> + <gl-modal + :title="s__('SelfMonitoring|Disable self monitoring?')" + :modal-id="modalId" + :ok-title="__('Delete project')" + :cancel-title="__('Cancel')" + ok-variant="danger" + @ok="deleteProject" + @cancel="hideSelfMonitorModal" + > + <div> + {{ + s__( + 'SelfMonitoring|Disabling this feature will delete the self monitoring project. Are you sure you want to delete the project?', + ) + }} + </div> + </gl-modal> + </section> +</template> diff --git a/app/assets/javascripts/self_monitor/index.js b/app/assets/javascripts/self_monitor/index.js new file mode 100644 index 00000000000..42c94e11989 --- /dev/null +++ b/app/assets/javascripts/self_monitor/index.js @@ -0,0 +1,23 @@ +import Vue from 'vue'; +import store from './store'; +import SelfMonitorForm from './components/self_monitor_form.vue'; + +export default () => { + const el = document.querySelector('.js-self-monitoring-settings'); + let selfMonitorProjectCreated; + + if (el) { + selfMonitorProjectCreated = el.dataset.selfMonitoringProjectExists; + // eslint-disable-next-line no-new + new Vue({ + el, + store: store({ + projectEnabled: selfMonitorProjectCreated, + ...el.dataset, + }), + render(createElement) { + return createElement(SelfMonitorForm); + }, + }); + } +}; diff --git a/app/assets/javascripts/self_monitor/store/actions.js b/app/assets/javascripts/self_monitor/store/actions.js new file mode 100644 index 00000000000..f8430a9b136 --- /dev/null +++ b/app/assets/javascripts/self_monitor/store/actions.js @@ -0,0 +1,126 @@ +import { __, s__ } from '~/locale'; +import axios from '~/lib/utils/axios_utils'; +import statusCodes from '~/lib/utils/http_status'; +import { backOff } from '~/lib/utils/common_utils'; +import * as types from './mutation_types'; + +const TWO_MINUTES = 120000; + +function backOffRequest(makeRequestCallback) { + return backOff((next, stop) => { + makeRequestCallback() + .then(resp => { + if (resp.status === statusCodes.ACCEPTED) { + next(); + } else { + stop(resp); + } + }) + .catch(stop); + }, TWO_MINUTES); +} + +export const setSelfMonitor = ({ commit }, enabled) => commit(types.SET_ENABLED, enabled); + +export const createProject = ({ dispatch }) => dispatch('requestCreateProject'); + +export const resetAlert = ({ commit }) => commit(types.SET_SHOW_ALERT, false); + +export const requestCreateProject = ({ dispatch, state, commit }) => { + commit(types.SET_LOADING, true); + axios + .post(state.createProjectEndpoint) + .then(resp => { + if (resp.status === statusCodes.ACCEPTED) { + dispatch('requestCreateProjectStatus', resp.data.job_id); + } + }) + .catch(error => { + dispatch('requestCreateProjectError', error); + }); +}; + +export const requestCreateProjectStatus = ({ dispatch, state }, jobId) => { + backOffRequest(() => axios.get(state.createProjectStatusEndpoint, { params: { job_id: jobId } })) + .then(resp => { + if (resp.status === statusCodes.OK) { + dispatch('requestCreateProjectSuccess', resp.data); + } + }) + .catch(error => { + dispatch('requestCreateProjectError', error); + }); +}; + +export const requestCreateProjectSuccess = ({ commit }, selfMonitorData) => { + commit(types.SET_LOADING, false); + commit(types.SET_PROJECT_URL, selfMonitorData.project_full_path); + commit(types.SET_ALERT_CONTENT, { + message: s__('SelfMonitoring|Self monitoring project has been successfully created.'), + actionText: __('View project'), + actionName: 'viewSelfMonitorProject', + }); + commit(types.SET_SHOW_ALERT, true); + commit(types.SET_PROJECT_CREATED, true); +}; + +export const requestCreateProjectError = ({ commit }, error) => { + const { response } = error; + const message = response.data && response.data.message ? response.data.message : ''; + + commit(types.SET_ALERT_CONTENT, { + message: `${__('There was an error saving your changes.')} ${message}`, + }); + commit(types.SET_SHOW_ALERT, true); + commit(types.SET_LOADING, false); +}; + +export const deleteProject = ({ dispatch }) => dispatch('requestDeleteProject'); + +export const requestDeleteProject = ({ dispatch, state, commit }) => { + commit(types.SET_LOADING, true); + axios + .delete(state.deleteProjectEndpoint) + .then(resp => { + if (resp.status === statusCodes.ACCEPTED) { + dispatch('requestDeleteProjectStatus', resp.data.job_id); + } + }) + .catch(error => { + dispatch('requestDeleteProjectError', error); + }); +}; + +export const requestDeleteProjectStatus = ({ dispatch, state }, jobId) => { + backOffRequest(() => axios.get(state.deleteProjectStatusEndpoint, { params: { job_id: jobId } })) + .then(resp => { + if (resp.status === statusCodes.OK) { + dispatch('requestDeleteProjectSuccess', resp.data); + } + }) + .catch(error => { + dispatch('requestDeleteProjectError', error); + }); +}; + +export const requestDeleteProjectSuccess = ({ commit }) => { + commit(types.SET_PROJECT_URL, ''); + commit(types.SET_PROJECT_CREATED, false); + commit(types.SET_ALERT_CONTENT, { + message: s__('SelfMonitoring|Self monitoring project has been successfully deleted.'), + actionText: __('Undo'), + actionName: 'createProject', + }); + commit(types.SET_SHOW_ALERT, true); + commit(types.SET_LOADING, false); +}; + +export const requestDeleteProjectError = ({ commit }, error) => { + const { response } = error; + const message = response.data && response.data.message ? response.data.message : ''; + + commit(types.SET_ALERT_CONTENT, { + message: `${__('There was an error saving your changes.')} ${message}`, + }); + commit(types.SET_LOADING, false); +}; diff --git a/app/assets/javascripts/self_monitor/store/index.js b/app/assets/javascripts/self_monitor/store/index.js new file mode 100644 index 00000000000..a222e9c87b8 --- /dev/null +++ b/app/assets/javascripts/self_monitor/store/index.js @@ -0,0 +1,21 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import createState from './state'; +import * as actions from './actions'; +import mutations from './mutations'; + +Vue.use(Vuex); + +export const createStore = initialState => + new Vuex.Store({ + modules: { + selfMonitoring: { + namespaced: true, + state: createState(initialState), + actions, + mutations, + }, + }, + }); + +export default createStore; diff --git a/app/assets/javascripts/self_monitor/store/mutation_types.js b/app/assets/javascripts/self_monitor/store/mutation_types.js new file mode 100644 index 00000000000..c5952b66144 --- /dev/null +++ b/app/assets/javascripts/self_monitor/store/mutation_types.js @@ -0,0 +1,6 @@ +export const SET_ENABLED = 'SET_ENABLED'; +export const SET_PROJECT_CREATED = 'SET_PROJECT_CREATED'; +export const SET_SHOW_ALERT = 'SET_SHOW_ALERT'; +export const SET_PROJECT_URL = 'SET_PROJECT_URL'; +export const SET_LOADING = 'SET_LOADING'; +export const SET_ALERT_CONTENT = 'SET_ALERT_CONTENT'; diff --git a/app/assets/javascripts/self_monitor/store/mutations.js b/app/assets/javascripts/self_monitor/store/mutations.js new file mode 100644 index 00000000000..7dca8bcdc4d --- /dev/null +++ b/app/assets/javascripts/self_monitor/store/mutations.js @@ -0,0 +1,22 @@ +import * as types from './mutation_types'; + +export default { + [types.SET_ENABLED](state, enabled) { + state.projectEnabled = enabled; + }, + [types.SET_PROJECT_CREATED](state, created) { + state.projectCreated = created; + }, + [types.SET_SHOW_ALERT](state, show) { + state.showAlert = show; + }, + [types.SET_PROJECT_URL](state, url) { + state.projectPath = url; + }, + [types.SET_LOADING](state, loading) { + state.loading = loading; + }, + [types.SET_ALERT_CONTENT](state, content) { + state.alertContent = content; + }, +}; diff --git a/app/assets/javascripts/self_monitor/store/state.js b/app/assets/javascripts/self_monitor/store/state.js new file mode 100644 index 00000000000..b8b4a4af614 --- /dev/null +++ b/app/assets/javascripts/self_monitor/store/state.js @@ -0,0 +1,15 @@ +import { parseBoolean } from '~/lib/utils/common_utils'; + +export default (initialState = {}) => ({ + projectEnabled: parseBoolean(initialState.projectEnabled) || false, + projectCreated: parseBoolean(initialState.selfMonitorProjectCreated) || false, + createProjectEndpoint: initialState.createSelfMonitoringProjectPath || '', + deleteProjectEndpoint: initialState.deleteSelfMonitoringProjectPath || '', + createProjectStatusEndpoint: initialState.statusCreateSelfMonitoringProjectPath || '', + deleteProjectStatusEndpoint: initialState.statusDeleteSelfMonitoringProjectPath || '', + selfMonitorProjectPath: initialState.selfMonitoringProjectFullPath || '', + showAlert: false, + projectPath: '', + loading: false, + alertContent: {}, +}); diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb index 657e5accdab..719de095faf 100644 --- a/app/helpers/markup_helper.rb +++ b/app/helpers/markup_helper.rb @@ -281,7 +281,7 @@ module MarkupHelper context.reverse_merge!( current_user: (current_user if defined?(current_user)), - # RelativeLinkFilter + # RepositoryLinkFilter and UploadLinkFilter commit: @commit, project_wiki: @project_wiki, ref: @ref, diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml index 55a48da8342..ff40d7da892 100644 --- a/app/views/admin/application_settings/metrics_and_profiling.html.haml +++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml @@ -47,6 +47,9 @@ .settings-content = render 'performance_bar' +- if Feature.enabled?(:self_monitoring_project) + .js-self-monitoring-settings{ data: self_monitoring_project_data } + %section.settings.as-usage.no-animate#js-usage-settings{ class: ('expanded' if expanded_by_default?) } .settings-header#usage-statistics %h4 |