Commit a4e55558 authored by Brandon Labuschagne's avatar Brandon Labuschagne Committed by Martin Wortschack

Rename Segments to Groups

This is a change being applied to the devops
adoption feature in order to avoid introducing
the new concept of segments.
parent 16fb5b0e
<script>
import {
GlFormGroup,
GlFormInput,
GlFormCheckboxTree,
GlModal,
GlSprintf,
GlAlert,
GlIcon,
} from '@gitlab/ui';
import { getIdFromGraphQLId, convertToGraphQLIds, TYPE_GROUP } from '~/graphql_shared/utils';
import { GlFormGroup, GlFormInput, GlFormRadioGroup, GlModal, GlAlert, GlIcon } from '@gitlab/ui';
import { getIdFromGraphQLId, convertToGraphQLId, TYPE_GROUP } from '~/graphql_shared/utils';
import * as Sentry from '~/sentry/wrapper';
import createDevopsAdoptionSegmentMutation from '../graphql/mutations/create_devops_adoption_segment.mutation.graphql';
import updateDevopsAdoptionSegmentMutation from '../graphql/mutations/update_devops_adoption_segment.mutation.graphql';
......@@ -21,8 +13,7 @@ export default {
GlModal,
GlFormGroup,
GlFormInput,
GlFormCheckboxTree,
GlSprintf,
GlFormRadioGroup,
GlAlert,
GlIcon,
},
......@@ -41,7 +32,7 @@ export default {
data() {
return {
name: this.segment?.name || '',
checkboxValues: this.segment ? this.checkboxValuesFromSegment() : [],
selectedGroupId: this.segment ? this.groupIdFromSegment() : null,
filter: '',
loading: false,
errors: [],
......@@ -49,7 +40,7 @@ export default {
},
computed: {
checkboxOptions() {
return this.groups.map(({ id, full_name }) => ({ label: full_name, value: id }));
return this.groups.map(({ id, full_name }) => ({ text: full_name, value: id }));
},
cancelOptions() {
return {
......@@ -76,7 +67,7 @@ export default {
};
},
canSubmit() {
return this.name.length && this.checkboxValues.length;
return this.name.length && Boolean(this.selectedGroupId);
},
displayError() {
return this.errors[0];
......@@ -87,7 +78,7 @@ export default {
filteredOptions() {
return this.filter
? this.checkboxOptions.filter((option) =>
option.label.toLowerCase().includes(this.filter.toLowerCase()),
option.text.toLowerCase().includes(this.filter.toLowerCase()),
)
: this.checkboxOptions;
},
......@@ -104,7 +95,7 @@ export default {
mutation: createDevopsAdoptionSegmentMutation,
variables: {
name: this.name,
groupIds: convertToGraphQLIds(TYPE_GROUP, this.checkboxValues),
groupIds: convertToGraphQLId(TYPE_GROUP, this.selectedGroupId),
},
update: (store, { data }) => {
const {
......@@ -140,7 +131,7 @@ export default {
variables: {
id: this.segment.id,
name: this.name,
groupIds: convertToGraphQLIds(TYPE_GROUP, this.checkboxValues),
groupIds: convertToGraphQLId(TYPE_GROUP, this.selectedGroupId),
},
});
......@@ -162,12 +153,12 @@ export default {
closeModal() {
this.$refs.modal.hide();
},
checkboxValuesFromSegment() {
return this.segment.groups.map(({ id }) => getIdFromGraphQLId(id));
groupIdFromSegment() {
return this.segment.groups.map(({ id }) => getIdFromGraphQLId(id))[0];
},
resetForm() {
this.name = this.segment?.name || '';
this.checkboxValues = this.segment ? this.checkboxValuesFromSegment() : [];
this.selectedGroupId = this.segment ? this.groupIdFromSegment() : null;
this.filter = '';
},
},
......@@ -212,10 +203,10 @@ export default {
/>
</gl-form-group>
<gl-form-group class="gl-mb-0">
<gl-form-checkbox-tree
<gl-form-radio-group
v-if="filteredOptions.length"
:key="filteredOptions.length"
v-model="checkboxValues"
v-model="selectedGroupId"
data-testid="groups"
:options="filteredOptions"
:hide-toggle-all="true"
......@@ -225,21 +216,6 @@ export default {
<gl-alert v-else variant="info" :dismissible="false" data-testid="filter-warning">
{{ $options.i18n.noResults }}
</gl-alert>
<div class="gl-text-gray-400" data-testid="groupsHelperText">
<gl-sprintf
:message="
n__(
$options.i18n.selectedGroupsTextSingular,
$options.i18n.selectedGroupsTextPlural,
checkboxValues.length,
)
"
>
<template #selectedCount>
{{ checkboxValues.length }}
</template>
</gl-sprintf>
</div>
</gl-form-group>
</gl-modal>
</template>
......@@ -21,45 +21,45 @@ export const DEVOPS_ADOPTION_STRINGS = {
'DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again.',
),
[DEVOPS_ADOPTION_ERROR_KEYS.segments]: s__(
'DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again.',
'DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again.',
),
tableHeader: {
text: s__(
'DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}.',
),
button: s__('DevopsAdoption|Add new segment'),
buttonTooltip: sprintf(s__('DevopsAdoption|Maximum %{maxSegments} segments allowed'), {
button: s__('DevopsAdoption|Add Group'),
buttonTooltip: sprintf(s__('DevopsAdoption|Maximum %{maxSegments} groups allowed'), {
maxSegments: MAX_SEGMENTS,
}),
},
},
emptyState: {
title: s__('DevopsAdoption|Add a segment to get started'),
title: s__('DevopsAdoption|Add a group to get started'),
description: s__(
'DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team.',
'DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin.',
),
button: s__('DevopsAdoption|Add new segment'),
button: s__('DevopsAdoption|Add Group'),
},
modal: {
addingTitle: s__('DevopsAdoption|New segment'),
editingTitle: s__('DevopsAdoption|Edit segment'),
addingButton: s__('DevopsAdoption|Create new segment'),
addingTitle: s__('DevopsAdoption|Add Group'),
editingTitle: s__('DevopsAdoption|Edit Group'),
addingButton: s__('DevopsAdoption|Add Group'),
editingButton: s__('DevopsAdoption|Save changes'),
cancel: __('Cancel'),
namePlaceholder: s__('DevopsAdoption|My segment'),
namePlaceholder: s__('DevopsAdoption|My group'),
filterPlaceholder: s__('DevopsAdoption|Filter by name'),
nameLabel: s__('DevopsAdoption|Name'),
selectedGroupsTextSingular: s__('DevopsAdoption|%{selectedCount} group selected (20 max)'),
selectedGroupsTextPlural: s__('DevopsAdoption|%{selectedCount} groups selected (20 max)'),
error: s__('DevopsAdoption|An error occured while saving the segment. Please try again.'),
selectedGroupsTextSingular: s__('DevopsAdoption|%{selectedCount} group selected'),
selectedGroupsTextPlural: s__('DevopsAdoption|%{selectedCount} groups selected'),
error: s__('DevopsAdoption|An error occured while saving the group. Please try again.'),
noResults: s__('DevopsAdoption|No filter results.'),
},
table: {
editButton: s__('DevopsAdoption|Edit segment'),
deleteButton: s__('DevopsAdoption|Delete segment'),
editButton: s__('DevopsAdoption|Edit Group'),
deleteButton: s__('DevopsAdoption|Delete Group'),
headers: {
name: {
label: s__('DevopsAdoption|Segment'),
label: __('Group'),
},
issueOpened: {
label: s__('DevopsAdoption|Issues'),
......@@ -90,14 +90,14 @@ export const DEVOPS_ADOPTION_STRINGS = {
tooltip: s__('DevopsAdoption|At least 1 security scan of any type run in pipeline'),
},
},
pendingTooltip: s__('DevopsAdoption|Segment data pending until the start of next month'),
pendingTooltip: s__('DevopsAdoption|Group data pending until the start of next month'),
},
deleteModal: {
title: s__('DevopsAdoption|Confirm delete segment'),
title: s__('DevopsAdoption|Confirm delete Group'),
confirmationMessage: s__('DevopsAdoption|Are you sure that you would like to delete %{name}?'),
cancel: __('Cancel'),
confirm: s__('DevopsAdoption|Delete segment'),
error: s__('DevopsAdoption|An error occured while deleting the segment. Please try again.'),
confirm: s__('DevopsAdoption|Delete Group'),
error: s__('DevopsAdoption|An error occured while deleting the group. Please try again.'),
},
tableCell: {
trueText: s__('DevopsAdoption|Adopted'),
......
---
title: Resolve Rename Segment to Group
merge_request: 51574
author:
type: changed
......@@ -406,7 +406,7 @@ describe('DevopsAdoptionApp', () => {
const tooltip = getBinding(segmentButtonWrapper.element, 'gl-tooltip');
expect(tooltip).toBeDefined();
expect(tooltip.value).toBe('Maximum 30 segments allowed');
expect(tooltip.value).toBe('Maximum 30 groups allowed');
});
});
});
......
import { ApolloMutation } from 'vue-apollo';
import { shallowMount } from '@vue/test-utils';
import { GlModal, GlFormInput, GlSprintf, GlAlert, GlIcon } from '@gitlab/ui';
import { getByText } from '@testing-library/dom';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import DevopsAdoptionSegmentModal from 'ee/admin/dev_ops_report/components/devops_adoption_segment_modal.vue';
......@@ -70,8 +69,6 @@ describe('DevopsAdoptionSegmentModal', () => {
const actionButtonLoadingState = () => findModal().props('actionPrimary').attributes[0].loading;
const findAlert = () => findModal().find(GlAlert);
const assertHelperText = (text) => expect(getByText(wrapper.element, text)).not.toBeNull();
afterEach(() => {
wrapper.destroy();
wrapper = null;
......@@ -91,7 +88,7 @@ describe('DevopsAdoptionSegmentModal', () => {
const isCorrectShape = (option) => {
const keys = Object.keys(option);
return keys.includes('label') && keys.includes('value');
return keys.includes('text') && keys.includes('value');
};
it('displays the name field', () => {
......@@ -101,7 +98,7 @@ describe('DevopsAdoptionSegmentModal', () => {
expect(name.find(GlFormInput).exists()).toBe(true);
});
it('contains the checkbox tree component', () => {
it('contains the radio group component', () => {
const checkboxes = findByTestId('groups');
expect(checkboxes.exists()).toBe(true);
......@@ -112,28 +109,6 @@ describe('DevopsAdoptionSegmentModal', () => {
expect(options.every(isCorrectShape)).toBe(true);
});
describe('selected groups helper text', () => {
it('displays the plural text when 0 groups are selected', () => {
assertHelperText('0 groups selected (20 max)');
});
it('dispalys the singular text when only 1 group is selected', async () => {
wrapper.setData({ checkboxValues: [groupNodes[0]] });
await nextTick();
assertHelperText('1 group selected (20 max)');
});
it('displays the plural text when multiple groups are selected', async () => {
wrapper.setData({ checkboxValues: groupNodes });
await nextTick();
assertHelperText('2 groups selected (20 max)');
});
});
describe('filtering', () => {
describe('filter input field', () => {
it('contains the filter input', () => {
......@@ -198,17 +173,17 @@ describe('DevopsAdoptionSegmentModal', () => {
});
it.each`
checkboxValues | name | disabled | values | state
${[]} | ${''} | ${true} | ${'checkbox and name'} | ${'disables'}
${[1]} | ${''} | ${true} | ${'checkbox'} | ${'disables'}
${[]} | ${segmentName} | ${true} | ${'name'} | ${'disables'}
${[1]} | ${segmentName} | ${false} | ${'nothing'} | ${'enables'}
selectedGroupId | name | disabled | values | state
${null} | ${''} | ${true} | ${'checkbox and name'} | ${'disables'}
${1} | ${''} | ${true} | ${'checkbox'} | ${'disables'}
${null} | ${segmentName} | ${true} | ${'name'} | ${'disables'}
${1} | ${segmentName} | ${false} | ${'nothing'} | ${'enables'}
`(
'$state the primary action if $values is missing',
async ({ checkboxValues, name, disabled }) => {
async ({ selectedGroupId, name, disabled }) => {
createComponent();
wrapper.setData({ checkboxValues, name });
wrapper.setData({ selectedGroupId, name });
await nextTick();
......@@ -218,7 +193,7 @@ describe('DevopsAdoptionSegmentModal', () => {
describe.each`
action | segment | additionalData
${'creating a new segment'} | ${null} | ${{ checkboxValues: groupIds, name: segmentName }}
${'creating a new segment'} | ${null} | ${{ selectedGroupId: groupIds[0], name: segmentName }}
${'updating an existing segment'} | ${devopsAdoptionSegmentsData.nodes[0]} | ${{}}
`('handles the form submission correctly when $action', ({ segment, additionalData }) => {
describe('submitting the form', () => {
......@@ -280,11 +255,11 @@ describe('DevopsAdoptionSegmentModal', () => {
const variables = segment
? {
id: segment.id,
groupIds: [groupGids[0]],
groupIds: groupGids[0],
name: segment.name,
}
: {
groupIds: groupGids,
groupIds: groupGids[0],
name: segmentName,
};
......@@ -301,10 +276,10 @@ describe('DevopsAdoptionSegmentModal', () => {
it('resets the form fields', async () => {
const name = segment ? 'Segment 1' : '';
const checkboxValues = segment ? [1] : [];
const selectedGroupId = segment ? 1 : null;
expect(wrapper.vm.name).toBe(name);
expect(wrapper.vm.checkboxValues).toEqual(checkboxValues);
expect(wrapper.vm.selectedGroupId).toEqual(selectedGroupId);
expect(wrapper.vm.filter).toBe('');
});
});
......@@ -319,6 +294,8 @@ describe('DevopsAdoptionSegmentModal', () => {
async ({ mutationSpy, message }) => {
createComponent({ mutationMock: mutationSpy, segment });
wrapper.setData(additionalData);
findModal().vm.$emit('primary', mockEvent);
await waitForPromises();
......@@ -336,6 +313,8 @@ describe('DevopsAdoptionSegmentModal', () => {
createComponent({ mutationMock: mutateWithErrors, segment });
wrapper.setData(additionalData);
findModal().vm.$emit('primary', mockEvent);
await waitForPromises();
......
......@@ -119,7 +119,7 @@ describe('DevopsAdoptionTable', () => {
const tooltip = getBinding(icon.element, 'gl-tooltip');
expect(tooltip).toBeDefined();
expect(tooltip.value).toBe('Segment data pending until the start of next month');
expect(tooltip.value).toBe('Group data pending until the start of next month');
});
});
});
......
......@@ -21,8 +21,8 @@ export const groupNodes = [
];
export const groupNodeLabelValues = [
{ label: 'Foo', value: '1' },
{ label: 'Bar', value: '2' },
{ text: 'Foo', value: '1' },
{ text: 'Bar', value: '2' },
];
export const groupIds = ['1', '2'];
......@@ -85,7 +85,7 @@ export const devopsAdoptionSegmentsDataEmpty = {
export const devopsAdoptionTableHeaders = [
{
index: 0,
label: 'Segment',
label: 'Group',
tooltip: null,
},
{
......@@ -132,9 +132,9 @@ export const devopsAdoptionTableHeaders = [
export const segmentName = 'Foooo';
export const genericErrorMessage = 'An error occured while saving the segment. Please try again.';
export const genericErrorMessage = 'An error occured while saving the group. Please try again.';
export const dataErrorMessage = 'Name already taken.';
export const genericDeleteErrorMessage =
'An error occured while deleting the segment. Please try again.';
'An error occured while deleting the group. Please try again.';
......@@ -9931,25 +9931,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
msgid "DevopsAdoption|Add a segment to get started"
msgid "DevopsAdoption|Add Group"
msgstr ""
msgid "DevopsAdoption|Add new segment"
msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
......@@ -9976,22 +9976,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
msgid "DevopsAdoption|Confirm delete segment"
msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
msgid "DevopsAdoption|Create new segment"
msgstr ""
msgid "DevopsAdoption|Delete segment"
msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
msgid "DevopsAdoption|Edit segment"
msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
......@@ -10000,24 +9997,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
msgid "DevopsAdoption|Group data pending until the start of next month"
msgstr ""
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
msgid "DevopsAdoption|My segment"
msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
msgid "DevopsAdoption|New segment"
msgstr ""
msgid "DevopsAdoption|No filter results."
msgstr ""
......@@ -10039,18 +10036,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
msgid "DevopsAdoption|Segment"
msgstr ""
msgid "DevopsAdoption|Segment data pending until the start of next month"
msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
msgstr ""
msgid "DevopsReport|Adoption"
msgstr ""
......
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