Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-07-29 03:10:57 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-07-29 03:10:57 +0300
commite064cd3f07fbc239fb46106a1eaf71379ea01603 (patch)
treeeb1f478d6f6d5e73bc50639f7af7a99b4d34a392 /app/assets/javascripts/behaviors
parent9037472904908109f5622a8a1e808c6225eced56 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/behaviors')
-rw-r--r--app/assets/javascripts/behaviors/components/json_table.vue71
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_gfm.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_json_table.js70
3 files changed, 145 insertions, 0 deletions
diff --git a/app/assets/javascripts/behaviors/components/json_table.vue b/app/assets/javascripts/behaviors/components/json_table.vue
new file mode 100644
index 00000000000..bb38d80c1b5
--- /dev/null
+++ b/app/assets/javascripts/behaviors/components/json_table.vue
@@ -0,0 +1,71 @@
+<script>
+import { GlTable, GlFormInput } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ GlTable,
+ GlFormInput,
+ },
+ props: {
+ fields: {
+ type: Array,
+ required: true,
+ },
+ items: {
+ type: Array,
+ required: true,
+ },
+ hasFilter: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ caption: {
+ type: String,
+ required: false,
+ default: __('Generated with JSON data'),
+ },
+ },
+ data() {
+ return {
+ filterInput: '',
+ };
+ },
+ computed: {
+ cleanedFields() {
+ return this.fields.map((field) => {
+ if (typeof field === 'string') {
+ return field;
+ }
+ return {
+ key: field.key,
+ label: field.label,
+ sortable: field.sortable || false,
+ };
+ });
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-display-inline-block">
+ <gl-form-input
+ v-if="hasFilter"
+ v-model="filterInput"
+ :placeholder="__('Type to search')"
+ class="gl-mb-2!"
+ />
+ <gl-table
+ :fields="cleanedFields"
+ :items="items"
+ :filter="filterInput"
+ show-empty
+ class="gl-mt-0!"
+ >
+ <template v-if="caption" #table-caption>
+ <small>{{ caption }}</small>
+ </template>
+ </gl-table>
+ </div>
+</template>
diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js
index c9ae3706383..ee5c0fe5ef3 100644
--- a/app/assets/javascripts/behaviors/markdown/render_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js
@@ -5,6 +5,7 @@ import { renderKroki } from './render_kroki';
import renderMath from './render_math';
import renderSandboxedMermaid from './render_sandboxed_mermaid';
import renderMetrics from './render_metrics';
+import { renderJSONTable } from './render_json_table';
// Render GitLab flavoured Markdown
//
@@ -15,6 +16,9 @@ $.fn.renderGFM = function renderGFM() {
renderKroki(this.find('.js-render-kroki[hidden]').get());
renderMath(this.find('.js-render-math'));
renderSandboxedMermaid(this.find('.js-render-mermaid'));
+ renderJSONTable(
+ Array.from(this.find('[lang="json"][data-lang-params="table"]').get()).map((e) => e.parentNode),
+ );
highlightCurrentUser(this.find('.gfm-project_member').get());
diff --git a/app/assets/javascripts/behaviors/markdown/render_json_table.js b/app/assets/javascripts/behaviors/markdown/render_json_table.js
new file mode 100644
index 00000000000..4d9ac1d266b
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/render_json_table.js
@@ -0,0 +1,70 @@
+import { memoize } from 'lodash';
+import Vue from 'vue';
+import { __ } from '~/locale';
+import { createAlert } from '~/flash';
+
+// Async import component since we might not need it...
+const JSONTable = memoize(() =>
+ import(/* webpackChunkName: 'gfm_json_table' */ '../components/json_table.vue'),
+);
+
+const mountParseError = (element) => {
+ // Let the error container be a sibling to the element.
+ // Otherwise, dismissing the alert causes the copy button to be misplaced.
+ const container = document.createElement('div');
+ element.insertAdjacentElement('beforebegin', container);
+
+ // We need to create a child element with a known selector for `createAlert`
+ const el = document.createElement('div');
+ el.classList.add('js-json-table-error');
+
+ container.insertAdjacentElement('afterbegin', el);
+
+ return createAlert({
+ message: __('Unable to parse JSON'),
+ variant: 'warning',
+ parent: container,
+ containerSelector: '.js-json-table-error',
+ });
+};
+
+const mountJSONTableVueComponent = (userData, element) => {
+ const { fields = [], items = [], filter, caption } = userData;
+
+ const container = document.createElement('div');
+ element.innerHTML = '';
+ element.appendChild(container);
+
+ return new Vue({
+ el: container,
+ render(h) {
+ return h(JSONTable, {
+ props: {
+ fields,
+ items,
+ hasFilter: filter,
+ caption,
+ },
+ });
+ },
+ });
+};
+
+const renderTable = (element) => {
+ // Avoid rendering multiple times
+ if (!element || element.classList.contains('js-json-table')) {
+ return;
+ }
+
+ element.classList.add('js-json-table');
+
+ try {
+ mountJSONTableVueComponent(JSON.parse(element.textContent), element);
+ } catch (e) {
+ mountParseError(element);
+ }
+};
+
+export const renderJSONTable = (elements) => {
+ elements.forEach(renderTable);
+};