Skip to content

Commit

Permalink
[TACKLE-192] - Bulk copy Assessment/Review (#261)
Browse files Browse the repository at this point in the history
* save changes

* save

* Save changes

* Save changes

* Add checbox confirmation

* save changes

* Add translations

* Fix warning msg

* Change CSV test files

* Fix notification and form

* remove unused import

* Add select all

* Add tests for useSelectionFromPageState

* Add tests

* change warning icon position

* Change icon
  • Loading branch information
carlosthe19916 authored Nov 2, 2021
1 parent caf599b commit 9508504
Show file tree
Hide file tree
Showing 39 changed files with 1,486 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Record Type 1,Application Name,Description,Comments,Business Service,Tag Type 1,Tag 1,Tag Type 2,Tag 2,Tag Type 3,Tag 3,Tag Type 4,Tag 4,Tag Type 5,Tag 5,Tag Type 6,Tag 6,Tag Type 7,Tag 7,Tag Type 8,Tag 8,Tag Type 9,Tag 9,Tag Type 10,Tag 10,Tag Type 11,Tag 11,Tag Type 12,Tag 12,Tag Type 13,Tag 13,Tag Type 14,Tag 14,Tag Type 15,Tag 15,Tag Type 16,Tag 16,Tag Type 17,Tag 17,Tag Type 18,Tag 18,Tag Type 19,Tag 19,Tag Type 20,Tag 20
,application-a,description-a,comment-a,service-a,tagType-a,tag-a-a,tagType-a,tag-b-a,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,application-b,description-b,comment-b,service-b,tagType-b,tag-a-b,tagType-b,tag-b-b,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,application-c,description-c,comment-c,service-x,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1,application-a,description-a,comment-a,service-a,tagType-a,tag-a-a,tagType-a,tag-b-a,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1,application-b,description-b,comment-b,service-b,tagType-b,tag-a-b,tagType-b,tag-b-b,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1,application-c,description-c,comment-c,service-x,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Record Type 1,Application Name,Description,Comments,Business Service,Tag Type 1,Tag 1,Tag Type 2,Tag 2,Tag Type 3,Tag 3,Tag Type 4,Tag 4,Tag Type 5,Tag 5,Tag Type 6,Tag 6,Tag Type 7,Tag 7,Tag Type 8,Tag 8,Tag Type 9,Tag 9,Tag Type 10,Tag 10,Tag Type 11,Tag 11,Tag Type 12,Tag 12,Tag Type 13,Tag 13,Tag Type 14,Tag 14,Tag Type 15,Tag 15,Tag Type 16,Tag 16,Tag Type 17,Tag 17,Tag Type 18,Tag 18,Tag Type 19,Tag 19,Tag Type 20,Tag 20
,application-a,description-a,comment-a,service-a,tagType-a,tag-a-a,tagType-a,tag-b-a,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,application-b,description-b,comment-b,service-b,tagType-b,tag-a-b,tagType-b,tag-b-b,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1,application-a,description-a,comment-a,service-a,tagType-a,tag-a-a,tagType-a,tag-b-a,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1,application-b,description-b,comment-b,service-b,tagType-b,tag-a-b,tagType-b,tag-b-b,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
12 changes: 12 additions & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"clearAllFilters": "Clear all filters",
"close": "Close",
"continue": "Continue",
"copy": "Copy",
"copyAssessment": "Copy assessment",
"copyAssessmentAndReview": "Copy assessment and review",
"create": "Create",
"createNew": "Create new",
"createTag": "Create tag",
Expand Down Expand Up @@ -69,6 +72,8 @@
"leavePage": "Are you sure you want to leave this page? Be sure to save your changes, or they will be lost."
},
"title": {
"copyApplicationAssessmentAndReviewFrom": "Copy {{what}} assessment and review",
"copyApplicationAssessmentFrom": "Copy {{what}} assessment",
"delete": "Delete {{what}}?",
"discard": "Discard {{what}}?",
"importApplicationFile": "Import application file",
Expand Down Expand Up @@ -101,6 +106,11 @@
"appNotAssesedTitle": "Assessment has not been completed",
"appNotAssessedBody": "In order to review an application it must be assessed first. Please assess the application",
"assessmentStakeholderHeader": "Select the stakeholder(s) or stakeholder group(s) associated with this assessment.",
"continueConfirmation": "Yes, continue",
"copyAssessmentAndReviewBody": "Some of the selected target applications have an in-progress or complete assessment/review. By continuing, the existing assessment(s)/review(s) will be replaced by the copied assessment/review. Do you wish to continue?",
"copyAssessmentAndReviewQuestion": "Copy assessment and review?",
"copyAssessmentBody": "Some of the selected target applications have an in-progress or complete assessment. By continuing, the existing assessment(s) will be replaced by the copied assessment. Do you wish to continue?",
"copyAssessmentQuestion": "Copy assessment?",
"couldNotFetchBody": "Resource doesn't exists or you don't have access to it",
"couldNotFetchTitle": "Not available",
"importErrorCheckDocumentation": "For status Error imports please check the documentation to ensure your file is structured correctly.",
Expand Down Expand Up @@ -243,6 +253,8 @@
"toastr": {
"success": {
"added": "Success! {{what}} was added as a {{type}}.",
"assessmentAndReviewCopied": "Success! Assessment and review copied to selected applications",
"assessmentCopied": "Success! Assessment copied to selected applications",
"assessmentDiscarded": "Success! Assessment discarded for {{application}}.",
"fileSavedToBeProcessed": "Success! file saved to be processed."
}
Expand Down
16 changes: 14 additions & 2 deletions public/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"clearAllFilters": "Limpiar todos los filtros",
"close": "Cerrar",
"continue": "Continuar",
"copy": "Copiar",
"copyAssessment": "Copiar evaluación",
"copyAssessmentAndReview": "Copiar evaluación y revisión",
"create": "Crear",
"createNew": "Crear nuevo",
"createTag": "Crear etiqueta",
Expand Down Expand Up @@ -69,6 +72,8 @@
"leavePage": "¿Estás seguro de querer salir de esta página? Asegúrate de guardar tus cambios o estos se perderán."
},
"title": {
"copyApplicationAssessmentAndReviewFrom": "Copiar evaluación y revisión de {{what}}",
"copyApplicationAssessmentFrom": "Copiar evaluación {{what}}",
"delete": "¿Eliminar {{what}}?",
"discard": "¿Descartar {{what}}?",
"importApplicationFile": "Importar archivo con aplicaciones",
Expand Down Expand Up @@ -98,9 +103,14 @@
"small": "Pequeño"
},
"message": {
"appNotAssesedTitle": "",
"appNotAssessedBody": "",
"appNotAssesedTitle": "La evaluación no se ha completado",
"appNotAssessedBody": "Para revisar una aplicación, esta debe de ser evaluada primero. Por favor evalúe la aplicación",
"assessmentStakeholderHeader": "Seleccione a los interesados o grupo de interesados asociados a esta evaluación.",
"continueConfirmation": "Si, continuar",
"copyAssessmentAndReviewBody": "Algunas de las aplicaciones de destino seleccionadas tienen una evaluación/revisión en curso o completa. Al continuar, las evaluaciones/revisiones existentes serán reemplazadas por la evaluación/revisión copiada. ¿Desea continuar?",
"copyAssessmentAndReviewQuestion": "¿Copiar evaluación y revisión?",
"copyAssessmentBody": "Algunas de las aplicaciones de destino seleccionadas tienen una evaluación en curso o completa. Al continuar, las evaluaciones existentes serán reemplazadas por la evaluación copiada. ¿Desea continuar?",
"copyAssessmentQuestion": "¿Copiar evaluación?",
"couldNotFetchBody": "El recurso no existe o no tienes permiso para acceder al mismo",
"couldNotFetchTitle": "No disponible",
"importErrorCheckDocumentation": "Para estados de importación Error por favor verifica la documentación para asegurar la correcta estructura del archivo.",
Expand Down Expand Up @@ -243,6 +253,8 @@
"toastr": {
"success": {
"added": "Éxito! {{what}} fue creado como un {{type}}.",
"assessmentAndReviewCopied": "Éxito! Evaluación y revisión copiada a las aplicaciones seleccionadas",
"assessmentCopied": "Éxito! Evaluación copiada a las aplicaciones seleccionadas",
"assessmentDiscarded": "Éxito! Evaluación de {{application}} desechada.",
"fileSavedToBeProcessed": "Éxito! El archivo fue guardado para ser procesado."
}
Expand Down
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import NotificationsPortal from "@redhat-cloud-services/frontend-components-noti
import "@redhat-cloud-services/frontend-components-notifications/index.css";

import { ConfirmDialogContainer } from "./shared/containers/confirm-dialog-container";
import { BulkCopyNotificationsContainer } from "./shared/containers/bulk-copy-notifications-container";

const App: React.FC = () => {
return (
Expand All @@ -19,6 +20,7 @@ const App: React.FC = () => {
</DefaultLayout>
<NotificationsPortal />
<ConfirmDialogContainer />
<BulkCopyNotificationsContainer />
</BrowserRouter>
);
};
Expand Down
14 changes: 14 additions & 0 deletions src/api/models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ export interface ApplicationImport {
isValid: boolean;
}

export interface BulkCopyReview {
id?: number;
sourceReview: number;
targetApplications: number[];
completed?: boolean;
}

// Pathfinder

export type AssessmentStatus = "EMPTY" | "STARTED" | "COMPLETE";
Expand Down Expand Up @@ -188,6 +195,13 @@ export interface AssessmentConfidence {
confidence: number;
}

export interface BulkCopyAssessment {
bulkId?: number;
fromAssessmentId: number;
applications: { applicationId: number }[];
completed?: boolean;
}

// Pagination

export interface BusinessServicePage {
Expand Down
24 changes: 24 additions & 0 deletions src/api/rest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
ApplicationImportSummaryPage,
ApplicationImportPage,
ApplicationImportSummary,
BulkCopyAssessment,
BulkCopyReview,
} from "./models";

export const CONTROLS_BASE_URL = "controls";
Expand Down Expand Up @@ -666,6 +668,16 @@ export const getApplicationSummaryCSV = (id: string): AxiosPromise => {
});
};

export const createBulkCopyReview = (
bulk: BulkCopyReview
): AxiosPromise<BulkCopyReview> => {
return APIClient.post<BulkCopyReview>(`${REVIEW}/bulk`, bulk);
};

export const getBulkCopyReview = (id: number): AxiosPromise<BulkCopyReview> => {
return APIClient.get<BulkCopyReview>(`${REVIEW}/bulk/${id}`);
};

//

export const getAssessments = (filters: {
Expand Down Expand Up @@ -723,3 +735,15 @@ export const getAssessmentConfidence = (
applicationIds.map((f) => ({ applicationId: f }))
);
};

export const createBulkCopyAssessment = (
bulk: BulkCopyAssessment
): AxiosPromise<BulkCopyAssessment> => {
return APIClient.post<BulkCopyAssessment>(`${ASSESSMENTS}/bulk`, bulk);
};

export const getBulkCopyAssessment = (
id: number
): AxiosPromise<BulkCopyAssessment> => {
return APIClient.get<BulkCopyAssessment>(`${ASSESSMENTS}/bulk/${id}`);
};
102 changes: 99 additions & 3 deletions src/pages/application-inventory/application-list/application-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { RootState } from "store/rootReducer";
import { alertActions } from "store/alert";
import { confirmDialogActions } from "store/confirmDialog";
import { unknownTagsSelectors } from "store/unknownTags";
import { bulkCopySelectors } from "store/bulkCopy";

import {
ApplicationToolbarToggleGroup,
Expand Down Expand Up @@ -84,6 +85,7 @@ import { ApplicationAssessment } from "./components/application-assessment";
import { ApplicationBusinessService } from "./components/application-business-service";
import { ApplicationListExpandedArea } from "./components/application-list-expanded-area";
import { ImportApplicationsForm } from "./components/import-applications-form";
import { BulkCopyAssessmentReviewForm } from "./components/bulk-copy-assessment-review-form";

const toSortByQuery = (
sortBy?: SortByQuery
Expand Down Expand Up @@ -132,10 +134,15 @@ export const ApplicationList: React.FC = () => {

// Redux
const dispatch = useDispatch();

const unknownTagIds = useSelector((state: RootState) =>
unknownTagsSelectors.unknownTagIds(state)
);

const isWatchingBulkCopy = useSelector((state: RootState) =>
bulkCopySelectors.isWatching(state)
);

// Router
const history = useHistory();

Expand Down Expand Up @@ -191,7 +198,13 @@ export const ApplicationList: React.FC = () => {

useEffect(() => {
refreshTable();
}, [filtersValue, paginationQuery, sortByQuery, refreshTable]);
}, [
filtersValue,
paginationQuery,
sortByQuery,
isWatchingBulkCopy,
refreshTable,
]);

// Create and update modal
const {
Expand Down Expand Up @@ -224,6 +237,22 @@ export const ApplicationList: React.FC = () => {
onDelete: (t: Application) => deleteApplication(t.id!),
});

// Copy assessment modal
const {
isOpen: isCopyAssessmentModalOpen,
data: applicationToCopyAssessmentFrom,
update: openCopyAssessmentModal,
close: closeCopyAssessmentModal,
} = useEntityModal<Application>();

// Copy assessment and review modal
const {
isOpen: isCopyAssessmentAndReviewModalOpen,
data: applicationToCopyAssessmentAndReviewFrom,
update: openCopyAssessmentAndReviewModal,
close: closeCopyAssessmentAndReviewModal,
} = useEntityModal<Application>();

// Dependencies modal
const {
isOpen: isDependenciesModalOpen,
Expand Down Expand Up @@ -388,7 +417,34 @@ export const ApplicationList: React.FC = () => {

const actions: (IAction | ISeparator)[] = [];

if (getApplicationAssessment(row.id!)) {
const applicationAssessment = getApplicationAssessment(row.id!);
if (applicationAssessment?.status === "COMPLETE") {
actions.push({
title: t("actions.copyAssessment"),
onClick: (
event: React.MouseEvent,
rowIndex: number,
rowData: IRowData
) => {
const row: Application = getRow(rowData);
openCopyAssessmentModal(row);
},
});
}
if (row.review) {
actions.push({
title: t("actions.copyAssessmentAndReview"),
onClick: (
event: React.MouseEvent,
rowIndex: number,
rowData: IRowData
) => {
const row: Application = getRow(rowData);
openCopyAssessmentAndReviewModal(row);
},
});
}
if (applicationAssessment) {
actions.push({
title: t("actions.discardAssessment"),
onClick: (
Expand Down Expand Up @@ -650,7 +706,7 @@ export const ApplicationList: React.FC = () => {
setFilter={setFilter}
/>
}
toolbar={
toolbarActions={
<>
<ToolbarGroup variant="button-group">
<ToolbarItem>
Expand Down Expand Up @@ -754,6 +810,46 @@ export const ApplicationList: React.FC = () => {
/>
</Modal>

<Modal
isOpen={isCopyAssessmentModalOpen}
variant="large"
title={t("dialog.title.copyApplicationAssessmentFrom", {
what: applicationToCopyAssessmentFrom?.name,
})}
onClose={closeCopyAssessmentModal}
>
{applicationToCopyAssessmentFrom && (
<BulkCopyAssessmentReviewForm
application={applicationToCopyAssessmentFrom}
assessment={
getApplicationAssessment(applicationToCopyAssessmentFrom.id!)!
}
onSaved={closeCopyAssessmentModal}
/>
)}
</Modal>
<Modal
isOpen={isCopyAssessmentAndReviewModalOpen}
variant="large"
title={t("dialog.title.copyApplicationAssessmentAndReviewFrom", {
what: applicationToCopyAssessmentAndReviewFrom?.name,
})}
onClose={closeCopyAssessmentAndReviewModal}
>
{applicationToCopyAssessmentAndReviewFrom && (
<BulkCopyAssessmentReviewForm
application={applicationToCopyAssessmentAndReviewFrom}
assessment={
getApplicationAssessment(
applicationToCopyAssessmentAndReviewFrom.id!
)!
}
review={applicationToCopyAssessmentAndReviewFrom.review}
onSaved={closeCopyAssessmentAndReviewModal}
/>
)}
</Modal>

<Modal
isOpen={isDependenciesModalOpen}
variant="medium"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { EmptyTextMessage } from "shared/components";
import { EFFORT_ESTIMATE_LIST, PROPOSED_ACTION_LIST } from "Constants";
import { Application } from "api/models";

import { ApplicationTags } from "../application-tags/application-tags";
import { ApplicationTags } from "../application-tags";
import { ApplicationRisk } from "./application-risk";

export interface IApplicationListExpandedAreaProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { ApplicationTags as UpdateApplicationModal } from "./application-tags";
export { ApplicationTags } from "./application-tags";
Loading

0 comments on commit 9508504

Please sign in to comment.