Skip to content

Commit

Permalink
[MDS-6157] major projects uploads file name convention (#3279)
Browse files Browse the repository at this point in the history
* adding file name convention to major projects uploads

* fixing prop type

* remove unnecssary import

* adjust test spec

* fix cypress test error

* adjust test snap

* addressing pr comments
  • Loading branch information
asinn134 authored Oct 25, 2024
1 parent 0cdee1c commit 48ee3af
Show file tree
Hide file tree
Showing 20 changed files with 155 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import FormWrapper from "../../forms/FormWrapper";
import { change, Field, getFormValues, reset, touch } from "redux-form";
import RenderFileUpload from "../../forms/RenderFileUpload";
import { spatialDocumentBundle } from "@mds/common/redux/utils/Validate";
import { OTHER_SPATIAL, SPATIAL_DATA_STANDARDS_URL, XML } from "../../..";
import {
OTHER_SPATIAL,
SPATIAL_DATA_STANDARDS_URL,
XML,
MAX_DOCUMENT_NAME_LENGTHS,
} from "../../..";
import { Alert, Button, Row, Steps, Typography } from "antd";
import RenderCancelButton from "../../forms/RenderCancelButton";
import RenderSubmitButton from "../../forms/RenderSubmitButton";
Expand Down Expand Up @@ -165,6 +170,7 @@ const AddSpatialDocumentsModal: FC<AddSpatialDocumentsModalProps> = ({
onRemoveFile={handleRemoveFile}
component={RenderFileUpload}
maxFileSize="400MB"
maxFileNameLength={MAX_DOCUMENT_NAME_LENGTHS.MAJOR_PROJECTS}
label="Upload Spatial File"
abbrevLabel
listedFileTypes={["spatial"]}
Expand Down
16 changes: 12 additions & 4 deletions services/common/src/components/forms/RenderFileUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ interface FileUploadProps extends BaseInputProps {
allowMultiple?: boolean;
allowReorder?: boolean;
maxFileSize?: string;
maxFileNameLength?: string;
itemInsertLocation?: ItemInsertLocationType;
// for a completely customized drop label
labelIdle?: string;
Expand All @@ -75,6 +76,7 @@ interface FileUploadProps extends BaseInputProps {

export const FileUpload: FC<FileUploadProps> = ({
maxFileSize = "750MB",
maxFileNameLength = null,
acceptedFileTypesMap = {},
onFileLoad = () => {},
onRemoveFile = () => {},
Expand Down Expand Up @@ -152,11 +154,15 @@ export const FileUpload: FC<FileUploadProps> = ({
fileTypeDisplayString = fileTypeList[0];
}

const fileSize = maxFileSize ? ` with max individual file size of ${maxFileSize}` : "";
const fileSize = maxFileSize ? ` with max file size of ${maxFileSize}` : "";
const secondLineWithNamingConvention = `<div>Use the naming convention: "YYYY MM DD Short Descriptive Title"
(max ${maxFileNameLength} characters) ${fileSize}.</div>`;
const secondLine = abbrevLabel
? `<div>We accept most common ${fileTypeDisplayString} files${fileSize}.</div>`
: `<div>Accepted filetypes: ${fileTypeDisplayString}</div>`;
return `${labelInstruction}<br>${secondLine}`;
return `${labelInstruction}<br>${
maxFileNameLength ? secondLineWithNamingConvention : secondLine
}`;
};

// Stores metadata and process function for each file, so we can manually
Expand All @@ -183,15 +189,17 @@ export const FileUpload: FC<FileUploadProps> = ({
const response = err.originalRequest
? JSON.parse(err.originalRequest.getUnderlyingObject().response)
: err || {};

const errorMessage = err?.response?.data?.message;
if (
!(
notificationDisabledStatusCodes?.length &&
notificationDisabledStatusCodes?.includes(response.status_code)
)
) {
notification.error({
message: `Failed to upload ${file && file.name ? file.name : ""}: ${err}`,
message: `Failed to upload ${file && file.name ? file.name : ""}: ${
errorMessage ? errorMessage : err
}`,
duration: 10,
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { Field } from "redux-form";
import { DOCUMENT, EXCEL, IMAGE, SPATIAL } from "@mds/common/constants/fileTypes";
import { PROJECT_SUMMARY_DOCUMENTS } from "@mds/common/constants/API";
import RenderFileUpload from "@mds/common/components/forms/RenderFileUpload";
import { IProjectSummaryDocument } from "../..";
import {
PROJECT_SUMMARY_DOCUMENT_TYPE_CODE,
DISCHARGE_FACTOR_FORM_AMENDMENT,
DISCHARGE_FACTOR_FORM_NEW,
IProjectSummaryDocument,
MAX_DOCUMENT_NAME_LENGTHS,
} from "../..";
import { requiredList } from "@mds/common/redux/utils/Validate";

Expand Down Expand Up @@ -46,16 +47,17 @@ export const AuthorizationSupportDocumentUpload: FC<AuthorizationSupportDocument
console.log(error);
}

const amendmentDocumentsIndex = documents.findIndex(
(doc) => fileToRemove.serverId === doc.document_manager_guid
);
const amendmentDocument = documents.find(
(doc) => fileToRemove.serverId === doc.document_manager_guid
);
const category =
amendmentDocument.category || amendmentDocument.project_summary_document_type_code;

removeAmendmentDocument(amendmentDocumentsIndex, category, fileToRemove.serverId);
if (fileToRemove.serverId) {
const amendmentDocumentsIndex = documents.findIndex(
(doc) => fileToRemove.serverId === doc.document_manager_guid
);
const amendmentDocument = documents.find(
(doc) => fileToRemove.serverId === doc.document_manager_guid
);
const category =
amendmentDocument?.category || amendmentDocument?.project_summary_document_type_code;
removeAmendmentDocument(amendmentDocumentsIndex, category, fileToRemove.serverId);
}
};

const handleFileLoad = (
Expand Down Expand Up @@ -105,6 +107,7 @@ export const AuthorizationSupportDocumentUpload: FC<AuthorizationSupportDocument
acceptedFileTypesMap={acceptedFileTypesMap}
listedFileTypes={["document", "image", "spreadsheet", "spatial"]}
abbrevLabel={true}
maxFileNameLength={MAX_DOCUMENT_NAME_LENGTHS.MAJOR_PROJECTS}
uploadUrl={PROJECT_SUMMARY_DOCUMENTS({ projectGuid, projectSummaryGuid, mineGuid })}
onFileLoad={(document_name, document_manager_guid) =>
handleFileLoad(
Expand Down Expand Up @@ -133,6 +136,7 @@ export const AuthorizationSupportDocumentUpload: FC<AuthorizationSupportDocument
acceptedFileTypesMap={acceptedFileTypesMap}
listedFileTypes={["document", "image", "spreadsheet", "spatial"]}
abbrevLabel={true}
maxFileNameLength={MAX_DOCUMENT_NAME_LENGTHS.MAJOR_PROJECTS}
uploadUrl={PROJECT_SUMMARY_DOCUMENTS({ projectGuid, projectSummaryGuid, mineGuid })}
onFileLoad={(document_name, document_manager_guid) =>
handleFileLoad(
Expand All @@ -159,6 +163,7 @@ export const AuthorizationSupportDocumentUpload: FC<AuthorizationSupportDocument
acceptedFileTypesMap={acceptedFileTypesMap}
listedFileTypes={["document", "image", "spreadsheet", "spatial"]}
abbrevLabel={true}
maxFileNameLength={MAX_DOCUMENT_NAME_LENGTHS.MAJOR_PROJECTS}
uploadUrl={PROJECT_SUMMARY_DOCUMENTS({ projectGuid, projectSummaryGuid, mineGuid })}
onFileLoad={(document_name, document_manager_guid) =>
handleFileLoad(
Expand All @@ -185,6 +190,7 @@ export const AuthorizationSupportDocumentUpload: FC<AuthorizationSupportDocument
acceptedFileTypesMap={acceptedFileTypesMap}
listedFileTypes={["document", "image", "spreadsheet", "spatial"]}
abbrevLabel={true}
maxFileNameLength={MAX_DOCUMENT_NAME_LENGTHS.MAJOR_PROJECTS}
uploadUrl={PROJECT_SUMMARY_DOCUMENTS({ projectGuid, projectSummaryGuid, mineGuid })}
onFileLoad={(document_name, document_manager_guid) =>
handleFileLoad(
Expand Down Expand Up @@ -213,6 +219,7 @@ export const AuthorizationSupportDocumentUpload: FC<AuthorizationSupportDocument
acceptedFileTypesMap={acceptedFileTypesMap}
listedFileTypes={["document", "image", "spreadsheet", "spatial"]}
abbrevLabel={true}
maxFileNameLength={MAX_DOCUMENT_NAME_LENGTHS.MAJOR_PROJECTS}
uploadUrl={PROJECT_SUMMARY_DOCUMENTS({ projectGuid, projectSummaryGuid, mineGuid })}
onFileLoad={(document_name, document_manager_guid) =>
handleFileLoad(
Expand All @@ -239,6 +246,7 @@ export const AuthorizationSupportDocumentUpload: FC<AuthorizationSupportDocument
acceptedFileTypesMap={acceptedFileTypesMap}
listedFileTypes={["document", "image", "spreadsheet", "spatial"]}
abbrevLabel={true}
maxFileNameLength={MAX_DOCUMENT_NAME_LENGTHS.MAJOR_PROJECTS}
uploadUrl={PROJECT_SUMMARY_DOCUMENTS({ projectGuid, projectSummaryGuid, mineGuid })}
onFileLoad={(document_name, document_manager_guid) =>
handleFileLoad(
Expand All @@ -263,6 +271,7 @@ export const AuthorizationSupportDocumentUpload: FC<AuthorizationSupportDocument
acceptedFileTypesMap={acceptedFileTypesMap}
listedFileTypes={["document", "image", "spreadsheet", "spatial"]}
abbrevLabel={true}
maxFileNameLength={MAX_DOCUMENT_NAME_LENGTHS.MAJOR_PROJECTS}
uploadUrl={PROJECT_SUMMARY_DOCUMENTS({ projectGuid, projectSummaryGuid, mineGuid })}
onFileLoad={(document_name, document_manager_guid) =>
handleFileLoad(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,16 @@ const RenderEMAPermitCommonSections = ({ code, isAmendment, index, isDisabled })
) => {
const categorySpecificDocumentType = PROJECT_SUMMARY_DOCUMENT_TYPE_CODE_STATE[category];
const categorySpecificDocuments = sectionValues[categorySpecificDocumentType];
const categorySpecificDocumentIndex = categorySpecificDocuments.findIndex(
const categorySpecificDocumentIndex = categorySpecificDocuments?.findIndex(
(doc) => document_manager_guid === doc.document_manager_guid
);

dispatch(
arrayRemove(
FORM.ADD_EDIT_PROJECT_SUMMARY,
`authorizations.[${code}].${authType}[${index}].${categorySpecificDocumentType}`,
categorySpecificDocumentIndex
)
);

dispatch(
arrayRemove(
FORM.ADD_EDIT_PROJECT_SUMMARY,
Expand Down
32 changes: 19 additions & 13 deletions services/common/src/components/projectSummary/DocumentUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,19 +146,25 @@ export const DocumentUpload: FC = () => {
};

const onRemoveFile = (err, fileItem) => {
const document_type_code = documents.find(
(file) => fileItem.serverId === file.document_manager_guid
)?.project_summary_document_type_code;
if (document_type_code === PROJECT_SUMMARY_DOCUMENT_TYPE_CODE.SPATIAL) {
const newSpatialDocuments = [...spatial_documents].filter(
(file) => fileItem.serverId !== file.document_manager_guid
);
dispatch(change(FORM.ADD_EDIT_PROJECT_SUMMARY, "spatial_documents", newSpatialDocuments));
} else if (document_type_code === PROJECT_SUMMARY_DOCUMENT_TYPE_CODE.SUPPORTING) {
const newSupportDocuments = [...support_documents].filter(
(file) => fileItem.serverId !== file.document_manager_guid
);
dispatch(change(FORM.ADD_EDIT_PROJECT_SUMMARY, "support_documents", newSupportDocuments));
if (err) {
console.log(err);
}

if (fileItem.serverId) {
const document_type_code = documents.find(
(file) => fileItem.serverId === file.document_manager_guid
)?.project_summary_document_type_code;
if (document_type_code === PROJECT_SUMMARY_DOCUMENT_TYPE_CODE.SPATIAL) {
const newSpatialDocuments = [...spatial_documents].filter(
(file) => fileItem.serverId !== file.document_manager_guid
);
dispatch(change(FORM.ADD_EDIT_PROJECT_SUMMARY, "spatial_documents", newSpatialDocuments));
} else if (document_type_code === PROJECT_SUMMARY_DOCUMENT_TYPE_CODE.SUPPORTING) {
const newSupportDocuments = [...support_documents].filter(
(file) => fileItem.serverId !== file.document_manager_guid
);
dispatch(change(FORM.ADD_EDIT_PROJECT_SUMMARY, "support_documents", newSupportDocuments));
}
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Alert, Divider, Modal, Popconfirm, Table, Typography } from "antd";
import { getUserInfo } from "@mds/common/redux/selectors/authenticationSelectors";
import { FilePondFile } from "filepond";
import { IDocument } from "@mds/common/interfaces/document";
import { MAX_DOCUMENT_NAME_LENGTHS } from "@mds/common/constants";

const notificationDisabledStatusCodes = [409]; // Define the notification disabled status codes

Expand Down Expand Up @@ -202,6 +203,7 @@ export const ProjectSummaryFileUpload: FC<WrappedFieldProps & ProjectSummaryFile
{...(props.label ? { label: props.label } : {})}
{...(props.listedFileTypes ? { listedFileTypes: props.listedFileTypes } : {})}
abbrevLabel={true}
maxFileNameLength={MAX_DOCUMENT_NAME_LENGTHS.MAJOR_PROJECTS}
id="fileUpload"
name="fileUpload"
component={RenderFileUpload}
Expand Down
4 changes: 4 additions & 0 deletions services/common/src/constants/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,7 @@ export enum AMS_WATER_SUSTAINABILITY_ACT_TYPES {
export enum AMS_FORESTRY_ACT_TYPE {
"OCCUPANT_CUT_LICENCE" = "OCCUPANT_CUT_LICENCE",
}

export enum MAX_DOCUMENT_NAME_LENGTHS {
"MAJOR_PROJECTS" = "50",
}
4 changes: 4 additions & 0 deletions services/core-api/app/api/constants.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from app.api.projects.project.models.project import Project
from app.api.mines.mine.models.mine import Mine
from app.api.services.document_manager_service import DocumentManagerService

from app.api.constants import MAX_DOCUMENT_NAME_LENGTHS

class InformationRequirementsTableDocumentUploadResource(Resource, UserMixin):
@api.doc(
Expand All @@ -17,11 +17,11 @@ def post(self, project_guid):

if not project:
raise NotFound('Project not found.')

mine = Mine.find_by_mine_guid(str(project.mine_guid))

if not mine:
raise NotFound('Mine not found.')

return DocumentManagerService.initializeFileUploadWithDocumentManager(
request, mine, 'information_requirements_table')
request, mine, 'information_requirements_table', MAX_DOCUMENT_NAME_LENGTHS['MAJOR_PROJECTS'])
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from app.api.projects.project.models.project import Project
from app.api.mines.mine.models.mine import Mine
from app.api.services.document_manager_service import DocumentManagerService
from app.api.constants import MAX_DOCUMENT_NAME_LENGTHS


class MajorMineApplicationDocumentUploadResource(Resource, UserMixin):
Expand All @@ -30,4 +31,4 @@ def post(self, project_guid):
raise NotFound('Mine not found.')

return DocumentManagerService.initializeFileUploadWithDocumentManager(
request, mine, 'major_mine_application')
request, mine, 'major_mine_application', MAX_DOCUMENT_NAME_LENGTHS['MAJOR_PROJECTS'])
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from app.api.projects.project.models.project import Project
from app.api.mines.mine.models.mine import Mine
from app.api.services.document_manager_service import DocumentManagerService
from app.api.constants import MAX_DOCUMENT_NAME_LENGTHS


class ProjectDecisionPackageDocumentUploadResource(Resource, UserMixin):
Expand All @@ -30,4 +31,4 @@ def post(self, project_guid):
raise NotFound('Mine not found.')

return DocumentManagerService.initializeFileUploadWithDocumentManager(
request, mine, 'project_decision_package')
request, mine, 'project_decision_package', MAX_DOCUMENT_NAME_LENGTHS['MAJOR_PROJECTS'])
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from app.api.services.document_manager_service import DocumentManagerService
from app.config import Config
from app.api.utils.feature_flag import is_feature_enabled, Feature
from app.api.constants import MAX_DOCUMENT_NAME_LENGTHS

class ProjectSummaryDocumentUploadResource(Resource, UserMixin):
@api.doc(
Expand All @@ -29,7 +30,8 @@ def post(self, project_guid, project_summary_guid):

if is_feature_enabled(Feature.MAJOR_PROJECT_REPLACE_FILE):
return DocumentManagerService.validateFileNameAndInitializeFileUploadWithDocumentManager(
request, mine, project_guid, 'project_summaries')
request, mine, project_guid, 'project_summaries', MAX_DOCUMENT_NAME_LENGTHS['MAJOR_PROJECTS'])
else:
return DocumentManagerService.initializeFileUploadWithDocumentManager(request, mine, 'project_summaries')
return DocumentManagerService.initializeFileUploadWithDocumentManager(
request, mine, 'project_summaries', MAX_DOCUMENT_NAME_LENGTHS['MAJOR_PROJECTS'])

15 changes: 10 additions & 5 deletions services/core-api/app/api/services/document_manager_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from flask import request as flask_request
from flask_restx import fields, marshal
from tusclient import client
from werkzeug.exceptions import BadRequest

logger = logging.getLogger(__name__)

Expand All @@ -34,7 +35,8 @@ class DocumentManagerService():
document_manager_document_resource_url = f'{Config.DOCUMENT_MANAGER_URL}/documents'

@classmethod
def validateFileNameAndInitializeFileUploadWithDocumentManager(cls, request, mine, project_guid, document_category):
def validateFileNameAndInitializeFileUploadWithDocumentManager(
cls, request, mine, project_guid, document_category, max_document_name_length=None):

metadata = cls._parse_request_metadata(request)
file_name = metadata.get('filename')
Expand All @@ -43,8 +45,7 @@ def validateFileNameAndInitializeFileUploadWithDocumentManager(cls, request, min
resp = None

if not mine_document: # No existing file found in this application hence continuing the file uploading
resp = DocumentManagerService.initializeFileUploadWithDocumentManager(request, mine, document_category)

resp = DocumentManagerService.initializeFileUploadWithDocumentManager(request, mine, document_category, max_document_name_length)
elif mine_document.is_archived: # An archived file with the same name in this application found, hence responing with 409
content = {
"description" : f"Archived file already exist with the given name: {file_name}",
Expand Down Expand Up @@ -76,11 +77,15 @@ def validateFileNameAndInitializeFileUploadWithDocumentManager(cls, request, min
return resp

@classmethod
def initializeFileUploadWithDocumentManager(cls, request, mine, document_category):
def initializeFileUploadWithDocumentManager(cls, request, mine, document_category, max_document_name_length=None):
metadata = cls._parse_request_metadata(request)
if not metadata or not metadata.get('filename'):
raise Exception('Request metadata missing filename')


file_name = ((metadata.get('filename')).rsplit('.', 1))[0]
if max_document_name_length and len(file_name) > max_document_name_length:
raise BadRequest(f'File name exceeds the {max_document_name_length} character limit')

folder, pretty_folder = cls._parse_upload_folders(mine, document_category)
data = {
'folder': folder,
Expand Down
Loading

0 comments on commit 48ee3af

Please sign in to comment.