diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-07-23 12:09:18 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-07-23 12:09:18 +0300 |
commit | defde9698e1d87e7d8c09e487ed75675d1d67323 (patch) | |
tree | ec74808523206172b81bd83baf7dd0f579b933f0 /app/assets/javascripts/incidents | |
parent | 6520b1366e604be8c9c43f36159ecd6a5284a2b0 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/incidents')
4 files changed, 192 insertions, 0 deletions
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue new file mode 100644 index 00000000000..a974afbe539 --- /dev/null +++ b/app/assets/javascripts/incidents/components/incidents_list.vue @@ -0,0 +1,129 @@ +<script> +import { GlLoadingIcon, GlTable, GlAlert } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import getIncidents from '../graphql/queries/get_incidents.query.graphql'; +import { I18N } from '../constants'; + +const tdClass = + 'table-col gl-display-flex d-md-table-cell gl-align-items-center gl-white-space-nowrap'; +const thClass = 'gl-hover-bg-blue-50'; +const bodyTrClass = + 'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-border-b-solid gl-hover-border-blue-200'; + +export default { + i18n: I18N, + fields: [ + { + key: 'title', + label: s__('IncidentManagement|Incident'), + thClass: `gl-pointer-events-none gl-w-half`, + tdClass, + }, + { + key: 'createdAt', + label: s__('IncidentManagement|Date created'), + thClass: `${thClass} gl-pointer-events-none`, + tdClass, + }, + { + key: 'assignees', + label: s__('IncidentManagement|Assignees'), + thClass: 'gl-pointer-events-none', + tdClass, + }, + ], + components: { + GlLoadingIcon, + GlTable, + GlAlert, + }, + inject: ['projectPath'], + apollo: { + incidents: { + query: getIncidents, + variables() { + return { + projectPath: this.projectPath, + labelNames: ['incident'], + }; + }, + update: ({ project: { issues: { nodes = [] } = {} } = {} }) => nodes, + error() { + this.errored = true; + }, + }, + }, + data() { + return { + errored: false, + isErrorAlertDismissed: false, + }; + }, + computed: { + showErrorMsg() { + return this.errored && !this.isErrorAlertDismissed; + }, + loading() { + return this.$apollo.queries.incidents.loading; + }, + hasIncidents() { + return this.incidents?.length; + }, + tbodyTrClass() { + return { + [bodyTrClass]: !this.loading && this.hasIncidents, + }; + }, + }, + methods: { + getAssignees(assignees) { + return assignees.nodes?.length > 0 + ? assignees.nodes[0]?.username + : s__('IncidentManagement|Unassigned'); + }, + }, +}; +</script> +<template> + <div class="incident-management-list"> + <gl-alert v-if="showErrorMsg" variant="danger" @dismiss="isErrorAlertDismissed = true"> + {{ $options.i18n.errorMsg }} + </gl-alert> + + <h4 class="gl-display-block d-md-none my-3"> + {{ s__('IncidentManagement|Incidents') }} + </h4> + <gl-table + :items="incidents" + :fields="$options.fields" + :show-empty="true" + :busy="loading" + stacked="md" + :tbody-tr-class="tbodyTrClass" + :no-local-sorting="true" + fixed + > + <template #cell(title)="{ item }"> + <div class="gl-max-w-full text-truncate" :title="item.title">{{ item.title }}</div> + </template> + + <template #cell(createdAt)="{ item }"> + {{ item.createdAt }} + </template> + + <template #cell(assignees)="{ item }"> + <div class="gl-max-w-full text-truncate" data-testid="assigneesField"> + {{ getAssignees(item.assignees) }} + </div> + </template> + + <template #table-busy> + <gl-loading-icon size="lg" color="dark" class="mt-3" /> + </template> + + <template #empty> + {{ $options.i18n.noIncidents }} + </template> + </gl-table> + </div> +</template> diff --git a/app/assets/javascripts/incidents/constants.js b/app/assets/javascripts/incidents/constants.js new file mode 100644 index 00000000000..572a8d851cb --- /dev/null +++ b/app/assets/javascripts/incidents/constants.js @@ -0,0 +1,7 @@ +/* eslint-disable import/prefer-default-export */ +import { s__ } from '~/locale'; + +export const I18N = { + errorMsg: s__('IncidentManagement|There was an error displaying the incidents.'), + noIncidents: s__('IncidentManagement|No incidents to display.'), +}; diff --git a/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql new file mode 100644 index 00000000000..4478aa56ee7 --- /dev/null +++ b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql @@ -0,0 +1,22 @@ +query getIncidents($projectPath: ID!, $labelNames: [String], $state: IssuableState) { + project(fullPath: $projectPath) { + issues(state: $state, labelName: $labelNames) { + nodes { + iid + title + createdAt + labels { + nodes { + title + color + } + } + assignees { + nodes { + username + } + } + } + } + } +} diff --git a/app/assets/javascripts/incidents/list.js b/app/assets/javascripts/incidents/list.js new file mode 100644 index 00000000000..f1599477c1a --- /dev/null +++ b/app/assets/javascripts/incidents/list.js @@ -0,0 +1,34 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +import IncidentsList from './components/incidents_list.vue'; + +Vue.use(VueApollo); +export default () => { + const selector = '#js-incidents'; + + const domEl = document.querySelector(selector); + const { projectPath } = domEl.dataset; + + const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), + }); + + return new Vue({ + el: selector, + provide: { + projectPath, + }, + apolloProvider, + components: { + IncidentsList, + }, + render(createElement) { + return createElement('incidents-list', { + props: { + projectPath, + }, + }); + }, + }); +}; |