Commit eedf5c44 authored by Savas Vedova's avatar Savas Vedova Committed by Brandon Labuschagne

Redesign new policy form

Implement the new design based on feedback received.

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