Commit 60625c65 authored by Brandon Labuschagne's avatar Brandon Labuschagne

Merge branch '339369-adjustments-to-the-policy-editor' into 'master'

Redesign new policy form

See merge request gitlab-org/gitlab!77482
parents bf965664 eedf5c44
...@@ -4,7 +4,7 @@ import { ...@@ -4,7 +4,7 @@ import {
GlFormGroup, GlFormGroup,
GlFormInput, GlFormInput,
GlFormTextarea, GlFormTextarea,
GlToggle, GlFormCheckbox,
GlButton, GlButton,
GlAlert, GlAlert,
GlIcon, GlIcon,
...@@ -35,11 +35,9 @@ import PolicyRuleBuilder from './policy_rule_builder.vue'; ...@@ -35,11 +35,9 @@ import PolicyRuleBuilder from './policy_rule_builder.vue';
export default { export default {
EDITOR_MODES, EDITOR_MODES,
i18n: { i18n: {
basicInformation: __('Basic information'),
actions: s__('SecurityOrchestration|Actions'), actions: s__('SecurityOrchestration|Actions'),
addRule: s__('SecurityOrchestration|Add rule'), addRule: s__('SecurityOrchestration|Add rule'),
defaultTrafficBehavior: s__(
'NetworkPolicies|Traffic that does not match any rule will be blocked.',
),
description: __('Description'), description: __('Description'),
toggleLabel: s__('SecurityOrchestration|Policy status'), toggleLabel: s__('SecurityOrchestration|Policy status'),
PARSING_ERROR_MESSAGE, PARSING_ERROR_MESSAGE,
...@@ -49,7 +47,8 @@ export default { ...@@ -49,7 +47,8 @@ export default {
), ),
noEnvironmentButton: __('Learn more'), noEnvironmentButton: __('Learn more'),
yamlPreview: s__('SecurityOrchestration|.yaml preview'), yamlPreview: s__('SecurityOrchestration|.yaml preview'),
policyPreview: s__('SecurityOrchestration|Policy preview'), policySummary: s__('SecurityOrchestration|Policy summary'),
policyEnabled: __('Enabled'),
rules: s__('SecurityOrchestration|Rules'), rules: s__('SecurityOrchestration|Rules'),
saveButtonTooltip: s__( saveButtonTooltip: s__(
'NetworkPolicies|Network policy can be created after the environment is loaded successfully.', 'NetworkPolicies|Network policy can be created after the environment is loaded successfully.',
...@@ -61,7 +60,7 @@ export default { ...@@ -61,7 +60,7 @@ export default {
GlFormGroup, GlFormGroup,
GlFormInput, GlFormInput,
GlFormTextarea, GlFormTextarea,
GlToggle, GlFormCheckbox,
GlButton, GlButton,
GlAlert, GlAlert,
GlIcon, GlIcon,
...@@ -236,11 +235,15 @@ export default { ...@@ -236,11 +235,15 @@ export default {
{{ $options.i18n.PARSING_ERROR_MESSAGE }} {{ $options.i18n.PARSING_ERROR_MESSAGE }}
</gl-alert> </gl-alert>
<h5 class="gl-mt-0 gl-mb-5">
{{ $options.i18n.basicInformation }}
</h5>
<gl-form-group :label="$options.i18n.name" label-for="policyName"> <gl-form-group :label="$options.i18n.name" label-for="policyName">
<gl-form-input id="policyName" v-model="policy.name" :disabled="hasParsingError" /> <gl-form-input id="policyName" v-model="policy.name" :disabled="hasParsingError" />
</gl-form-group> </gl-form-group>
<gl-form-group :label="$options.i18n.description" label-for="policyDescription"> <gl-form-group :label="$options.i18n.description" label-for="policyDescription" optional>
<gl-form-textarea <gl-form-textarea
id="policyDescription" id="policyDescription"
v-model="policy.description" v-model="policy.description"
...@@ -248,13 +251,26 @@ export default { ...@@ -248,13 +251,26 @@ export default {
/> />
</gl-form-group> </gl-form-group>
<gl-form-group :disabled="hasParsingError" data-testid="policy-enable"> <gl-form-group
<gl-toggle v-model="policy.isEnabled" :label="$options.i18n.toggleLabel" /> :label="$options.i18n.toggleLabel"
:disabled="hasParsingError"
data-testid="policy-enable"
class="gl-mb-6"
>
<gl-form-checkbox id="policyStatus" v-model="policy.isEnabled">
{{ $options.i18n.policyEnabled }}
</gl-form-checkbox>
</gl-form-group> </gl-form-group>
<dim-disable-container data-testid="rule-builder-container" :disabled="hasParsingError"> <dim-disable-container
class="gl-mb-6"
data-testid="rule-builder-container"
:disabled="hasParsingError"
>
<template #title> <template #title>
<h4>{{ $options.i18n.rules }}</h4> <h5 class="gl-mt-0 gl-mb-5">
{{ $options.i18n.rules }}
</h5>
</template> </template>
<template #disabled> <template #disabled>
...@@ -277,58 +293,54 @@ export default { ...@@ -277,58 +293,54 @@ export default {
@remove="removeRule(index)" @remove="removeRule(index)"
/> />
<div
class="gl-p-5 gl-rounded-base gl-border-1 gl-border-solid gl-border-gray-100 gl-mb-5 gl-bg-gray-10"
>
<gl-button variant="link" data-testid="add-rule" icon="plus" @click="addRule"> <gl-button variant="link" data-testid="add-rule" icon="plus" @click="addRule">
{{ $options.i18n.addRule }} {{ $options.i18n.addRule }}
</gl-button> </gl-button>
</div>
</dim-disable-container> </dim-disable-container>
<dim-disable-container data-testid="policy-action-container" :disabled="hasParsingError"> <dim-disable-container
class="gl-mb-6"
data-testid="policy-action-container"
:disabled="hasParsingError"
>
<template #title> <template #title>
<h4>{{ $options.i18n.actions }}</h4> <h5 class="gl-mt-0 gl-mb-5">{{ $options.i18n.actions }}</h5>
<p>{{ $options.i18n.defaultTrafficBehavior }}</p>
</template> </template>
<template #disabled> <template #disabled>
<div <div class="gl-bg-gray-10 gl-p-6"></div>
class="gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100 gl-rounded-base gl-p-6"
></div>
</template> </template>
<policy-action-picker /> <policy-action-picker />
<policy-alert-picker :policy-alert="policyAlert" @update-alert="handleAlertUpdate" /> <policy-alert-picker :policy-alert="policyAlert" @update-alert="handleAlertUpdate" />
</dim-disable-container> </dim-disable-container>
</template>
<template #rule-editor-preview> <div v-if="!hasParsingError" class="gl-my-6">
<h5>{{ $options.i18n.yamlPreview }}</h5>
<pre
data-testid="yaml-preview"
class="gl-bg-white gl-border-none gl-p-0"
:class="{ 'gl-opacity-5': hasParsingError }"
>{{ policyYaml || yamlEditorValue }}</pre
>
</template>
<template v-if="!hasParsingError" #bottom>
<div class="gl-my-6">
<gl-button <gl-button
v-collapse-toggle="$options.policyPreviewHumanCollapseId" v-collapse-toggle="$options.policyPreviewHumanCollapseId"
category="tertiary" category="tertiary"
class="gl-font-weight-bold gl-bg-transparent! gl-px-0!" class="gl-font-weight-bold gl-bg-transparent! gl-px-0!"
> >
{{ $options.i18n.policyPreview }} {{ $options.i18n.policySummary }}
<gl-icon :name="isPolicyPreviewHumanVisible ? 'angle-up' : 'angle-down'" :size="12" /> <gl-icon :name="isPolicyPreviewHumanVisible ? 'angle-up' : 'angle-down'" :size="12" />
</gl-button> </gl-button>
<gl-collapse <gl-collapse
:id="$options.policyPreviewHumanCollapseId" :id="$options.policyPreviewHumanCollapseId"
v-model="isPolicyPreviewHumanVisible" v-model="isPolicyPreviewHumanVisible"
> >
<policy-preview-human class="gl-md-w-70p" :policy-description="humanizedPolicy" /> <policy-preview-human :policy-description="humanizedPolicy" />
</gl-collapse> </gl-collapse>
</div> </div>
</template> </template>
<template #rule-editor-preview>
<h5>{{ $options.i18n.yamlPreview }}</h5>
<pre
data-testid="yaml-preview"
class="gl-border-none gl-p-0"
:class="{ 'gl-opacity-5': hasParsingError }"
>{{ policyYaml || yamlEditorValue }}</pre
>
</template>
</policy-editor-layout> </policy-editor-layout>
<gl-empty-state <gl-empty-state
v-else v-else
......
...@@ -132,13 +132,11 @@ export default { ...@@ -132,13 +132,11 @@ export default {
</script> </script>
<template> <template>
<div <div class="gl-bg-gray-10 gl-px-3 gl-pt-3 gl-relative gl-display-flex">
class="gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100 gl-rounded-base px-3 pt-3 gl-relative" <gl-form class="gl-flex-grow-1" inline @submit.prevent>
>
<gl-form inline @submit.prevent>
<gl-sprintf :message="sprintfTemplate"> <gl-sprintf :message="sprintfTemplate">
<template #ifLabel="{ content }"> <template #ifLabel="{ content }">
<label for="ruleType" class="text-uppercase gl-font-lg gl-mr-4 gl-mb-5!">{{ <label for="ruleType" class="text-uppercase gl-font-lg gl-mr-4 gl-mb-3!">{{
content content
}}</label> }}</label>
</template> </template>
...@@ -146,14 +144,14 @@ export default { ...@@ -146,14 +144,14 @@ export default {
<template #ruleType> <template #ruleType>
<gl-form-select <gl-form-select
id="ruleType" id="ruleType"
class="gl-mr-4 gl-mb-5" class="gl-mr-4 gl-mb-3"
:value="ruleType" :value="ruleType"
:options="$options.ruleTypes" :options="$options.ruleTypes"
/> />
</template> </template>
<template #isLabel="{ content }"> <template #isLabel="{ content }">
<label for="direction" class="gl-mr-4 gl-mb-5! gl-font-weight-normal">{{ <label for="direction" class="gl-mr-4 gl-mb-3! gl-font-weight-normal">{{
content content
}}</label> }}</label>
</template> </template>
...@@ -163,7 +161,7 @@ export default { ...@@ -163,7 +161,7 @@ export default {
<gl-form-select <gl-form-select
id="direction" id="direction"
v-model="rule.direction" v-model="rule.direction"
class="gl-mr-4 gl-mb-5" class="gl-mr-4 gl-mb-3"
:options="$options.trafficDirections" :options="$options.trafficDirections"
/> />
<!-- eslint-enable vue/no-mutating-props --> <!-- eslint-enable vue/no-mutating-props -->
...@@ -172,7 +170,7 @@ export default { ...@@ -172,7 +170,7 @@ export default {
<template #ruleSelector> <template #ruleSelector>
<gl-form-select <gl-form-select
data-testid="endpoint-match-mode" data-testid="endpoint-match-mode"
class="gl-mr-4 gl-mb-5" class="gl-mr-4 gl-mb-3"
:value="endpointMatchMode" :value="endpointMatchMode"
:disabled="endpointSelectorDisabled" :disabled="endpointSelectorDisabled"
:options="$options.endpointMatchModes" :options="$options.endpointMatchModes"
...@@ -183,7 +181,7 @@ export default { ...@@ -183,7 +181,7 @@ export default {
<gl-form-input <gl-form-input
v-if="shouldShowEndpointLabels" v-if="shouldShowEndpointLabels"
data-testid="endpoint-labels" data-testid="endpoint-labels"
class="gl-mr-4 gl-mb-5 gl-bg-white!" class="gl-mr-4 gl-mb-3 gl-bg-white!"
placeholder="key:value" placeholder="key:value"
:value="endpointLabels" :value="endpointLabels"
:disabled="endpointSelectorDisabled" :disabled="endpointSelectorDisabled"
...@@ -193,23 +191,23 @@ export default { ...@@ -193,23 +191,23 @@ export default {
</template> </template>
<template #directionLabel="{ content }"> <template #directionLabel="{ content }">
<label for="ruleMode" class="gl-mr-4 gl-mb-5! gl-font-weight-normal">{{ content }}</label> <label for="ruleMode" class="gl-mr-4 gl-mb-3! gl-font-weight-normal">{{ content }}</label>
</template> </template>
<template #rule> <template #rule>
<gl-form-select <gl-form-select
id="ruleMode" id="ruleMode"
class="gl-mr-4 gl-mb-5" class="gl-mr-4 gl-mb-3"
:value="rule.ruleType" :value="rule.ruleType"
:options="$options.ruleModes" :options="$options.ruleModes"
@change="$emit('rule-type-change', $event)" @change="$emit('rule-type-change', $event)"
/> />
<component :is="ruleComponentName" v-model="ruleComponentModel" class="gl-mr-4 gl-mb-5" /> <component :is="ruleComponentName" v-model="ruleComponentModel" class="gl-mr-4 gl-mb-3" />
</template> </template>
<template #portsLabel="{ content }"> <template #portsLabel="{ content }">
<label for="portMatch" class="gl-mr-4 gl-mb-5! gl-font-weight-normal">{{ <label for="portMatch" class="gl-mr-4 gl-mb-3! gl-font-weight-normal">{{
content content
}}</label> }}</label>
</template> </template>
...@@ -219,7 +217,7 @@ export default { ...@@ -219,7 +217,7 @@ export default {
<gl-form-select <gl-form-select
id="portMatch" id="portMatch"
v-model="rule.portMatchMode" v-model="rule.portMatchMode"
class="gl-mr-4 gl-mb-5" class="gl-mr-4 gl-mb-3"
:options="$options.portMatchModes" :options="$options.portMatchModes"
/> />
<!-- placeholder is the same in all languages--> <!-- placeholder is the same in all languages-->
...@@ -228,7 +226,7 @@ export default { ...@@ -228,7 +226,7 @@ export default {
v-if="shouldShowPorts" v-if="shouldShowPorts"
v-model="rule.ports" v-model="rule.ports"
data-testid="ports" data-testid="ports"
class="gl-mr-4 gl-mb-5 gl-bg-white!" class="gl-mr-4 gl-mb-3 gl-bg-white!"
placeholder="80/tcp" placeholder="80/tcp"
/> />
<!-- eslint-enable @gitlab/vue-require-i18n-attribute-strings --> <!-- eslint-enable @gitlab/vue-require-i18n-attribute-strings -->
...@@ -236,11 +234,10 @@ export default { ...@@ -236,11 +234,10 @@ export default {
</template> </template>
</gl-sprintf> </gl-sprintf>
</gl-form> </gl-form>
<gl-button <gl-button
icon="remove" icon="remove"
category="tertiary" category="tertiary"
class="gl-absolute gl-top-3 gl-right-3" class="gl-align-self-start gl-ml-3"
:aria-label="__('Remove')" :aria-label="__('Remove')"
data-testid="remove-rule" data-testid="remove-rule"
@click="$emit('remove')" @click="$emit('remove')"
......
...@@ -17,9 +17,7 @@ export default { ...@@ -17,9 +17,7 @@ export default {
</script> </script>
<template> <template>
<div <div class="gl-bg-gray-10 gl-px-5 gl-pt-5">
class="gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100 gl-rounded-base gl-px-5 gl-pt-5"
>
<gl-form inline> <gl-form inline>
<gl-sprintf <gl-sprintf
:message=" :message="
......
<script> <script>
import { GlAlert, GlFormGroup, GlFormSelect } from '@gitlab/ui'; import { GlAlert, GlFormGroup, GlFormSelect } from '@gitlab/ui';
import { s__ } from '~/locale';
import { POLICY_TYPE_COMPONENT_OPTIONS } from '../constants'; import { POLICY_TYPE_COMPONENT_OPTIONS } from '../constants';
import EnvironmentPicker from '../environment_picker.vue'; import EnvironmentPicker from '../environment_picker.vue';
import NetworkPolicyEditor from './network_policy/network_policy_editor.vue'; import NetworkPolicyEditor from './network_policy/network_policy_editor.vue';
...@@ -66,6 +67,9 @@ export default { ...@@ -66,6 +67,9 @@ export default {
this.newPolicyType = type; this.newPolicyType = type;
}, },
}, },
i18n: {
title: s__('SecurityOrchestration|Policy description'),
},
}; };
</script> </script>
...@@ -75,7 +79,7 @@ export default { ...@@ -75,7 +79,7 @@ export default {
{{ error }} {{ error }}
</gl-alert> </gl-alert>
<header class="gl-pb-5"> <header class="gl-pb-5">
<h3>{{ s__('SecurityOrchestration|Policy description') }}</h3> <h3>{{ $options.i18n.title }}</h3>
</header> </header>
<div class="gl-display-flex"> <div class="gl-display-flex">
<gl-form-group :label="s__('SecurityOrchestration|Policy type')" label-for="policyType"> <gl-form-group :label="s__('SecurityOrchestration|Policy type')" label-for="policyType">
......
<script> <script>
import { import {
GlButton, GlButton,
GlFormGroup,
GlModal, GlModal,
GlModalDirective, GlModalDirective,
GlSegmentedControl, GlSegmentedControl,
...@@ -16,7 +15,6 @@ export default { ...@@ -16,7 +15,6 @@ export default {
}, },
components: { components: {
GlButton, GlButton,
GlFormGroup,
GlModal, GlModal,
GlSegmentedControl, GlSegmentedControl,
PolicyYamlEditor: () => PolicyYamlEditor: () =>
...@@ -127,19 +125,17 @@ export default { ...@@ -127,19 +125,17 @@ export default {
</script> </script>
<template> <template>
<section> <section class="gl-mt-6">
<div class="gl-mb-5 gl-border-1 gl-border-solid gl-border-gray-100 gl-rounded-base"> <div class="gl-mb-5">
<gl-form-group <div class="gl-border-b-solid gl-border-b-1 gl-border-gray-100 gl-mb-6 gl-pb-6">
class="gl-px-5 gl-py-3 gl-mb-0 gl-bg-gray-10 gl-border-b-solid gl-border-b-gray-100 gl-border-b-1 gl-rounded-top-base"
>
<gl-segmented-control <gl-segmented-control
:options="editorModes" :options="editorModes"
:checked="selectedEditorMode" :checked="selectedEditorMode"
@input="updateEditorMode" @input="updateEditorMode"
/> />
</gl-form-group> </div>
<div class="gl-display-flex gl-sm-flex-direction-column"> <div class="gl-display-flex gl-sm-flex-direction-column">
<section class="gl-w-full" :class="{ 'gl-p-5': shouldShowRuleEditor }"> <section class="gl-w-full gl-mr-7">
<div v-if="shouldShowRuleEditor" data-testid="rule-editor"> <div v-if="shouldShowRuleEditor" data-testid="rule-editor">
<slot name="rule-editor"></slot> <slot name="rule-editor"></slot>
</div> </div>
...@@ -153,7 +149,7 @@ export default { ...@@ -153,7 +149,7 @@ export default {
</section> </section>
<section <section
v-if="shouldShowRuleEditor" v-if="shouldShowRuleEditor"
class="gl-md-w-50p gl-md-max-w-30p gl-p-5 gl-border-l-gray-100 gl-border-l-1 gl-md-border-l-solid" class="gl-md-w-50p gl-md-max-w-30p gl-p-5 gl-bg-gray-10 gl-ml-11 gl-align-self-start"
data-testid="rule-editor-preview" data-testid="rule-editor-preview"
> >
<slot name="rule-editor-preview"></slot> <slot name="rule-editor-preview"></slot>
......
...@@ -27,7 +27,7 @@ export default { ...@@ -27,7 +27,7 @@ export default {
<div <div
v-if="policyDescription" v-if="policyDescription"
v-safe-html:[$options.safeHtmlConfig]="policyDescription" v-safe-html:[$options.safeHtmlConfig]="policyDescription"
class="gl-bg-white gl-rounded-base gl-py-3 gl-px-4 gl-border-1 gl-border-solid gl-border-gray-100" class="gl-bg-gray-10 gl-py-3 gl-px-4"
></div> ></div>
<div v-else> <div v-else>
<gl-alert variant="info" :dismissible="false"> <gl-alert variant="info" :dismissible="false">
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
exports[`PolicyActionPicker component renders policy action picker 1`] = ` exports[`PolicyActionPicker component renders policy action picker 1`] = `
<div <div
class="gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100 gl-rounded-base gl-px-5 gl-pt-5" class="gl-bg-gray-10 gl-px-5 gl-pt-5"
> >
<gl-form-stub <gl-form-stub
inline="" inline=""
......
import { GlEmptyState, GlToggle } from '@gitlab/ui'; import { GlEmptyState, GlFormCheckbox, GlFormGroup } from '@gitlab/ui';
import { EDITOR_MODE_YAML } from 'ee/threat_monitoring/components/policy_editor/constants'; import { EDITOR_MODE_YAML } from 'ee/threat_monitoring/components/policy_editor/constants';
import DimDisableContainer from 'ee/threat_monitoring/components/policy_editor/dim_disable_container.vue'; import DimDisableContainer from 'ee/threat_monitoring/components/policy_editor/dim_disable_container.vue';
import { import {
...@@ -65,7 +65,11 @@ describe('NetworkPolicyEditor component', () => { ...@@ -65,7 +65,11 @@ describe('NetworkPolicyEditor component', () => {
...provide, ...provide,
}, },
store, store,
stubs: { DimDisableContainer, PolicyYamlEditor: true, transition: stubTransition() }, stubs: {
DimDisableContainer,
PolicyYamlEditor: true,
transition: stubTransition(),
},
}); });
}; };
...@@ -82,7 +86,7 @@ describe('NetworkPolicyEditor component', () => { ...@@ -82,7 +86,7 @@ describe('NetworkPolicyEditor component', () => {
const findPolicyEditorLayout = () => wrapper.findComponent(PolicyEditorLayout); const findPolicyEditorLayout = () => wrapper.findComponent(PolicyEditorLayout);
const findCollapseToggle = () => const findCollapseToggle = () =>
wrapper.findByRole('button', { wrapper.findByRole('button', {
name: NetworkPolicyEditor.i18n.policyPreview, name: NetworkPolicyEditor.i18n.policySummary,
}); });
const modifyPolicyAlert = async ({ isAlertEnabled }) => { const modifyPolicyAlert = async ({ isAlertEnabled }) => {
...@@ -96,11 +100,12 @@ describe('NetworkPolicyEditor component', () => { ...@@ -96,11 +100,12 @@ describe('NetworkPolicyEditor component', () => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders toggle with label', () => { it('renders checkbox with label', () => {
factory(); factory();
const policyEnableToggle = findPolicyEnableContainer().findComponent(GlToggle); expect(findPolicyEnableContainer().findComponent(GlFormGroup).attributes('label')).toBe(
expect(policyEnableToggle.exists()).toBe(true); NetworkPolicyEditor.i18n.toggleLabel,
expect(policyEnableToggle.props('label')).toBe(NetworkPolicyEditor.i18n.toggleLabel); );
expect(findPolicyEnableContainer().findComponent(GlFormCheckbox).exists()).toBe(true);
}); });
it('disables the tooltip and enables the save button', () => { it('disables the tooltip and enables the save button', () => {
......
...@@ -5370,6 +5370,9 @@ msgstr "" ...@@ -5370,6 +5370,9 @@ msgstr ""
msgid "Based on" msgid "Based on"
msgstr "" msgstr ""
msgid "Basic information"
msgstr ""
msgid "Be careful. Changing the project's namespace can have unintended side effects." msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "" msgstr ""
...@@ -23550,9 +23553,6 @@ msgstr "" ...@@ -23550,9 +23553,6 @@ msgstr ""
msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first." msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
msgstr "" msgstr ""
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
msgid "NetworkPolicies|all DNS names" msgid "NetworkPolicies|all DNS names"
msgstr "" msgstr ""
...@@ -31681,10 +31681,10 @@ msgstr "" ...@@ -31681,10 +31681,10 @@ msgstr ""
msgid "SecurityOrchestration|Policy editor" msgid "SecurityOrchestration|Policy editor"
msgstr "" msgstr ""
msgid "SecurityOrchestration|Policy preview" msgid "SecurityOrchestration|Policy status"
msgstr "" msgstr ""
msgid "SecurityOrchestration|Policy status" msgid "SecurityOrchestration|Policy summary"
msgstr "" msgstr ""
msgid "SecurityOrchestration|Policy type" msgid "SecurityOrchestration|Policy type"
......
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