From 746575a5ab759edfffb4f2cc06609513eaa3c0d4 Mon Sep 17 00:00:00 2001 From: Mark Florian Date: Fri, 27 Mar 2020 18:21:46 +0000 Subject: [PATCH 1/3] Update dependencies table UI Part of [Update dependencies table UI][1]. This is the largest piece that implements the new table layout. It's behind the `dependency_list_ui` feature flag, which is currently disabled by default. This means that the existing UI is still in place, and unaffected. Specifically, this: - Reimplements the table using `GlTable` from GitLab UI - Removes the UI tabs - Combines the component name and version columns - Adds a warning badge for rows with vulnerabilities - Adds a document icon to the location column [1]: https://gitlab.com/gitlab-org/gitlab/-/issues/195928 --- .../dependencies/components/app.vue | 69 +++--- .../components/dependencies_table.vue | 129 ++++++++++- .../projects/dependencies_controller.rb | 4 + .../components/__snapshots__/app_spec.js.snap | 26 +++ .../dependencies/components/app_spec.js | 162 ++++++++++++- .../components/dependencies_table_spec.js | 215 +++++++++++++++++- locale/gitlab.pot | 5 + 7 files changed, 578 insertions(+), 32 deletions(-) diff --git a/ee/app/assets/javascripts/dependencies/components/app.vue b/ee/app/assets/javascripts/dependencies/components/app.vue index 55a044069b3825..c6ee05de3c21b1 100644 --- a/ee/app/assets/javascripts/dependencies/components/app.vue +++ b/ee/app/assets/javascripts/dependencies/components/app.vue @@ -12,6 +12,7 @@ import { } from '@gitlab/ui'; import { __ } from '~/locale'; import Icon from '~/vue_shared/components/icon.vue'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import DependenciesActions from './dependencies_actions.vue'; import DependencyListIncompleteAlert from './dependency_list_incomplete_alert.vue'; import DependencyListJobFailedAlert from './dependency_list_job_failed_alert.vue'; @@ -36,6 +37,7 @@ export default { Icon, PaginatedDependenciesTable, }, + mixins: [glFeatureFlagsMixin()], props: { endpoint: { type: String, @@ -157,36 +159,47 @@ export default { @dismiss="dismissJobFailedAlert" /> -
-

- {{ __('Dependencies') }} - - - -

-

- - - - - - {{ generatedAtTimeAgo }} - -

+
+
+

+ {{ __('Dependencies') }} + + + +

+

+ + + + + + {{ generatedAtTimeAgo }} + +

+
+
- +
+ +
+ + +import { cloneDeep } from 'lodash'; +import { GlBadge, GlIcon, GlLink, GlNewButton, GlSkeletonLoading, GlTable } from '@gitlab/ui'; import { s__ } from '~/locale'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import DependenciesTableRow from './dependencies_table_row.vue'; +import DependencyLicenseLinks from './dependency_license_links.vue'; +import DependencyVulnerabilities from './dependency_vulnerabilities.vue'; + +const tdClass = (value, key, item) => { + const classes = []; + + // eslint-disable-next-line no-underscore-dangle + if (item._showDetails) { + classes.push('border-bottom-0'); + } + + if (key === 'isVulnerable') { + classes.push('text-right'); + } + + return classes; +}; export default { name: 'DependenciesTable', components: { DependenciesTableRow, + DependencyLicenseLinks, + DependencyVulnerabilities, + GlBadge, + GlIcon, + GlLink, + GlNewButton, + GlSkeletonLoading, + GlTable, }, + mixins: [glFeatureFlagsMixin()], props: { dependencies: { type: Array, @@ -27,13 +56,109 @@ export default { { className: 'section-15', label: s__('Dependencies|License') }, ]; - return { tableSections }; + return { + localDependencies: this.transformDependenciesForUI(this.dependencies), + tableSections, + }; }, + computed: { + anyDependencyHasVulnerabilities() { + return this.localDependencies.some(({ vulnerabilities }) => vulnerabilities.length > 0); + }, + }, + watch: { + dependencies(dependencies) { + this.localDependencies = this.transformDependenciesForUI(dependencies); + }, + }, + methods: { + transformDependenciesForUI(dependencies) { + return cloneDeep(dependencies).map(dependency => ({ + ...dependency, + + // GlTable uses this field to track whether to render the "details" + // row beneath this row. + _showDetails: false, + })); + }, + }, + fields: [ + { key: 'component', label: s__('Dependencies|Component'), tdClass }, + { key: 'packager', label: s__('Dependencies|Packager'), tdClass }, + { key: 'location', label: s__('Dependencies|Location'), tdClass }, + { key: 'license', label: s__('Dependencies|License'), tdClass }, + { key: 'isVulnerable', label: '', tdClass }, + ], + DEPENDENCIES_PER_PAGE: 20, };