Skip to content

Commit

Permalink
[frontend] fixes bulk operations not refreshing the datatables correc…
Browse files Browse the repository at this point in the history
…tly (#2216)

Co-authored-by: Guillaume Paris <[email protected]>
  • Loading branch information
impolitepanda and guillaumejparis authored Jan 15, 2025
1 parent d5401bf commit b11f516
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 42 deletions.
20 changes: 19 additions & 1 deletion openbas-front/src/actions/Inject.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { bulkDeleteReferential, delReferential, getReferential, postReferential, putReferential } from '../utils/Action';
import {
bulkDeleteReferential,
delReferential,
getReferential,
postReferential,
putReferential,
simpleDelCall,
simplePutCall,
} from '../utils/Action';
import * as schema from './Schema';

// -- INJECTS --
Expand All @@ -13,11 +21,21 @@ export const bulkDeleteInjects = data => (dispatch) => {
return bulkDeleteReferential(uri, 'injects', data)(dispatch);
};

export const bulkDeleteInjectsSimple = (data) => {
const uri = `/api/injects`;
return simpleDelCall(uri, data);
};

export const bulkUpdateInject = data => (dispatch) => {
const uri = `/api/injects`;
return putReferential(schema.inject, uri, data)(dispatch);
};

export const bulkUpdateInjectSimple = (data) => {
const uri = `/api/injects`;
return simplePutCall(uri, data);
};

// -- EXERCISES --

export const fetchExerciseInjects = exerciseId => (dispatch) => {
Expand Down
12 changes: 3 additions & 9 deletions openbas-front/src/admin/components/common/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,7 @@ export type TeamContextType = {
export type InjectContextType = {
searchInjects: (input: SearchPaginationInput) => Promise<{ data: Page<InjectOutputType> }>;
onAddInject: (inject: Inject) => Promise<{ result: string; entities: { injects: Record<string, InjectStore> } }>;
onBulkUpdateInject: (param: InjectBulkUpdateInputs) => Promise<{
result: string;
entities: { injects: Record<string, InjectStore> };
}>;
onBulkUpdateInject: (param: InjectBulkUpdateInputs) => Promise<Inject[] | void>;
onUpdateInject: (injectId: Inject['inject_id'], inject: Inject) => Promise<{ result: string; entities: { injects: Record<string, InjectStore> } }>;
onUpdateInjectTrigger?: (injectId: Inject['inject_id']) => Promise<{ result: string; entities: { injects: Record<string, InjectStore> } }>;
onUpdateInjectActivation: (injectId: Inject['inject_id'], injectEnabled: { inject_enabled: boolean }) => Promise<{
Expand Down Expand Up @@ -203,11 +200,8 @@ export const InjectContext = createContext<InjectContextType>({
onAddInject(_inject: Inject): Promise<{ result: string; entities: { injects: Record<string, InjectStore> } }> {
return Promise.resolve({ result: '', entities: { injects: {} } });
},
onBulkUpdateInject(_param: InjectBulkUpdateInputs): Promise<{
result: string;
entities: { injects: Record<string, InjectStore> };
}> {
return Promise.resolve({ result: '', entities: { injects: {} } });
onBulkUpdateInject(_param: InjectBulkUpdateInputs): Promise<Inject[] | void> {
return Promise.resolve([]);
},
onUpdateInject(_injectId: Inject['inject_id'], _inject: Inject): Promise<{ result: string; entities: { injects: Record<string, InjectStore> } }> {
return Promise.resolve({ result: '', entities: { injects: {} } });
Expand Down
28 changes: 22 additions & 6 deletions openbas-front/src/admin/components/common/injects/Injects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useQueryableWithLocalStorage } from '../../../../components/common/quer
import { useFormatter } from '../../../../components/i18n';
import ItemBoolean from '../../../../components/ItemBoolean';
import ItemTags from '../../../../components/ItemTags';
import Loader from '../../../../components/Loader';
import PlatformIcon from '../../../../components/PlatformIcon';
import type {
Article,
Expand Down Expand Up @@ -250,6 +251,8 @@ const Injects: FunctionComponent<Props> = ({

// Injects
const [injects, setInjects] = useState<InjectOutputType[]>([]);
// Bulk loading indcator for tests and delete
const [isBulkLoading, setIsBulkLoading] = useState<boolean>(false);
const [selectedInjectId, setSelectedInjectId] = useState<string | null>(null);
const [reloadInjectCount, setReloadInjectCount] = useState(0);

Expand All @@ -264,13 +267,17 @@ const Injects: FunctionComponent<Props> = ({

const onUpdate = (result: { result: string; entities: { injects: Record<string, InjectStore> } }) => {
if (result.entities) {
const updated = result.entities.injects[result.result];
setInjects(injects.map((i) => {
return (i.inject_id !== updated.inject_id ? i as InjectOutputType : (updated as InjectOutputType));
}));
const updatedResults = result.entities.injects[result.result];
setInjects(injects.map(i => i.inject_id !== updatedResults.inject_id ? i : updatedResults as InjectOutputType));
}
};

const onBulkUpdate = (updatedResults: Inject[]) => {
setInjects(injects.map((originalInject) => {
return updatedResults.find(updatedInject => updatedInject.inject_id === originalInject.inject_id) as unknown as InjectOutputType || originalInject;
}));
};

const onDelete = (result: string) => {
if (result) {
setInjects(injects.filter(i => (i.inject_id !== result)));
Expand Down Expand Up @@ -420,12 +427,13 @@ const Injects: FunctionComponent<Props> = ({
simulation_or_scenario_id: exerciseOrScenarioId,
update_operations: operationsToPerform,
})
.then((result: { result: string; entities: { injects: Record<string, InjectStore> } }) => {
onUpdate(result);
.then((result) => {
if (result) onBulkUpdate(result);
});
};

const bulkDeleteInjects = () => {
setIsBulkLoading(true);
const deleteIds = injectsToProcess.map((inject: InjectOutputType) => inject.inject_id);
const ignoreIds = injectsToIgnore.map((inject: InjectOutputType) => inject.inject_id);
injectContext.onBulkDeleteInjects({
Expand All @@ -440,10 +448,13 @@ const Injects: FunctionComponent<Props> = ({
const deletedIds = result.map(inject => inject.inject_id);
setInjects(newNumbers !== 0 ? injects.filter(inject => !deletedIds.includes(inject.inject_id)) : []);
queryableHelpers.paginationHelpers.handleChangeTotalElements(newNumbers);
}).finally(() => {
setIsBulkLoading(false);
});
};

const massTestInjects = () => {
setIsBulkLoading(true);
const testIds = injectsToProcess.map((inject: InjectOutputType) => inject.inject_id);
const ignoreIds = injectsToIgnore.map((inject: InjectOutputType) => inject.inject_id);
injectContext.bulkTestInjects({
Expand All @@ -461,6 +472,8 @@ const Injects: FunctionComponent<Props> = ({
itsDedicatedPage: <Link to={`${result.uri}`}>{t('its dedicated page')}</Link>,
}));
}
}).finally(() => {
setIsBulkLoading(false);
});
};

Expand All @@ -471,6 +484,9 @@ const Injects: FunctionComponent<Props> = ({

const atLeastOneValidInject = injects.some(inject => !inject.inject_injector_contract?.injector_contract_content_parsed);

if (isBulkLoading) {
return <Loader />;
}
return (
<>
<PaginationComponentV2
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
addInjectForScenario,
bulkDeleteInjects,
bulkUpdateInject,
bulkDeleteInjectsSimple,
bulkUpdateInjectSimple,
deleteInjectScenario,
fetchScenarioInjects,
updateInjectActivationForScenario,
Expand Down Expand Up @@ -38,11 +38,8 @@ const injectContextForScenario = (scenario: Scenario) => {
onAddInject(inject: Inject): Promise<{ result: string; entities: { injects: Record<string, InjectStore> } }> {
return dispatch(addInjectForScenario(scenario.scenario_id, inject));
},
onBulkUpdateInject(param: InjectBulkUpdateInputs): Promise<{
result: string;
entities: { injects: Record<string, InjectStore> };
}> {
return dispatch(bulkUpdateInject(param));
onBulkUpdateInject(param: InjectBulkUpdateInputs): Promise<Inject[] | void> {
return bulkUpdateInjectSimple(param).then((result: { data: Inject[] }) => result?.data);
},
onUpdateInject(injectId: Inject['inject_id'], inject: Inject): Promise<{ result: string; entities: { injects: Record<string, InjectStore> } }> {
return dispatch(updateInjectForScenario(scenario.scenario_id, injectId, inject));
Expand All @@ -68,7 +65,7 @@ const injectContextForScenario = (scenario: Scenario) => {
return dryImportXlsForScenario(scenario.scenario_id, importId, input).then(result => result.data);
},
onBulkDeleteInjects(param: InjectBulkProcessingInput): Promise<Inject[]> {
return dispatch(bulkDeleteInjects(param));
return bulkDeleteInjectsSimple(param).then((result: { data: Inject[] }) => result?.data);
},
bulkTestInjects(param: InjectBulkProcessingInput): Promise<{ uri: string; data: InjectTestStatus[] }> {
return bulkTestInjects(param).then(result => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { fetchExercise, fetchExerciseTeams } from '../../../../actions/Exercise'
import { dryImportXlsForExercise, importXlsForExercise } from '../../../../actions/exercises/exercise-action';
import {
addInjectForExercise,
bulkDeleteInjects,
bulkUpdateInject,
bulkDeleteInjectsSimple,
bulkUpdateInjectSimple,
deleteInjectForExercise,
fetchExerciseInjects,
injectDone,
Expand Down Expand Up @@ -36,12 +36,8 @@ const injectContextForExercise = (exercise: Exercise) => {
onAddInject(inject: Inject): Promise<{ result: string; entities: { injects: Record<string, InjectStore> } }> {
return dispatch(addInjectForExercise(exercise.exercise_id, inject));
},
onBulkUpdateInject(param: InjectBulkUpdateInputs): Promise<{
result: string;
entities: { injects: Record<string, InjectStore> };
}> {
// exercise.exercise_id
return dispatch(bulkUpdateInject(param));
onBulkUpdateInject(param: InjectBulkUpdateInputs): Promise<Inject[] | void> {
return bulkUpdateInjectSimple(param).then((result: { data: Inject[] }) => result?.data);
},
onUpdateInject(injectId: Inject['inject_id'], inject: Inject): Promise<{ result: string; entities: { injects: Record<string, InjectStore> } }> {
return dispatch(updateInjectForExercise(exercise.exercise_id, injectId, inject));
Expand Down Expand Up @@ -73,8 +69,7 @@ const injectContextForExercise = (exercise: Exercise) => {
return dryImportXlsForExercise(exercise.exercise_id, importId, input).then(result => result.data);
},
onBulkDeleteInjects(param: InjectBulkProcessingInput): Promise<Inject[]> {
// exercise.exercise_id
return dispatch(bulkDeleteInjects(param));
return bulkDeleteInjectsSimple(param).then((result: { data: Inject[] }) => result?.data);
},
bulkTestInjects(param: InjectBulkProcessingInput): Promise<{ uri: string; data: InjectTestStatus[] }> {
return bulkTestInjects(param).then(result => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import type { ArticlesHelper } from '../../../../../actions/channels/article-hel
import { fetchExerciseInjectExpectations, fetchExerciseTeams } from '../../../../../actions/Exercise';
import type { ExercisesHelper } from '../../../../../actions/exercises/exercise-helper';
import type { ChallengeHelper } from '../../../../../actions/helper';
import { fetchExerciseInjectsSimple } from '../../../../../actions/injects/inject-action';
import type { InjectHelper } from '../../../../../actions/injects/inject-helper';
import { fetchVariablesForExercise } from '../../../../../actions/variables/variable-actions';
import type { VariablesHelper } from '../../../../../actions/variables/variable-helper';
import { useFormatter } from '../../../../../components/i18n';
Expand Down Expand Up @@ -56,10 +54,9 @@ const ExerciseInjects: FunctionComponent = () => {
setViewMode(mode);
};

const { injects, exercise, teams, articles, variables } = useHelper(
(helper: InjectHelper & ExercisesHelper & ArticlesHelper & ChallengeHelper & VariablesHelper) => {
const { exercise, teams, articles, variables } = useHelper(
(helper: ExercisesHelper & ArticlesHelper & ChallengeHelper & VariablesHelper) => {
return {
injects: helper.getExerciseInjects(exerciseId),
exercise: helper.getExercise(exerciseId),
teams: helper.getExerciseTeams(exerciseId),
articles: helper.getExerciseArticles(exerciseId),
Expand All @@ -68,7 +65,6 @@ const ExerciseInjects: FunctionComponent = () => {
},
);
useDataLoader(() => {
dispatch(fetchExerciseInjectsSimple(exerciseId));
dispatch(fetchExerciseTeams(exerciseId));
dispatch(fetchExerciseArticles(exerciseId));
dispatch(fetchVariablesForExercise(exerciseId));
Expand All @@ -87,7 +83,6 @@ const ExerciseInjects: FunctionComponent = () => {
<Injects
isExercise={true}
exerciseOrScenarioId={exerciseId}
injects={injects}
teams={teams}
articles={articles}
variables={variables}
Expand Down
3 changes: 2 additions & 1 deletion openbas-front/src/utils/Action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ export const simplePutCall = (uri: string, data?: unknown, defaultNotifyErrorBeh
}
throw error;
});
export const simpleDelCall = (uri: string, defaultNotifyErrorBehavior: boolean = true, defaultSuccessBehavior: boolean = true) => simpleApi.delete(buildUri(uri))
// eslint-disable-next-line max-len
export const simpleDelCall = (uri: string, data?: unknown, defaultNotifyErrorBehavior: boolean = true, defaultSuccessBehavior: boolean = true) => simpleApi.delete(buildUri(uri), data ? { data: data } : undefined)
.then((response) => {
if (defaultSuccessBehavior) {
notifySuccess('The element has been successfully deleted.');
Expand Down

0 comments on commit b11f516

Please sign in to comment.