diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-09 15:09:29 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-09 15:09:29 +0000 |
commit | 209bd8cf1f542f6ba2a069b368a9187faa871e96 (patch) | |
tree | 6b77dc8183135b8316cc70c8dbc9c4e7c18cf05a /app/assets | |
parent | a9ced7da447785c57477b3d8dbccc73a78cface1 (diff) | |
download | gitlab-ce-209bd8cf1f542f6ba2a069b368a9187faa871e96.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
15 files changed, 141 insertions, 29 deletions
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js index 3c00ae98e75..cc9bfa2e174 100644 --- a/app/assets/javascripts/diffs/store/mutations.js +++ b/app/assets/javascripts/diffs/store/mutations.js @@ -326,6 +326,7 @@ export default { }, [types.SET_SHOW_WHITESPACE](state, showWhitespace) { state.showWhitespace = showWhitespace; + state.diffFiles = []; }, [types.TOGGLE_FILE_FINDER_VISIBLE](state, visible) { state.fileFinderVisible = visible; diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js index fdd27e08793..1678991b1ea 100644 --- a/app/assets/javascripts/header.js +++ b/app/assets/javascripts/header.js @@ -5,6 +5,7 @@ import { highCountTrim } from '~/lib/utils/text_utility'; import SetStatusModalTrigger from './set_status_modal/set_status_modal_trigger.vue'; import SetStatusModalWrapper from './set_status_modal/set_status_modal_wrapper.vue'; import { parseBoolean } from '~/lib/utils/common_utils'; +import Tracking from '~/tracking'; /** * Updates todo counter when todos are toggled. @@ -73,6 +74,24 @@ function initStatusTriggers() { } } +export function initNavUserDropdownTracking() { + const el = document.querySelector('.js-nav-user-dropdown'); + const buyEl = document.querySelector('.js-buy-ci-minutes-link'); + + if (el && buyEl) { + const { trackLabel, trackProperty } = buyEl.dataset; + const trackEvent = 'show_buy_ci_minutes'; + + $(el).on('shown.bs.dropdown', () => { + Tracking.event(undefined, trackEvent, { + label: trackLabel, + property: trackProperty, + }); + }); + } +} + document.addEventListener('DOMContentLoaded', () => { requestIdleCallback(initStatusTriggers); + initNavUserDropdownTracking(); }); diff --git a/app/assets/javascripts/helpers/monitor_helper.js b/app/assets/javascripts/helpers/monitor_helper.js index 87b4b14f6bf..94a0d38f05f 100644 --- a/app/assets/javascripts/helpers/monitor_helper.js +++ b/app/assets/javascripts/helpers/monitor_helper.js @@ -1,4 +1,64 @@ /** + * @param {String} queryLabel - Default query label for chart + * @param {Object} metricAttributes - Default metric attribute values (e.g. method, instance) + * @returns {String} The formatted query label + * @example + * singleAttributeLabel('app', {__name__: "up", app: "prometheus"}) -> "app: prometheus" + */ +const singleAttributeLabel = (queryLabel, metricAttributes) => { + if (!queryLabel) return ''; + const relevantAttribute = queryLabel.toLowerCase().replace(' ', '_'); + const value = metricAttributes[relevantAttribute]; + if (!value) return ''; + return `${queryLabel}: ${value}`; +}; + +/** + * @param {String} queryLabel - Default query label for chart + * @param {Object} metricAttributes - Default metric attribute values (e.g. method, instance) + * @returns {String} The formatted query label + * @example + * templatedLabel('__name__', {__name__: "up", app: "prometheus"}) -> "__name__" + */ +const templatedLabel = (queryLabel, metricAttributes) => { + if (!queryLabel) return ''; + // eslint-disable-next-line array-callback-return + Object.entries(metricAttributes).map(([templateVar, label]) => { + const regex = new RegExp(`{{\\s*${templateVar}\\s*}}`, 'g'); + // eslint-disable-next-line no-param-reassign + queryLabel = queryLabel.replace(regex, label); + }); + + return queryLabel; +}; + +/** + * @param {Object} metricAttributes - Default metric attribute values (e.g. method, instance) + * @returns {String} The formatted query label + * @example + * multiMetricLabel('', {__name__: "up", app: "prometheus"}) -> "__name__: up, app: prometheus" + */ +const multiMetricLabel = metricAttributes => { + return Object.entries(metricAttributes) + .map(([templateVar, label]) => `${templateVar}: ${label}`) + .join(', '); +}; + +/** + * @param {String} queryLabel - Default query label for chart + * @param {Object} metricAttributes - Default metric attribute values (e.g. method, instance) + * @returns {String} The formatted query label + */ +const getSeriesLabel = (queryLabel, metricAttributes) => { + return ( + singleAttributeLabel(queryLabel, metricAttributes) || + templatedLabel(queryLabel, metricAttributes) || + multiMetricLabel(metricAttributes) || + queryLabel + ); +}; + +/** * @param {Array} queryResults - Array of Result objects * @param {Object} defaultConfig - Default chart config values (e.g. lineStyle, name) * @returns {Array} The formatted values @@ -12,21 +72,11 @@ export const makeDataSeries = (queryResults, defaultConfig) => if (!data.length) { return null; } - const relevantMetric = defaultConfig.name.toLowerCase().replace(' ', '_'); - const name = result.metric[relevantMetric]; const series = { data }; - if (name) { - series.name = `${defaultConfig.name}: ${name}`; - } else { - series.name = defaultConfig.name; - Object.keys(result.metric).forEach(templateVar => { - const value = result.metric[templateVar]; - const regex = new RegExp(`{{\\s*${templateVar}\\s*}}`, 'g'); - - series.name = series.name.replace(regex, value); - }); - } - - return { ...defaultConfig, ...series }; + return { + ...defaultConfig, + ...series, + name: getSeriesLabel(defaultConfig.name, result.metric), + }; }) .filter(series => series !== null); diff --git a/app/assets/javascripts/monitoring/components/charts/bar.vue b/app/assets/javascripts/monitoring/components/charts/bar.vue index 01fd8940dad..e1018cd5952 100644 --- a/app/assets/javascripts/monitoring/components/charts/bar.vue +++ b/app/assets/javascripts/monitoring/components/charts/bar.vue @@ -58,7 +58,7 @@ export default { }, methods: { formatLegendLabel(query) { - return `${query.label}`; + return query.label; }, onResize() { if (!this.$refs.barChart) return; diff --git a/app/assets/javascripts/monitoring/components/charts/column.vue b/app/assets/javascripts/monitoring/components/charts/column.vue index 0ed801e6e57..7a2e3e1b511 100644 --- a/app/assets/javascripts/monitoring/components/charts/column.vue +++ b/app/assets/javascripts/monitoring/components/charts/column.vue @@ -76,7 +76,7 @@ export default { }, methods: { formatLegendLabel(query) { - return `${query.label}`; + return query.label; }, onResize() { if (!this.$refs.columnChart) return; diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue index e43a0131528..f4cd6bbbb34 100644 --- a/app/assets/javascripts/monitoring/components/charts/time_series.vue +++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue @@ -251,7 +251,7 @@ export default { }, methods: { formatLegendLabel(query) { - return `${query.label}`; + return query.label; }, isTooltipOfType(tooltipType, defaultType) { return tooltipType === defaultType; diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js index 5e620d6c2f5..d01acdd031b 100644 --- a/app/assets/javascripts/monitoring/stores/utils.js +++ b/app/assets/javascripts/monitoring/stores/utils.js @@ -68,12 +68,11 @@ export const parseEnvironmentsResponse = (response = [], projectPath) => * https://gitlab.com/gitlab-org/gitlab/issues/207198 * * @param {Array} metrics - Array of prometheus metrics - * @param {String} defaultLabel - Default label for metrics * @returns {Object} */ -const mapToMetricsViewModel = (metrics, defaultLabel) => +const mapToMetricsViewModel = metrics => metrics.map(({ label, id, metric_id, query_range, prometheus_endpoint_path, ...metric }) => ({ - label: label || defaultLabel, + label, queryRange: query_range, prometheusEndpointPath: prometheus_endpoint_path, metricId: uniqMetricsId({ metric_id, id }), diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js index d74447dd566..b2636f910fe 100644 --- a/app/assets/javascripts/repository/router.js +++ b/app/assets/javascripts/repository/router.js @@ -12,7 +12,7 @@ export default function createRouter(base, baseRef) { base: joinPaths(gon.relative_url_root || '', base), routes: [ { - path: `(/-)?/tree/(${encodeURIComponent(baseRef)}|${baseRef})/:path*`, + path: `(/-)?/tree/(${encodeURIComponent(baseRef).replace(/%2F/g, '/')}|${baseRef})/:path*`, name: 'treePath', component: TreePage, props: route => ({ diff --git a/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue b/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue new file mode 100644 index 00000000000..83b50b2f8eb --- /dev/null +++ b/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue @@ -0,0 +1,23 @@ +<script> +import { GlNewButton } from '@gitlab/ui'; + +export default { + components: { + GlNewButton, + }, + props: { + saveable: { + type: Boolean, + required: false, + default: false, + }, + }, +}; +</script> +<template> + <div class="d-flex bg-light border-top justify-content-between align-items-center py-3 px-4"> + <gl-new-button variant="success" :disabled="!saveable"> + {{ __('Submit Changes') }} + </gl-new-button> + </div> +</template> diff --git a/app/assets/javascripts/static_site_editor/components/static_site_editor.vue b/app/assets/javascripts/static_site_editor/components/static_site_editor.vue index f06d48ee4f5..80a55d5ee11 100644 --- a/app/assets/javascripts/static_site_editor/components/static_site_editor.vue +++ b/app/assets/javascripts/static_site_editor/components/static_site_editor.vue @@ -3,27 +3,29 @@ import { mapState, mapGetters, mapActions } from 'vuex'; import { GlSkeletonLoader } from '@gitlab/ui'; import EditArea from './edit_area.vue'; +import Toolbar from './publish_toolbar.vue'; export default { components: { EditArea, GlSkeletonLoader, + Toolbar, }, computed: { ...mapState(['content', 'isLoadingContent']), - ...mapGetters(['isContentLoaded']), + ...mapGetters(['isContentLoaded', 'contentChanged']), }, mounted() { this.loadContent(); }, methods: { - ...mapActions(['loadContent']), + ...mapActions(['loadContent', 'setContent']), }, }; </script> <template> - <div class="d-flex justify-content-center h-100"> - <div v-if="isLoadingContent" class="w-50 h-50 mt-2"> + <div class="d-flex justify-content-center h-100 pt-2"> + <div v-if="isLoadingContent" class="w-50 h-50"> <gl-skeleton-loader :width="500" :height="102"> <rect width="500" height="16" rx="4" /> <rect y="20" width="375" height="16" rx="4" /> @@ -33,6 +35,13 @@ export default { <rect x="410" y="40" width="90" height="16" rx="4" /> </gl-skeleton-loader> </div> - <edit-area v-if="isContentLoaded" class="w-75 h-100 shadow-none" :value="content" /> + <div v-if="isContentLoaded" class="d-flex flex-grow-1 flex-column"> + <edit-area + class="w-75 h-100 shadow-none align-self-center" + :value="content" + @input="setContent" + /> + <toolbar :saveable="contentChanged" /> + </div> </div> </template> diff --git a/app/assets/javascripts/static_site_editor/store/actions.js b/app/assets/javascripts/static_site_editor/store/actions.js index 192345f3749..141148de1e0 100644 --- a/app/assets/javascripts/static_site_editor/store/actions.js +++ b/app/assets/javascripts/static_site_editor/store/actions.js @@ -15,4 +15,8 @@ export const loadContent = ({ commit, state: { sourcePath, projectId } }) => { }); }; +export const setContent = ({ commit }, content) => { + commit(mutationTypes.SET_CONTENT, content); +}; + export default () => {}; diff --git a/app/assets/javascripts/static_site_editor/store/getters.js b/app/assets/javascripts/static_site_editor/store/getters.js index 8baa2941594..41256201c26 100644 --- a/app/assets/javascripts/static_site_editor/store/getters.js +++ b/app/assets/javascripts/static_site_editor/store/getters.js @@ -1,2 +1,2 @@ -// eslint-disable-next-line import/prefer-default-export -export const isContentLoaded = ({ content }) => Boolean(content); +export const isContentLoaded = ({ originalContent }) => Boolean(originalContent); +export const contentChanged = ({ originalContent, content }) => originalContent !== content; diff --git a/app/assets/javascripts/static_site_editor/store/mutation_types.js b/app/assets/javascripts/static_site_editor/store/mutation_types.js index cbe51180541..2bb201f5d24 100644 --- a/app/assets/javascripts/static_site_editor/store/mutation_types.js +++ b/app/assets/javascripts/static_site_editor/store/mutation_types.js @@ -1,3 +1,4 @@ export const LOAD_CONTENT = 'loadContent'; export const RECEIVE_CONTENT_SUCCESS = 'receiveContentSuccess'; export const RECEIVE_CONTENT_ERROR = 'receiveContentError'; +export const SET_CONTENT = 'setContent'; diff --git a/app/assets/javascripts/static_site_editor/store/mutations.js b/app/assets/javascripts/static_site_editor/store/mutations.js index 88cb74d2b11..8b8bacf35c2 100644 --- a/app/assets/javascripts/static_site_editor/store/mutations.js +++ b/app/assets/javascripts/static_site_editor/store/mutations.js @@ -8,8 +8,12 @@ export default { state.isLoadingContent = false; state.title = title; state.content = content; + state.originalContent = content; }, [types.RECEIVE_CONTENT_ERROR](state) { state.isLoadingContent = false; }, + [types.SET_CONTENT](state, content) { + state.content = content; + }, }; diff --git a/app/assets/javascripts/static_site_editor/store/state.js b/app/assets/javascripts/static_site_editor/store/state.js index b68e73f06f5..1ae11b3343d 100644 --- a/app/assets/javascripts/static_site_editor/store/state.js +++ b/app/assets/javascripts/static_site_editor/store/state.js @@ -3,7 +3,9 @@ const createState = (initialState = {}) => ({ sourcePath: null, isLoadingContent: false, + isSavingChanges: false, + originalContent: '', content: '', title: '', |