Skip to content

Commit ea010c4

Browse files
Merge pull request #783 from zhuje/ou1236-loading-kebab
OU-1236: Kebab icon should be disable while "Checking permissions" is happening
2 parents fca06de + fda27f7 commit ea010c4

3 files changed

Lines changed: 67 additions & 10 deletions

File tree

web/src/components/dashboards/perses/dashboard-action-modals.tsx

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,8 @@ export const DuplicateActionModal = ({ dashboard, isOpen, onClose }: ActionModal
208208
return allProjects[0] || '';
209209
}, [dashboard, editableProjects, allProjects]);
210210

211-
const { schema: validationSchema } = useDashboardValidationSchema(defaultProject, t);
212-
213211
const form = useForm<CreateDashboardValidationType>({
214-
resolver: validationSchema
215-
? zodResolver(validationSchema)
216-
: zodResolver(createDashboardDialogValidationSchema(t)),
212+
resolver: zodResolver(createDashboardDialogValidationSchema(t)),
217213
mode: 'onBlur',
218214
defaultValues: {
219215
projectName: defaultProject,
@@ -222,6 +218,12 @@ export const DuplicateActionModal = ({ dashboard, isOpen, onClose }: ActionModal
222218
});
223219

224220
const selectedProjectName = form.watch('projectName');
221+
const dashboardName = form.watch('dashboardName');
222+
223+
const { schema: dynamicValidationSchema, isSchemaLoading } = useDashboardValidationSchema(
224+
selectedProjectName,
225+
t,
226+
);
225227

226228
const projectOptions = useMemo<TypeaheadSelectOption[]>(() => {
227229
if (!editableProjects) {
@@ -236,6 +238,48 @@ export const DuplicateActionModal = ({ dashboard, isOpen, onClose }: ActionModal
236238

237239
const createDashboardMutation = useCreateDashboardMutation();
238240

241+
React.useEffect(() => {
242+
const isPerseProject = persesProjects?.some(
243+
(project) => project.metadata?.name === selectedProjectName,
244+
);
245+
246+
if (dynamicValidationSchema && selectedProjectName && !isSchemaLoading && isPerseProject) {
247+
const currentValues = form.getValues();
248+
const result = dynamicValidationSchema.safeParse(currentValues);
249+
250+
if (!result.success) {
251+
const hasDashboardIssue = result.error.issues.some(
252+
(issue) => issue.path[0] === 'dashboardName',
253+
);
254+
255+
if (hasDashboardIssue) {
256+
result.error.issues.forEach((issue) => {
257+
if (issue.path[0] === 'dashboardName') {
258+
form.setError('dashboardName', {
259+
type: 'validate',
260+
message: issue.message,
261+
});
262+
}
263+
});
264+
} else {
265+
form.clearErrors('dashboardName');
266+
}
267+
} else {
268+
form.clearErrors('dashboardName');
269+
}
270+
} else if (!isPerseProject && selectedProjectName) {
271+
// Clear any existing validation errors for non-Perses projects
272+
form.clearErrors('dashboardName');
273+
}
274+
}, [
275+
selectedProjectName,
276+
dynamicValidationSchema,
277+
form,
278+
dashboardName,
279+
isSchemaLoading,
280+
persesProjects,
281+
]);
282+
239283
React.useEffect(() => {
240284
if (isOpen && dashboard && editableProjects?.length > 0 && defaultProject) {
241285
form.reset({
@@ -435,9 +479,10 @@ export const DuplicateActionModal = ({ dashboard, isOpen, onClose }: ActionModal
435479
!(form.watch('dashboardName') || '')?.trim() ||
436480
!(form.watch('projectName') || '')?.trim() ||
437481
!hasEditableProject ||
482+
isSchemaLoading ||
438483
createDashboardMutation.isPending
439484
}
440-
isLoading={createDashboardMutation.isPending}
485+
isLoading={createDashboardMutation.isPending || isSchemaLoading}
441486
>
442487
{t('Duplicate')}
443488
</Button>

web/src/components/dashboards/perses/dashboard-action-validations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function useDashboardValidationSchema(
6060
if (!dashboards?.length)
6161
return {
6262
schema: createDashboardDialogValidationSchema(t),
63-
isSchemaLoading: true,
63+
isSchemaLoading: false,
6464
hasSchemaError: false,
6565
};
6666

@@ -87,6 +87,6 @@ export function useDashboardValidationSchema(
8787
}),
8888
);
8989

90-
return { schema: refinedSchema, isSchemaLoading: true, hasSchemaError: false };
90+
return { schema: refinedSchema, isSchemaLoading: false, hasSchemaError: false };
9191
}, [dashboards, isDashboardsLoading, isError, t]);
9292
}

web/src/components/dashboards/perses/dashboard-list.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
DuplicateActionModal,
3737
RenameActionModal,
3838
} from './dashboard-action-modals';
39+
import { useEditableProjects } from './hooks/useEditableProjects';
3940
const perPageOptions = [
4041
{ title: '10', value: 10 },
4142
{ title: '20', value: 20 },
@@ -58,7 +59,9 @@ const DashboardActionsCell = React.memo(
5859
emptyActions: any[];
5960
}) => {
6061
const { t } = useTranslation(process.env.I18N_NAMESPACE);
61-
const { canEdit, loading } = usePersesEditPermissions(project);
62+
63+
const { permissionsLoading } = useEditableProjects();
64+
const { canEdit } = usePersesEditPermissions(project);
6265
const disabled = !canEdit;
6366

6467
const rowSpecificActions = useMemo(
@@ -79,7 +82,7 @@ const DashboardActionsCell = React.memo(
7982
[dashboard, onRename, onDuplicate, onDelete, t],
8083
);
8184

82-
if (disabled || loading) {
85+
if (disabled) {
8386
return (
8487
<Tooltip content={t("You don't have permissions for dashboard actions")}>
8588
<div>
@@ -88,6 +91,15 @@ const DashboardActionsCell = React.memo(
8891
</Tooltip>
8992
);
9093
}
94+
if (permissionsLoading) {
95+
return (
96+
<Tooltip content={t('Checking permissions...')}>
97+
<div>
98+
<ActionsColumn items={emptyActions} isDisabled={true} />
99+
</div>
100+
</Tooltip>
101+
);
102+
}
91103

92104
return <ActionsColumn items={rowSpecificActions} isDisabled={false} />;
93105
},

0 commit comments

Comments
 (0)