Skip to content

Commit

Permalink
[MDS-5356] actions dropdown (#2606)
Browse files Browse the repository at this point in the history
* merge changes, basic switch to TS

* add update_timestamp to response model, changed CoreTable to use ColumnsType, made functin to calculate expandProps: allow more custom props and not allow 'children' to force expansion rendering unless on purpose. Moved some columns from common columns to document columns file, updated an import. Made document object model and an extension: cannot always guarantee method access so set more properties- testing added for proper usage. DocumentTable: changed matchChildColumns to showVersionHistory prop, used FileOperations interface to keep allowed actions structure consistent with docs themselves, parseDocuments run documents through constructor; get rid of archiveDocumentsArgs, instead let the document keep the mine guid, separated out old and new columns functions, it was getting confusing, found the table param 'childrenColumnName'

* filter allowed actions by the user's roles. Do the setting in the table because it's most DRY for now

* eslint determined to make my file not compile, switching to any

* brought changes over from Core to MS, and moved document models into common folder, updated imports

* delete document modal, extremely similar to archive document modal

* Minespace. Bring over styles to make the document table, document columns basically the same (minus a bug with userAccessData...). Brought some changes back to Core as well

* tests and snaps

* fix diff

* changed comment, it was a lie

* change function from public to protected, don't actually want it called externally

* diff

* removed some comments

* fix diff?
  • Loading branch information
taraepp authored Jul 27, 2023
1 parent eaa4148 commit ae724ae
Show file tree
Hide file tree
Showing 52 changed files with 2,069 additions and 1,136 deletions.
1 change: 1 addition & 0 deletions services/core-api/app/api/mines/response_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def format(self, value):
'document_manager_guid': fields.String,
'document_name': fields.String,
'upload_date': fields.String,
'update_timestamp': fields.String,
'create_user': fields.String,
'is_archived': fields.Boolean,
'archived_date': fields.String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const ArchiveDocumentModal: FC<ArchiveDocumentModalProps> = (props: ArchiveDocum
documents={props.documents}
view="minimal"
uploadDateIndex="upload_date"
excludedColumnKeys={["archive", "remove", "category"]}
excludedColumnKeys={["actions", "category"]}
/>

<div className="ant-modal-footer">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from "react";
import DocumentTable from "@/components/common/DocumentTable";
import { Typography } from "antd";
import { IMineDocument } from "@mds/common";
import { DeleteOutlined } from "@ant-design/icons";
import { Feature, isFeatureEnabled } from "@mds/common";
import { MineDocument } from "@common/models/documents/document";

interface ArchivedDocumentsSectionProps {
documents: IMineDocument;
documents: MineDocument[];
documentColumns: any;
titleLevel?: 1 | 2 | 3 | 4 | 5;
}
Expand All @@ -16,12 +16,6 @@ const ArchivedDocumentsSection = (props: ArchivedDocumentsSectionProps) => {
return <></>;
}

const docs = props.documents.map((d) => {
d.name = d.document_name;

return d;
});

return (
<div id="archived-documents">
<Typography.Title level={props.titleLevel || 4}>
Expand All @@ -33,7 +27,7 @@ const ArchivedDocumentsSection = (props: ArchivedDocumentsSectionProps) => {
</Typography.Paragraph>
<DocumentTable
documentColumns={props.documentColumns}
documents={docs}
documents={props.documents}
excludedColumnKeys={["archive", "remove"]}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { FC } from "react";

import DocumentTable from "@/components/common/DocumentTable";
import { Alert, Button, Form, Typography } from "antd";
import { MineDocument } from "@common/models/documents/document";

interface DeleteDocumentModalProps {
documents: MineDocument[];
handleSubmit(documents: MineDocument[]): Promise<void>;
closeModal(): void;
}

const DeleteDocumentModal: FC<DeleteDocumentModalProps> = (props: DeleteDocumentModalProps) => {
return (
<Form
layout="vertical"
onFinish={() => props.handleSubmit(props.documents).then(props.closeModal)}
>
<Typography.Paragraph>
<Alert
message="Deleted files are not reviewed as part of the submission"
showIcon
type="warning"
description="By deleting this file, you are deleting all of its previous versions. This action cannot be undone."
/>
</Typography.Paragraph>

<Typography.Paragraph strong>
You&apos;re about to delete the following file{props.documents?.length > 1 ? "s" : ""}:
</Typography.Paragraph>

<DocumentTable
documents={props.documents}
view="minimal"
uploadDateIndex="upload_date"
excludedColumnKeys={["actions", "category"]}
/>

<div className="ant-modal-footer">
<Button className="full-mobile" onClick={props.closeModal}>
Cancel
</Button>
<Button className="full-mobile" type="primary" htmlType="submit">
Delete
</Button>
</div>
</Form>
);
};

export default DeleteDocumentModal;
153 changes: 153 additions & 0 deletions services/core-web/common/models/documents/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { USER_ROLES } from "@mds/common";

export enum FileOperations {
View = "Open in document viewer",
Download = "Download file",
Replace = "Replace file",
Archive = "Archive file",
Delete = "Delete",
}

/*
A base class for Mine Documents
There is an issue with antd where sorting a table that has children (ie matchChildColumnsToParent)
will transform the records into type <any> (with versions still maintaining their type) so properties accessed
by the table should be *set* to the specific object, cannot expect to be able to consistently call its methods
include "user_roles" property in the json used in the constructor to set allowed actions based on the user
*/
export class MineDocument {
public mine_document_guid: string;

public mine_guid: string;

public document_manager_guid: string;

public document_name: string;

public create_user: string;

public update_user: string;

public upload_date: string;

public update_timestamp: string;

public is_archived: boolean;

public archived_by: string;

public archived_date: string;

public is_latest_version: boolean;

public category?: string;

// generated
public key: string;

public file_type: string;

public number_prev_versions: number;

public versions: MineDocument[]; // all previous file versions, not including latest

public allowed_actions: FileOperations[];

constructor(jsonObject: any) {
this.mine_document_guid = jsonObject.mine_document_guid;
this.mine_guid = jsonObject.mine_guid;
this.document_manager_guid = jsonObject.document_manager_guid;
this.document_name = jsonObject.document_name;
this.create_user = jsonObject.create_user;
this.update_user = jsonObject.update_user;
this.upload_date = jsonObject.upload_date;
this.update_timestamp = jsonObject.update_timestamp;
this.category = jsonObject.category;
this.is_archived = jsonObject.is_archived ?? false;
this.archived_by = jsonObject.archived_by;
this.archived_date = jsonObject.archived_date;
this.is_latest_version = jsonObject.is_latest_version ?? true;
this.setCalculatedProperties(jsonObject);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected makeChild(params: any, _constructorArgs: any) {
return new MineDocument(params);
}

protected setCalculatedProperties(jsonObject: any) {
this.key = this.is_latest_version
? this.mine_document_guid
: jsonObject.document_manager_version_guid;
this.file_type = this.getFileType();

const versions = jsonObject.versions ?? [];
if (this.is_latest_version && versions.length) {
this.number_prev_versions = versions.length - 1;
this.versions = versions
.slice(1)
.map((version) => this.makeChild({ ...version, is_latest_version: false }, jsonObject));
} else {
this.number_prev_versions = 0;
this.versions = [];
}
this.setAllowedActions(jsonObject.user_roles);
}

public getFileType() {
const index = this.document_name.lastIndexOf(".");
return index === -1 ? null : this.document_name.substring(index).toLocaleLowerCase();
}

public setAllowedActions(userRoles: string[] = []) {
this.allowed_actions = this.getAllowedActions(userRoles).filter(Boolean);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected getAllowedActions(_userRoles: string[] = []) {
const canModify = this.is_latest_version && !this.is_archived;
return [
this.file_type === ".pdf" && FileOperations.View,
FileOperations.Download,
canModify && FileOperations.Replace,
canModify && FileOperations.Archive,
canModify && FileOperations.Delete,
];
}
}

export class MajorMineApplicationDocument extends MineDocument {
public major_mine_application_document_type_code: string;

public versions: MajorMineApplicationDocument[];

constructor(jsonObject: any) {
super(jsonObject);
this.major_mine_application_document_type_code =
jsonObject.major_mine_application_document_type_code;
}

protected makeChild(params: any, constructorArgs: any) {
return new MajorMineApplicationDocument({
...params,
major_mine_application_document_type_code:
constructorArgs.major_mine_application_document_type_code,
});
}

public getAllowedActions(userRoles: string[] = []) {
const allowedActions = super.getAllowedActions();

const canModifyRoles = [
USER_ROLES.role_edit_major_mine_applications,
USER_ROLES.role_minespace_proponent,
];
const canModify = userRoles.some((role) => canModifyRoles.includes(role));

return allowedActions.filter(
(action) => canModify || [FileOperations.View, FileOperations.Download].includes(action)
);
}
}
47 changes: 22 additions & 25 deletions services/core-web/src/components/common/CoreTable.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import React from "react";
import { Table, TableProps, Tooltip } from "antd";
import { ColumnType } from "antd/es/table";
import { ColumnsType } from "antd/es/table";
import { MinusSquareFilled, PlusSquareFilled } from "@ant-design/icons";
import { ExpandableConfig } from "antd/lib/table/interface";

interface CoreTableExpandConfig<T> extends ExpandableConfig<T> {
getDataSource: (record: T) => any[];
getDataSource?: (record: T) => any[];
rowKey?: string | ((record: any) => string);
recordDescription?: string;
subTableColumns?: ColumnType<any>[];
subTableColumns?: ColumnsType<any>;
matchChildColumnsToParent?: boolean;
// and any other props from expandable https://4x.ant.design/components/table/#expandable
}

interface CoreTableProps<T> extends TableProps<T> {
columns: ColumnType<T>[];
columns: ColumnsType<T>;
dataSource: T[];
condition?: boolean;
rowKey?: string | ((record: T) => string | number); // defaults to "key"
Expand Down Expand Up @@ -94,29 +94,26 @@ const CoreTable = <T,>(props: CoreTableProps<T>) => {
);
};

const expansionProps = expandProps
? {
rowExpandable:
expandProps.rowExpandable ?? ((record) => expandProps.getDataSource(record).length > 0),
expandIcon: renderTableExpandIcon,
expandRowByClick: true,
expandedRowRender: expandProps.expandedRowRender ?? renderExpandedRow,
...expandProps,
}
: null;

const matchChildColumnsToParentProps = expandProps
? {
expandIcon: renderTableExpandIcon,
indentSize: 0,
}
: null;
const getExpansionProps = () => {
if (expandProps) {
return expandProps.matchChildColumnsToParent
? { expandIcon: renderTableExpandIcon, indentSize: 0, ...expandProps }
: {
rowExpandable:
expandProps.rowExpandable ??
((record) => expandProps.getDataSource(record).length > 0),
expandIcon: renderTableExpandIcon,
expandRowByClick: true,
expandedRowRender: expandProps.expandedRowRender ?? renderExpandedRow,
...expandProps,
};
}
return { showExpandColumn: false };
};

return condition ? (
<Table
expandable={
expandProps?.matchChildColumnsToParent ? matchChildColumnsToParentProps : expansionProps
}
expandable={getExpansionProps()}
pagination={pagination}
locale={{ emptyText }}
className={`${tableClass} core-table`}
Expand All @@ -126,8 +123,8 @@ const CoreTable = <T,>(props: CoreTableProps<T>) => {
? "table-row-align-middle no-sub-table-expandable-rows fade-in"
: "fade-in"
}
{...tableProps}
columns={columns}
{...tableProps}
></Table>
) : (
<Table
Expand Down
Loading

0 comments on commit ae724ae

Please sign in to comment.