summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-15 00:08:06 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-15 00:08:06 +0000
commitaebabf8f5a4b5b4ef68221aeb73729f91f11f98f (patch)
tree6cc4117df89eec3be7ea8cbb199515aef4622aca /app
parent67cd2904c9ebd7ba346cc92a37ac953747a3f0e5 (diff)
downloadgitlab-ce-aebabf8f5a4b5b4ef68221aeb73729f91f11f98f.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_metrics.js27
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue23
-rw-r--r--app/assets/javascripts/ide/stores/utils.js43
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/getters.js23
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue16
-rw-r--r--app/controllers/projects/alert_management_controller.rb5
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/serializers/merge_request_poll_widget_entity.rb6
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml11
11 files changed, 119 insertions, 46 deletions
diff --git a/app/assets/javascripts/behaviors/markdown/render_metrics.js b/app/assets/javascripts/behaviors/markdown/render_metrics.js
index 9260a89bd52..37cbce46b6f 100644
--- a/app/assets/javascripts/behaviors/markdown/render_metrics.js
+++ b/app/assets/javascripts/behaviors/markdown/render_metrics.js
@@ -1,15 +1,12 @@
import Vue from 'vue';
-import EmbedGroup from '~/monitoring/components/embeds/embed_group.vue';
import { createStore } from '~/monitoring/stores/embed_group/';
// TODO: Handle copy-pasting - https://gitlab.com/gitlab-org/gitlab-foss/issues/64369.
export default function renderMetrics(elements) {
if (!elements.length) {
- return;
+ return Promise.resolve();
}
- const EmbedGroupComponent = Vue.extend(EmbedGroup);
-
const wrapperList = [];
elements.forEach(element => {
@@ -31,14 +28,20 @@ export default function renderMetrics(elements) {
element.parentNode.removeChild(element);
});
- wrapperList.forEach(wrapper => {
- // eslint-disable-next-line no-new
- new EmbedGroupComponent({
- el: wrapper,
- store: createStore(),
- propsData: {
- urls: wrapper.urls,
- },
+ return import(
+ /* webpackChunkName: 'gfm_metrics' */ '~/monitoring/components/embeds/embed_group.vue'
+ ).then(({ default: EmbedGroup }) => {
+ const EmbedGroupComponent = Vue.extend(EmbedGroup);
+
+ wrapperList.forEach(wrapper => {
+ // eslint-disable-next-line no-new
+ new EmbedGroupComponent({
+ el: wrapper,
+ store: createStore(),
+ propsData: {
+ urls: wrapper.urls,
+ },
+ });
});
});
}
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index a0305a8f52f..c72a8b2b0d0 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -13,6 +13,7 @@ import {
import Editor from '../lib/editor';
import FileTemplatesBar from './file_templates/bar.vue';
import { __ } from '~/locale';
+import { extractMarkdownImagesFromEntries } from '../stores/utils';
export default {
components: {
@@ -26,6 +27,12 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ content: '',
+ images: {},
+ };
+ },
computed: {
...mapState('rightPane', {
rightPaneIsOpen: 'isOpen',
@@ -36,6 +43,7 @@ export default {
'currentActivityView',
'renderWhitespaceInCode',
'editorTheme',
+ 'entries',
]),
...mapGetters([
'currentMergeRequest',
@@ -136,6 +144,18 @@ export default {
this.$nextTick(() => this.refreshEditorDimensions());
}
},
+ showContentViewer(val) {
+ if (!val) return;
+
+ if (this.fileType === 'markdown') {
+ const { content, images } = extractMarkdownImagesFromEntries(this.file, this.entries);
+ this.content = content;
+ this.images = images;
+ } else {
+ this.content = this.file.content || this.file.raw;
+ this.images = {};
+ }
+ },
},
beforeDestroy() {
this.editor.dispose();
@@ -310,7 +330,8 @@ export default {
></div>
<content-viewer
v-if="showContentViewer"
- :content="file.content || file.raw"
+ :content="content"
+ :images="images"
:path="file.rawPath || file.path"
:file-path="file.path"
:file-size="file.size"
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index 4e5b01596d8..56671142bd4 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -1,4 +1,5 @@
import { commitActionTypes, FILE_VIEW_MODE_EDITOR } from '../constants';
+import { relativePathToAbsolute, isAbsolute, isRootRelative } from '~/lib/utils/url_utility';
export const dataStructure = () => ({
id: '',
@@ -274,3 +275,45 @@ export const pathsAreEqual = (a, b) => {
// if the contents of a file dont end with a newline, this function adds a newline
export const addFinalNewlineIfNeeded = content =>
content.charAt(content.length - 1) !== '\n' ? `${content}\n` : content;
+
+export function extractMarkdownImagesFromEntries(mdFile, entries) {
+ /**
+ * Regex to identify an image tag in markdown, like:
+ *
+ * ![img alt goes here](/img.png)
+ * ![img alt](../img 1/img.png "my image title")
+ * ![img alt](https://gitlab.com/assets/logo.svg "title here")
+ *
+ */
+ const reMdImage = /!\[([^\]]*)\]\((.*?)(?:(?="|\))"([^"]*)")?\)/gi;
+ const prefix = 'gl_md_img_';
+ const images = {};
+
+ let content = mdFile.content || mdFile.raw;
+ let i = 0;
+
+ content = content.replace(reMdImage, (_, alt, path, title) => {
+ const imagePath = (isRootRelative(path) ? path : relativePathToAbsolute(path, mdFile.path))
+ .substr(1)
+ .trim();
+
+ const imageContent = entries[imagePath]?.content || entries[imagePath]?.raw;
+
+ if (!isAbsolute(path) && imageContent) {
+ const ext = path.includes('.')
+ ? path
+ .split('.')
+ .pop()
+ .trim()
+ : 'jpeg';
+ const src = `data:image/${ext};base64,${imageContent}`;
+ i += 1;
+ const key = `{{${prefix}${i}}}`;
+ images[key] = { alt, src, title };
+ return key;
+ }
+ return title ? `![${alt}](${path}"${title}")` : `![${alt}](${path})`;
+ });
+
+ return { content, images };
+}
diff --git a/app/assets/javascripts/reports/accessibility_report/store/getters.js b/app/assets/javascripts/reports/accessibility_report/store/getters.js
index 83e97a48e3b..9aff427e644 100644
--- a/app/assets/javascripts/reports/accessibility_report/store/getters.js
+++ b/app/assets/javascripts/reports/accessibility_report/store/getters.js
@@ -37,23 +37,12 @@ export const summaryStatus = state => {
export const shouldRenderIssuesList = state =>
Object.values(state.report).some(x => Array.isArray(x) && x.length > 0);
-export const unresolvedIssues = state => [
- ...state.report.existing_errors,
- ...state.report.existing_warnings,
- ...state.report.existing_notes,
-];
-
-export const resolvedIssues = state => [
- ...state.report.resolved_errors,
- ...state.report.resolved_warnings,
- ...state.report.resolved_notes,
-];
-
-export const newIssues = state => [
- ...state.report.new_errors,
- ...state.report.new_warnings,
- ...state.report.new_notes,
-];
+// We could just map state, but we're going to iterate in the future
+// to add notes and warnings to these issue lists, so I'm going to
+// keep these as getters
+export const unresolvedIssues = state => state.report.existing_errors;
+export const resolvedIssues = state => state.report.resolved_errors;
+export const newIssues = state => state.report.new_errors;
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index d0251c29fba..265ff81f39f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -40,7 +40,6 @@ import TerraformPlan from './components/mr_widget_terraform_plan.vue';
import GroupedTestReportsApp from '../reports/components/grouped_test_reports_app.vue';
import { setFaviconOverlay } from '../lib/utils/common_utils';
import GroupedAccessibilityReportsApp from '../reports/accessibility_report/grouped_accessibility_reports_app.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
el: '#js-vue-mr-widget',
@@ -80,7 +79,6 @@ export default {
TerraformPlan,
GroupedAccessibilityReportsApp,
},
- mixins: [glFeatureFlagsMixin()],
props: {
mrData: {
type: Object,
@@ -146,7 +144,7 @@ export default {
});
},
shouldShowAccessibilityReport() {
- return this.mr.accessibilityReportPath && this.glFeatures.accessibilityMergeRequestWidget;
+ return this.mr.accessibilityReportPath;
},
},
watch: {
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
index 3f8b8cea256..fe488ab6cfa 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
@@ -39,6 +39,11 @@ export default {
required: false,
default: '',
},
+ images: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
},
computed: {
viewer() {
@@ -67,6 +72,7 @@ export default {
:file-size="fileSize"
:project-path="projectPath"
:content="content"
+ :images="images"
:commit-sha="commitSha"
/>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
index bfd13a4b10f..1344c766e0e 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -5,6 +5,7 @@ import '~/behaviors/markdown/render_gfm';
import { GlSkeletonLoading } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
+import { forEach, escape } from 'lodash';
const { CancelToken } = axios;
let axiosSource;
@@ -32,6 +33,11 @@ export default {
type: String,
required: true,
},
+ images: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
},
data() {
return {
@@ -76,7 +82,15 @@ export default {
postOptions,
)
.then(({ data }) => {
- this.previewContent = data.body;
+ let previewContent = data.body;
+ forEach(this.images, ({ src, title = '', alt }, key) => {
+ previewContent = previewContent.replace(
+ key,
+ `<img src="${escape(src)}" title="${escape(title)}" alt="${escape(alt)}">`,
+ );
+ });
+
+ this.previewContent = previewContent;
this.isLoading = false;
this.$nextTick(() => {
diff --git a/app/controllers/projects/alert_management_controller.rb b/app/controllers/projects/alert_management_controller.rb
index 086aca3f6a3..bcaaeb3c017 100644
--- a/app/controllers/projects/alert_management_controller.rb
+++ b/app/controllers/projects/alert_management_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Projects::AlertManagementController < Projects::ApplicationController
- before_action :ensure_list_feature_enabled, only: :index
before_action :ensure_detail_feature_enabled, only: :details
before_action :authorize_read_alert_management_alert!
before_action do
@@ -18,10 +17,6 @@ class Projects::AlertManagementController < Projects::ApplicationController
private
- def ensure_list_feature_enabled
- render_404 unless Feature.enabled?(:alert_management_minimal, project)
- end
-
def ensure_detail_feature_enabled
render_404 unless Feature.enabled?(:alert_management_detail, project)
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 87b69291559..5613b5b9589 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -32,7 +32,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:code_navigation, @project)
push_frontend_feature_flag(:widget_visibility_polling, @project, default_enabled: true)
push_frontend_feature_flag(:merge_ref_head_comments, @project)
- push_frontend_feature_flag(:accessibility_merge_request_widget, @project)
push_frontend_feature_flag(:mr_commit_neighbor_nav, @project, default_enabled: true)
end
diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb
index 08255db5cbf..aad607f358a 100644
--- a/app/serializers/merge_request_poll_widget_entity.rb
+++ b/app/serializers/merge_request_poll_widget_entity.rb
@@ -71,6 +71,12 @@ class MergeRequestPollWidgetEntity < Grape::Entity
end
end
+ expose :accessibility_report_path do |merge_request|
+ if merge_request.has_accessibility_reports?
+ accessibility_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
+ end
+ end
+
expose :terraform_reports_path do |merge_request|
if merge_request.has_terraform_reports?
terraform_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 2f33cb22502..f0e68423424 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -222,12 +222,11 @@
%span
= _('Metrics')
- - if Feature.enabled?(:alert_management_minimal, @project)
- - if project_nav_tab?(:alert_management)
- = nav_link(controller: :alert_management) do
- = link_to project_alert_management_index_path(@project), title: _('Alerts'), class: 'shortcuts-tracking qa-operations-tracking-link' do
- %span
- = _('Alerts')
+ - if project_nav_tab?(:alert_management)
+ = nav_link(controller: :alert_management) do
+ = link_to project_alert_management_index_path(@project), title: _('Alerts'), class: 'shortcuts-tracking qa-operations-tracking-link' do
+ %span
+ = _('Alerts')
- if project_nav_tab? :environments
= render_if_exists "layouts/nav/sidebar/tracing_link"