Skip to content

Commit

Permalink
Merge pull request #1444 from Vizzuality/MRXN23-321-disabled-solution…
Browse files Browse the repository at this point in the history
…s-nav-case

[fe]: Disable solutions when scenario have not ran an scenario [MRXN23-321]
  • Loading branch information
agnlez authored Aug 23, 2023
2 parents 3c4b7fa + ec4a4ed commit c292881
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 134 deletions.
69 changes: 27 additions & 42 deletions app/hoc/scenarios.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { QueryClient } from 'react-query';

import { NAVIGATION_TREE } from 'layout/project/navigation/constants';
import { Session } from 'next-auth';
import { getSession } from 'next-auth/react';
import { dehydrate } from 'react-query/hydration';

import { NAVIGATION_TREE } from 'layout/project/navigation/constants';
import { Project } from 'types/api/project';
import { Scenario } from 'types/api/scenario';
import { Solution } from 'types/api/solution';

import ROLES from 'services/roles';
import SCENARIOS from 'services/scenarios';
import USERS from 'services/users';

import { mergeDehydratedState } from './utils';

const fetchUser = (session: Session, queryClient) => {
const fetchUser = (session: Session, queryClient: QueryClient) => {
return queryClient.prefetchQuery('me', () =>
USERS.request({
method: 'GET',
Expand All @@ -31,7 +30,11 @@ const fetchUser = (session: Session, queryClient) => {
);
};

const fetchProjectUsers = (session: Session, queryClient, { pid }) => {
const fetchProjectUsers = (
session: Session,
queryClient: QueryClient,
{ pid }: { pid: Project['id'] }
) => {
return queryClient.prefetchQuery(['roles', pid], () =>
ROLES.request({
method: 'GET',
Expand All @@ -47,9 +50,13 @@ const fetchProjectUsers = (session: Session, queryClient, { pid }) => {
);
};

const fetchScenario = (session: Session, queryClient, { sid }) => {
return queryClient.prefetchQuery(['scenarios', sid], () =>
SCENARIOS.request({
const fetchScenario = (
session: Session,
queryClient: QueryClient,
{ sid }: { sid: Scenario['id'] }
) => {
return queryClient.prefetchQuery(['scenario', sid], () =>
SCENARIOS.request<{ data: Scenario }>({
method: 'GET',
url: `/${sid}`,
headers: {
Expand All @@ -61,23 +68,11 @@ const fetchScenario = (session: Session, queryClient, { sid }) => {
);
};

const fetchScenarioSolutions = (session: Session, { sid }: { sid: Scenario['id'] }) => {
return SCENARIOS.request<{ data: Solution[] }>({
method: 'GET',
url: `/${sid}/marxan/solutions`,
headers: {
Authorization: `Bearer ${session.accessToken}`,
},
params: {
'page[size]': 1,
'page[number]': 1,
},
}).then((response) => {
return response.data?.data;
});
};

const fetchScenarioLock = (session, queryClient, { sid }) => {
const fetchScenarioLock = (
session: Session,
queryClient: QueryClient,
{ sid }: { sid: Scenario['id'] }
) => {
return queryClient.prefetchQuery(['scenario-lock', sid], () =>
SCENARIOS.request({
method: 'GET',
Expand Down Expand Up @@ -117,7 +112,7 @@ export function withScenario(getServerSidePropsFunc?: Function) {
const queryClient = new QueryClient();

await fetchScenario(session, queryClient, { sid });
const scenario = queryClient.getQueryData<{ data: Scenario }>(['scenarios', sid]);
const scenario = queryClient.getQueryData<{ data: Scenario }>(['scenario', sid])?.data;

if (!scenario) {
return {
Expand Down Expand Up @@ -271,23 +266,13 @@ export function withSolutions(getServerSidePropsFunc?: Function) {
const { pid, tab, sid } = query as { pid: string; tab: string; sid: string };

const queryClient = new QueryClient();
const solutions = await fetchScenarioSolutions(session, { sid });
queryClient.setQueryData(
[
'all-solutions',
sid,
JSON.stringify({
disablePagination: false,
'page[size]': 1,
'page[number]': 1,
}),
],
{ data: solutions }
);

// ? if the scenarios has no solutions and the user is trying to access the solutions tab,

await fetchScenario(session, queryClient, { sid });
const scenario = queryClient.getQueryData<{ data: Scenario }>(['scenario', sid])?.data;

// ? if the scenario has not been ran at least once and the user tries to access the solutions tab,
// ? it will be redirected to the overview tab as the solutions menu should be disabled.
if (NAVIGATION_TREE.solutions.includes(tab) && !solutions.length) {
if (NAVIGATION_TREE.solutions.includes(tab) && !scenario.ranAtLeastOnce) {
return {
props: {},
redirect: {
Expand Down
39 changes: 20 additions & 19 deletions app/hooks/scenarios/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {

import { useRouter } from 'next/router';

import axios, { AxiosError } from 'axios';
import axios, { AxiosError, AxiosRequestConfig } from 'axios';
import { formatDistanceToNow } from 'date-fns';
import flatten from 'lodash/flatten';
import { useSession } from 'next-auth/react';
Expand All @@ -32,8 +32,6 @@ import UPLOADS from 'services/uploads';

import {
UseScenariosOptionsProps,
UseSaveScenarioProps,
SaveScenarioProps,
UseDeleteScenarioProps,
DeleteScenarioProps,
UseUploadScenarioCostSurfaceProps,
Expand All @@ -46,8 +44,6 @@ import {
UseUploadPAProps,
UseDuplicateScenarioProps,
DuplicateScenarioProps,
UseRunScenarioProps,
RunScenarioProps,
UseCancelRunScenarioProps,
CancelRunScenarioProps,
UseSaveScenarioCalibrationRangeProps,
Expand Down Expand Up @@ -481,6 +477,7 @@ export function useScenarios(pId, options: UseScenariosOptionsProps = {}) {

export function useScenario(id: Scenario['id']) {
const { data: session } = useSession();

return useQuery({
queryKey: ['scenario', id],
queryFn: async () =>
Expand All @@ -504,28 +501,30 @@ export function useSaveScenario({
requestConfig = {
method: 'POST',
},
}: UseSaveScenarioProps) {
}: {
requestConfig?: AxiosRequestConfig<{ data: Scenario }>;
}) {
const queryClient = useQueryClient();
const { data: session } = useSession();

const saveScenario = ({ id, data }: SaveScenarioProps) => {
return SCENARIOS.request({
const saveScenario = ({ id, data }: { id?: Scenario['id']; data: Record<string, unknown> }) => {
return SCENARIOS.request<{ data: Scenario }>({
url: id ? `/${id}` : '/',
data,
headers: {
Authorization: `Bearer ${session.accessToken}`,
},
...requestConfig,
});
}).then((response) => response.data);
};

return useMutation(saveScenario, {
onSuccess: async (data: any) => {
const { id, projectId } = data?.data?.data;
onSuccess: async ({ data }) => {
const { id, projectId } = data;

await queryClient.invalidateQueries(['scenarios', projectId]);
await queryClient.invalidateQueries(['scenario', id]);
queryClient.setQueryData(['scenario', id], data?.data?.data);
queryClient.setQueryData(['scenario', id], data);
},
});
}
Expand Down Expand Up @@ -813,11 +812,13 @@ export function useRunScenario({
requestConfig = {
method: 'POST',
},
}: UseRunScenarioProps) {
}: {
requestConfig?: AxiosRequestConfig;
}) {
const { data: session } = useSession();
const queryClient = useQueryClient();

const duplicateScenario = ({ id }: RunScenarioProps) => {
// Pending endpoint
const runScenario = ({ id }: { id: Scenario['id'] }) => {
return SCENARIOS.request({
url: `/${id}/marxan`,
headers: {
Expand All @@ -827,12 +828,12 @@ export function useRunScenario({
});
};

return useMutation(duplicateScenario, {
onSuccess: (data: any, variables, context) => {
console.info('Success', data, variables, context);
return useMutation(runScenario, {
onSuccess: async (data, variables) => {
const { id } = variables;
await queryClient.invalidateQueries(['scenario', id]);
},
onError: (error, variables, context) => {
// An error happened!
console.info('Error', error, variables, context);
},
});
Expand Down
17 changes: 0 additions & 17 deletions app/hooks/scenarios/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,6 @@ export interface UseScenariosOptionsProps {
filters?: Record<string, unknown>;
}

export interface UseSaveScenarioProps {
requestConfig?: AxiosRequestConfig;
}

export interface SaveScenarioProps {
id?: string;
data: any;
}

export interface UseDeleteScenarioProps {
requestConfig?: AxiosRequestConfig;
}
Expand Down Expand Up @@ -84,14 +75,6 @@ export interface DuplicateScenarioProps {
sid: string | string[];
}

export interface UseRunScenarioProps {
requestConfig?: AxiosRequestConfig;
}

export interface RunScenarioProps {
id: string | string[];
}

export interface UseCancelRunScenarioProps {
requestConfig?: AxiosRequestConfig;
}
Expand Down
4 changes: 2 additions & 2 deletions app/layout/header/title/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export const Title: React.FC<TitleProps> = () => {
},
},
{
onSuccess: ({ data: { data: s } }) => {
onSuccess: ({ data }) => {
addToast(
'save-scenario-name',
<>
Expand All @@ -122,7 +122,7 @@ export const Title: React.FC<TitleProps> = () => {
level: 'success',
}
);
console.info('Scenario name saved succesfully', s);
console.info('Scenario name saved succesfully', data);
},
onError: () => {
addToast(
Expand Down
13 changes: 7 additions & 6 deletions app/layout/project/navigation/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ export const NAVIGATION_TREE = {

export const MENU_COMMON_CLASSES = 'flex flex-col items-center space-y-2';
export const MENU_ITEM_COMMON_CLASSES =
'flex group rounded-xl cursor-pointer bg-transparent transition-colors first:mt-2';
'group flex cursor-pointer rounded-xl bg-transparent transition-colors first:mt-2';

export const MENU_ITEM_ACTIVE_CLASSES =
'group/active bg-primary-400 border-primary-400 hover:border-primary-400';
export const MENU_ITEM_DISABLED_CLASSES = 'pointer-events-none opacity-50';

export const ICONS_COMMON_CLASSES =
'h-5 w-5 text-gray-400 group-hover:text-white group-[.bg-primary-400]:text-gray-500';
'group/active border-primary-400 bg-primary-400 hover:border-primary-400';

export const MENU_ITEM_BUTTON_COMMON_CLASSES = 'flex p-[10px]';
export const MENU_ITEM_BUTTON_DISABLED_CLASSES = 'cursor-default opacity-50';

export const ICON_COMMON_CLASSES =
'h-5 w-5 text-gray-400 group-hover:text-white group-[.bg-primary-400]:text-gray-500';
export const ICON_DISABLED_CLASSES = 'group-hover:text-gray-400';
Loading

0 comments on commit c292881

Please sign in to comment.