Commit d10d8da7 authored by Alexander Turinske's avatar Alexander Turinske

Move empty state into the threat monitoring tabs

- with the addition of the alerts tab, which does not
  need an environment set up for the project,
  move the empty state, that is shown when an invalid
  environment id is provided, into the tabs that
  require an environment
- create new component as empty state now has two
  instances
- update tests
parent 54c270f1
<script>
import { mapActions } from 'vuex';
import {
GlAlert,
GlEmptyState,
GlIcon,
GlLink,
GlPopover,
GlSprintf,
GlTabs,
GlTab,
} from '@gitlab/ui';
import { GlAlert, GlIcon, GlLink, GlPopover, GlTabs, GlTab } from '@gitlab/ui';
import { s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
......@@ -17,22 +8,22 @@ import Alerts from './alerts/alerts.vue';
import ThreatMonitoringFilters from './threat_monitoring_filters.vue';
import ThreatMonitoringSection from './threat_monitoring_section.vue';
import NetworkPolicyList from './network_policy_list.vue';
import NoEnvironmentEmptyState from './no_environment_empty_state.vue';
export default {
name: 'ThreatMonitoring',
components: {
GlAlert,
GlEmptyState,
GlIcon,
GlLink,
GlPopover,
GlSprintf,
GlTabs,
GlTab,
Alerts,
ThreatMonitoringFilters,
ThreatMonitoringSection,
NetworkPolicyList,
NoEnvironmentEmptyState,
},
mixins: [glFeatureFlagsMixin()],
inject: ['documentationPath'],
......@@ -45,10 +36,6 @@ export default {
type: String,
required: true,
},
emptyStateSvgPath: {
type: String,
required: true,
},
wafNoDataSvgPath: {
type: String,
required: true,
......@@ -122,10 +109,6 @@ export default {
`ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view
this data, ensure your Network Policies are installed and enabled for your cluster.`,
),
emptyStateDescription: s__(
`ThreatMonitoring|To view this data, ensure you have configured an environment
for this project and that at least one threat monitoring feature is enabled. %{linkStart}More information%{linkEnd}`,
),
alertText: s__(
`ThreatMonitoring|The graph below is an overview of traffic coming to your
application as tracked by the Web Application Firewall (WAF). View the docs
......@@ -138,22 +121,7 @@ export default {
</script>
<template>
<gl-empty-state
v-if="!isSetUpMaybe"
ref="emptyState"
:title="s__('ThreatMonitoring|No environments detected')"
:svg-path="emptyStateSvgPath"
>
<template #description>
<gl-sprintf :message="$options.emptyStateDescription">
<template #link="{ content }">
<gl-link :href="documentationPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</template>
</gl-empty-state>
<section v-else>
<section>
<gl-alert
v-if="showAlert"
class="my-3"
......@@ -190,45 +158,55 @@ export default {
<alerts />
</gl-tab>
<gl-tab ref="networkPolicyTab" :title="s__('ThreatMonitoring|Policies')">
<no-environment-empty-state v-if="!isSetUpMaybe" />
<network-policy-list
v-else
:documentation-path="documentationPath"
:new-policy-path="newPolicyPath"
/>
</gl-tab>
<gl-tab :title="s__('ThreatMonitoring|Statistics')">
<threat-monitoring-filters />
<gl-tab
:title="s__('ThreatMonitoring|Statistics')"
data-testid="threat-monitoring-statistics-tab"
>
<no-environment-empty-state v-if="!isSetUpMaybe" />
<div v-else>
<threat-monitoring-filters />
<threat-monitoring-section
ref="wafSection"
store-namespace="threatMonitoringWaf"
:title="s__('ThreatMonitoring|Web Application Firewall')"
:subtitle="s__('ThreatMonitoring|Requests')"
:anomalous-title="s__('ThreatMonitoring|Anomalous Requests')"
:nominal-title="s__('ThreatMonitoring|Total Requests')"
:y-legend="s__('ThreatMonitoring|Requests')"
:chart-empty-state-title="s__('ThreatMonitoring|Application firewall not detected')"
:chart-empty-state-text="$options.wafChartEmptyStateDescription"
:chart-empty-state-svg-path="wafNoDataSvgPath"
:documentation-path="documentationPath"
documentation-anchor="web-application-firewall"
/>
<threat-monitoring-section
ref="wafSection"
store-namespace="threatMonitoringWaf"
:title="s__('ThreatMonitoring|Web Application Firewall')"
:subtitle="s__('ThreatMonitoring|Requests')"
:anomalous-title="s__('ThreatMonitoring|Anomalous Requests')"
:nominal-title="s__('ThreatMonitoring|Total Requests')"
:y-legend="s__('ThreatMonitoring|Requests')"
:chart-empty-state-title="s__('ThreatMonitoring|Application firewall not detected')"
:chart-empty-state-text="$options.wafChartEmptyStateDescription"
:chart-empty-state-svg-path="wafNoDataSvgPath"
:documentation-path="documentationPath"
documentation-anchor="web-application-firewall"
/>
<hr />
<hr />
<threat-monitoring-section
ref="networkPolicySection"
store-namespace="threatMonitoringNetworkPolicy"
:title="s__('ThreatMonitoring|Container Network Policy')"
:subtitle="s__('ThreatMonitoring|Packet Activity')"
:anomalous-title="s__('ThreatMonitoring|Dropped Packets')"
:nominal-title="s__('ThreatMonitoring|Total Packets')"
:y-legend="s__('ThreatMonitoring|Operations Per Second')"
:chart-empty-state-title="s__('ThreatMonitoring|Container NetworkPolicies not detected')"
:chart-empty-state-text="$options.networkPolicyChartEmptyStateDescription"
:chart-empty-state-svg-path="networkPolicyNoDataSvgPath"
:documentation-path="documentationPath"
documentation-anchor="container-network-policy"
/>
<threat-monitoring-section
ref="networkPolicySection"
store-namespace="threatMonitoringNetworkPolicy"
:title="s__('ThreatMonitoring|Container Network Policy')"
:subtitle="s__('ThreatMonitoring|Packet Activity')"
:anomalous-title="s__('ThreatMonitoring|Dropped Packets')"
:nominal-title="s__('ThreatMonitoring|Total Packets')"
:y-legend="s__('ThreatMonitoring|Operations Per Second')"
:chart-empty-state-title="
s__('ThreatMonitoring|Container NetworkPolicies not detected')
"
:chart-empty-state-text="$options.networkPolicyChartEmptyStateDescription"
:chart-empty-state-svg-path="networkPolicyNoDataSvgPath"
:documentation-path="documentationPath"
documentation-anchor="container-network-policy"
/>
</div>
</gl-tab>
</gl-tabs>
</section>
......
......@@ -5,6 +5,11 @@ export const TOTAL_REQUESTS = s__('ThreatMonitoring|Total Requests');
export const ANOMALOUS_REQUESTS = s__('ThreatMonitoring|Anomalous Requests');
export const TIME = s__('ThreatMonitoring|Time');
export const REQUESTS = s__('ThreatMonitoring|Requests');
export const NO_ENVIRONMENT_TITLE = s__('ThreatMonitoring|No environments detected');
export const EMPTY_STATE_DESCRIPTION = s__(
`ThreatMonitoring|To view this data, ensure you have configured an environment
for this project and that at least one threat monitoring feature is enabled. %{linkStart}More information%{linkEnd}`,
);
export const COLORS = {
nominal: gray700,
......
<script>
import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
import { EMPTY_STATE_DESCRIPTION, NO_ENVIRONMENT_TITLE } from './constants';
export default {
i18n: { EMPTY_STATE_DESCRIPTION, NO_ENVIRONMENT_TITLE },
name: 'NoEnvironmentEmptyState',
components: {
GlEmptyState,
GlLink,
GlSprintf,
},
inject: ['documentationPath', 'emptyStateSvgPath'],
};
</script>
<template>
<gl-empty-state :title="$options.i18n.NO_ENVIRONMENT_TITLE" :svg-path="emptyStateSvgPath">
<template #description>
<gl-sprintf :message="$options.i18n.EMPTY_STATE_DESCRIPTION">
<template #link="{ content }">
<gl-link :href="documentationPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</template>
</gl-empty-state>
</template>
......@@ -46,6 +46,7 @@ export default () => {
el,
provide: {
documentationPath,
emptyStateSvgPath,
projectPath,
},
store,
......@@ -53,7 +54,6 @@ export default () => {
return createElement(ThreatMonitoringApp, {
props: {
chartEmptyStateSvgPath,
emptyStateSvgPath,
wafNoDataSvgPath,
networkPolicyNoDataSvgPath,
defaultEnvironmentId: parseInt(defaultEnvironmentId, 10),
......
---
title: Move empty state into the threat monitoring tabs
merge_request: 51748
author:
type: changed
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NoEnvironmentEmptyState component default state matches the snapshot 1`] = `
<gl-empty-state-stub
svgpath="/svgs"
title="No environments detected"
>
<gl-sprintf-stub
message="To view this data, ensure you have configured an environment for this project and that at least one threat monitoring feature is enabled. %{linkStart}More information%{linkEnd}"
/>
</gl-empty-state-stub>
`;
import { GlAlert, GlSprintf } from '@gitlab/ui';
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import ThreatMonitoringAlerts from 'ee/threat_monitoring/components/alerts/alerts.vue';
import ThreatMonitoringApp from 'ee/threat_monitoring/components/app.vue';
import ThreatMonitoringFilters from 'ee/threat_monitoring/components/threat_monitoring_filters.vue';
import NetworkPolicyList from 'ee/threat_monitoring/components/network_policy_list.vue';
import NoEnvironmentEmptyState from 'ee/threat_monitoring/components/no_environment_empty_state.vue';
import createStore from 'ee/threat_monitoring/store';
import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
......@@ -25,7 +27,7 @@ describe('ThreatMonitoringApp component', () => {
let store;
let wrapper;
const factory = ({ propsData, provide = {}, state, options } = {}) => {
const factory = ({ propsData, provide = {}, state, stubs = {} } = {}) => {
store = createStore();
Object.assign(store.state.threatMonitoring, {
environmentsEndpoint,
......@@ -55,19 +57,20 @@ describe('ThreatMonitoringApp component', () => {
...provide,
},
store,
...options,
stubs,
});
};
const findAlert = () => wrapper.find(GlAlert);
const findAlertsView = () => wrapper.find(ThreatMonitoringAlerts);
const findNetworkPolicyList = () => wrapper.find(NetworkPolicyList);
const findFilters = () => wrapper.find(ThreatMonitoringFilters);
const findWafSection = () => wrapper.find({ ref: 'wafSection' });
const findNetworkPolicySection = () => wrapper.find({ ref: 'networkPolicySection' });
const findEmptyState = () => wrapper.find({ ref: 'emptyState' });
const findEmptyStateMessage = () => wrapper.find(GlSprintf);
const findNoEnvironmentEmptyStates = () => wrapper.findAll(NoEnvironmentEmptyState);
const findNetworkPolicyTab = () => wrapper.find({ ref: 'networkPolicyTab' });
const findAlertTab = () => wrapper.find('[data-testid="threat-monitoring-alerts-tab"]');
const findStatisticsTab = () => wrapper.find('[data-testid="threat-monitoring-statistics-tab"]');
afterEach(() => {
wrapper.destroy();
......@@ -82,6 +85,7 @@ describe('ThreatMonitoringApp component', () => {
propsData: {
defaultEnvironmentId: invalidEnvironmentId,
},
stubs: { GlTabs: false },
});
});
......@@ -89,13 +93,21 @@ describe('ThreatMonitoringApp component', () => {
expect(store.dispatch).not.toHaveBeenCalled();
});
it('shows only the empty state', () => {
const emptyState = findEmptyState();
expect(wrapper.element).toBe(emptyState.element);
expect(findEmptyStateMessage().exists()).toBe(true);
expect(emptyState.props()).toMatchObject({
svgPath: emptyStateSvgPath,
});
it('shows the no environment empty state', () => {
expect(findNoEnvironmentEmptyStates().length).toBe(2);
});
it('shows the tabs', () => {
expect(findNetworkPolicyTab().exists()).toBe(true);
expect(findStatisticsTab().exists()).toBe(true);
});
it('does not show the network policy list', () => {
expect(findNetworkPolicyList().exists()).toBe(false);
});
it('does not show the threat monitoring section', () => {
expect(findNetworkPolicySection().exists()).toBe(false);
});
},
);
......
import { shallowMount } from '@vue/test-utils';
import NoEnvironmentEmptyState from 'ee/threat_monitoring/components/no_environment_empty_state.vue';
const documentationPath = '/docs';
const emptyStateSvgPath = '/svgs';
describe('NoEnvironmentEmptyState component', () => {
let wrapper;
const factory = () => {
wrapper = shallowMount(NoEnvironmentEmptyState, {
provide: {
documentationPath,
emptyStateSvgPath,
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('default state', () => {
beforeEach(() => {
factory();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment