-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MDS-5356] Actions Dropdown #2605
Changes from 9 commits
e4aeb51
fcf151f
d35f3da
cee488c
c5f774d
17bff75
5ec934e
f987272
bbdeb22
0ca08ba
1219d2e
16ab780
f8cdd4e
3d4d169
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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'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; |
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", | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Made sense to me to put this here, but would make sense to put it in the documents directory instead |
||
|
||
/* | ||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. eslint added all these spaces on me and I was not feeling like changing eslint rules, even though it irritates me to look at it. |
||
|
||
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 versions, 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://bcmines.atlassian.net/browse/MDS-5356?focusedCommentId=22159 <-- some explanation of why things are set up this way (with functions setting a value instead of returning it) |
||
} | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
public 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) | ||
); | ||
} | ||
} |
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"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The change to ColumnsType was just because of my struggles with type (see above) and attempt to fix it by getting rid of differences between what we had and antd demos. It didn't seem to affect anything. |
||
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" | ||
|
@@ -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 }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ran into an issue where if the dataSource had children, it would show the expand icon even if I didn't want it to. Forced it to be deliberate. |
||
}; | ||
|
||
return condition ? ( | ||
<Table | ||
expandable={ | ||
expandProps?.matchChildColumnsToParent ? matchChildColumnsToParentProps : expansionProps | ||
} | ||
expandable={getExpansionProps()} | ||
pagination={pagination} | ||
locale={{ emptyText }} | ||
className={`${tableClass} core-table`} | ||
|
@@ -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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is copied from ArchiveDocumentModal, with some word changes.