mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-28 00:17:12 +01:00
chore: improve release plan template form validation (#9371)
https://linear.app/unleash/issue/2-3321/improve-release-template-name-uniqueness-error-response-messages https://linear.app/unleash/issue/2-3285/milestone-name-uniqueness Slightly improves UX in our release plan template form validation. 
This commit is contained in:
parent
4e7ce65567
commit
192bd83fa6
@ -235,6 +235,7 @@ export const MilestoneCard = ({
|
|||||||
title: '',
|
title: '',
|
||||||
id: 'temp',
|
id: 'temp',
|
||||||
});
|
});
|
||||||
|
clearErrors();
|
||||||
};
|
};
|
||||||
|
|
||||||
const openAddUpdateStrategyForm = (
|
const openAddUpdateStrategyForm = (
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { useReleasePlanTemplates } from 'hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates';
|
||||||
|
import { useOptionalPathParam } from 'hooks/useOptionalPathParam';
|
||||||
import type { IReleasePlanMilestonePayload } from 'interfaces/releasePlans';
|
import type { IReleasePlanMilestonePayload } from 'interfaces/releasePlans';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
@ -14,6 +16,9 @@ export const useTemplateForm = (
|
|||||||
{ id: uuidv4(), name: 'Milestone 1', sortOrder: 0 },
|
{ id: uuidv4(), name: 'Milestone 1', sortOrder: 0 },
|
||||||
],
|
],
|
||||||
) => {
|
) => {
|
||||||
|
const templateId = useOptionalPathParam('templateId');
|
||||||
|
const { templates } = useReleasePlanTemplates();
|
||||||
|
|
||||||
const [name, setName] = useState(initialName);
|
const [name, setName] = useState(initialName);
|
||||||
const [description, setDescription] = useState(initialDescription);
|
const [description, setDescription] = useState(initialDescription);
|
||||||
const [milestones, setMilestones] = useState(initialMilestones);
|
const [milestones, setMilestones] = useState(initialMilestones);
|
||||||
@ -39,6 +44,19 @@ export const useTemplateForm = (
|
|||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
templates.some(
|
||||||
|
(template) =>
|
||||||
|
template.name === name && template.id !== templateId,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
setErrors((prev) => ({
|
||||||
|
...prev,
|
||||||
|
name: 'A template with this name already exists.',
|
||||||
|
}));
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (milestones.length === 0) {
|
if (milestones.length === 0) {
|
||||||
setErrors((prev) => ({
|
setErrors((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
@ -47,42 +65,31 @@ export const useTemplateForm = (
|
|||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const milestoneNames = milestones.filter(
|
const errors: Record<string, string> = {};
|
||||||
(m) => !m.name || m.name.length === 0,
|
const nameSet = new Set();
|
||||||
);
|
milestones.forEach((m) => {
|
||||||
if (milestoneNames && milestoneNames.length > 0) {
|
if (!m.name || m.name.length === 0) {
|
||||||
setErrors((prev) => ({
|
errors[m.id] = 'Milestone must have a valid name.';
|
||||||
...prev,
|
errors[`${m.id}_name`] = 'Milestone must have a valid name.';
|
||||||
...Object.assign(
|
}
|
||||||
{},
|
|
||||||
...milestoneNames.map((mst) => ({
|
|
||||||
[mst.id]: 'Milestone must have a valid name.',
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
...Object.assign(
|
|
||||||
{},
|
|
||||||
...milestoneNames.map((mst) => ({
|
|
||||||
[`${mst.id}_name`]: 'Milestone must have a valid name.',
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
}));
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emptyMilestones = milestones.filter(
|
if (!m.strategies || m.strategies.length === 0) {
|
||||||
(m) => !m.strategies || m.strategies.length === 0,
|
errors[m.id] = 'Milestone must have at least one strategy.';
|
||||||
);
|
}
|
||||||
if (emptyMilestones && emptyMilestones.length > 0) {
|
|
||||||
|
if (nameSet.has(m.name)) {
|
||||||
|
errors[m.id] = 'Milestone names must be unique.';
|
||||||
|
} else if (m.name) {
|
||||||
|
nameSet.add(m.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Object.keys(errors).length > 0) {
|
||||||
setErrors((prev) => ({
|
setErrors((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
|
...errors,
|
||||||
milestones:
|
milestones:
|
||||||
'All milestones must have at least one strategy each.',
|
'All milestones must have unique names and at least one strategy each.',
|
||||||
...Object.assign(
|
|
||||||
{},
|
|
||||||
...emptyMilestones.map((mst) => ({
|
|
||||||
[mst.id]: 'Milestone must have at least one strategy.',
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
}));
|
}));
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user