diff --git a/src/Utils/Funcs.ts b/src/Utils/Funcs.ts index b63383f..349bbd7 100644 --- a/src/Utils/Funcs.ts +++ b/src/Utils/Funcs.ts @@ -4,23 +4,27 @@ import { SPDEVMODE_LOCAL_STORAGE_KEY } from '../webparts/constants'; export function getEntryWebAccessUrl( nodeId: string, - repoId: string, waUrl: string, - isContainer: boolean + isContainer: boolean, + repoId?: string ): string | undefined { - if (nodeId?.length === 0 || repoId?.length === 0 || waUrl?.length === 0) { + if (!nodeId || nodeId?.length === 0 || !waUrl || waUrl?.length === 0) { return undefined; } let newUrl: string; if (isContainer) { - const queryParams: UrlUtils.QueryParameter[] = [['repo', repoId]]; + const queryParams: UrlUtils.QueryParameter[] = repoId + ? [['repo', repoId]] + : []; newUrl = UrlUtils.combineURLs(waUrl ?? '', 'Browse.aspx', queryParams); newUrl += `#?id=${encodeURIComponent(nodeId)}`; } else { - const queryParams: UrlUtils.QueryParameter[] = [ - ['repo', repoId], - ['docid', nodeId], - ]; + const queryParams: UrlUtils.QueryParameter[] = repoId + ? [ + ['repo', repoId], + ['docid', nodeId], + ] + : [['docid', nodeId]]; newUrl = UrlUtils.combineURLs(waUrl ?? '', 'DocView.aspx', queryParams); } return newUrl; diff --git a/src/extensions/savetoLaserfiche/CommonDialogs.tsx b/src/extensions/savetoLaserfiche/CommonDialogs.tsx index a735ff8..a147c66 100644 --- a/src/extensions/savetoLaserfiche/CommonDialogs.tsx +++ b/src/extensions/savetoLaserfiche/CommonDialogs.tsx @@ -1,91 +1,89 @@ import * as React from 'react'; -import { Navigation } from 'spfx-navigation'; import styles from './SendToLaserFiche.module.scss'; +import { SPComponentLoader } from '@microsoft/sp-loader'; +import { SavedToLaserficheDocumentData } from './SaveDocumentToLaserfiche'; -const SAVING_DOCUMENT_TO_LASERFICHE = 'Saving your document to Laserfiche'; +const SAVING_DOCUMENT_TO_LASERFICHE = 'Saving document to Laserfiche...'; export default function LoadingDialog() { return ( <> - -
-

{SAVING_DOCUMENT_TO_LASERFICHE}

-
+ +
+
{SAVING_DOCUMENT_TO_LASERFICHE}
); } -const DOCUMENT_UPLOADED = 'Document uploaded'; -const DOCUMENT_UPLOADED_METADATA_FAILED = - 'Document uploaded to repository, updating metadata failed due to constraint mismatch'; +const DOCUMENT_SUCCESSFULLY_UPLOADED_TO_LASERFICHE_WITH_NAME = + 'Document successfully uploaded to Laserfiche with name:'; +const METADATA_FAILED_TO_SAVE_INVALID_FIELD = + 'All metadata failed to save due to at least one invalid field'; const TEMPLATE_FIELDS_NOT_APPLIED = 'The Laserfiche template and fields were not applied to this document.'; const CLOSE = 'Close'; -const GO_TO_FILE = 'Go to File'; -const GO_TO_LIBRARY = 'Go to Library'; -const CLICK_HERE_VIEW_FILE_LASERFICHE = - 'Click here to view the file in Laserfiche'; -const CLICK_HERE_GO_SHAREPOINT_LIBRARY = - 'Click here to go back to your SharePoint library'; +const VIEW_FILE_IN_LASERFICHE = 'View file in Laserfiche'; -export function SavedToLaserficheSuccessDialog(props: { - closeClick: () => Promise; - successfulSave: { - fileLink: string; - pathBack: string; - metadataSaved: boolean; - }; +export function SavedToLaserficheSuccessDialogText(props: { + successfulSave: SavedToLaserficheDocumentData; }) { + React.useEffect(() => { + SPComponentLoader.loadCss( + 'https://cdn.jsdelivr.net/npm/@laserfiche/lf-ui-components@14/cdn/indigo-pink.css' + ); + SPComponentLoader.loadCss( + 'https://cdn.jsdelivr.net/npm/@laserfiche/lf-ui-components@14/cdn/lf-ms-office-lite.css' + ); + }, []); + const metadataFailedNotice: JSX.Element = ( - {DOCUMENT_UPLOADED_METADATA_FAILED} + {METADATA_FAILED_TO_SAVE_INVALID_FIELD}

{TEMPLATE_FIELDS_NOT_APPLIED}

); + return ( + <> +
+ {`${DOCUMENT_SUCCESSFULLY_UPLOADED_TO_LASERFICHE_WITH_NAME} ${props.successfulSave.fileName}.`} + {!props.successfulSave.metadataSaved && metadataFailedNotice} +
+ + ); +} + +export function SavedToLaserficheSuccessDialogButtons(props: { + closeClick: () => Promise; + successfulSave: SavedToLaserficheDocumentData; +}) { + React.useEffect(() => { + SPComponentLoader.loadCss( + 'https://cdn.jsdelivr.net/npm/@laserfiche/lf-ui-components@14/cdn/indigo-pink.css' + ); + SPComponentLoader.loadCss( + 'https://cdn.jsdelivr.net/npm/@laserfiche/lf-ui-components@14/cdn/lf-ms-office-lite.css' + ); + }, []); + function viewFile() { window.open(props.successfulSave.fileLink); } - function redirect() { - Navigation.navigate(props.successfulSave.pathBack, true); - } - return ( <> -
-

- {props.successfulSave.metadataSaved - ? DOCUMENT_UPLOADED - : metadataFailedNotice} -

-
- -
- - {props.successfulSave.fileLink && ( - - )} + {props.successfulSave?.fileLink && ( -
+ )} + ); } diff --git a/src/extensions/savetoLaserfiche/GetDocumentDataDialog.tsx b/src/extensions/savetoLaserfiche/GetDocumentDataDialog.tsx index 677d2f2..0643c6b 100644 --- a/src/extensions/savetoLaserfiche/GetDocumentDataDialog.tsx +++ b/src/extensions/savetoLaserfiche/GetDocumentDataDialog.tsx @@ -34,6 +34,7 @@ import { getSPListURL } from '../../Utils/Funcs'; import SaveToLaserficheCustomDialog from './SaveToLaserficheDialog'; import { BaseComponentContext } from '@microsoft/sp-component-base'; import LoadingDialog from './CommonDialogs'; +import { SPComponentLoader } from '@microsoft/sp-loader'; const signInPageRoute = '/SitePages/LaserficheSpSignIn.aspx'; @@ -73,7 +74,8 @@ export class GetDocumentDataCustomDialog extends BaseDialog { spFileInfo={this.fileInfo} context={this.context} showSaveToDialog={this.showNextDialog} - /> + handleCancelDialog={this.close} + /> ); ReactDOM.render(element, this.domElement); @@ -90,8 +92,11 @@ const FOLLOWING_SP_FIELDS_BLANK_MAPPED_TO_REQUIRED_LF_FIELDS = const PLEASE_FILL_OUT_REQUIRED_FIELDS_TRY_AGAIN = 'Please fill out these required fields and try again.'; +const CANCEL = 'Cancel'; + function GetDocumentDialogData(props: { showSaveToDialog: (fileData: ISPDocumentData) => void; + handleCancelDialog: () => Promise; spFileInfo: { fileName: string; spContentType: string; @@ -117,6 +122,13 @@ function GetDocumentDialogData(props: { )); React.useEffect(() => { + SPComponentLoader.loadCss( + 'https://cdn.jsdelivr.net/npm/@laserfiche/lf-ui-components@14/cdn/indigo-pink.css' + ); + SPComponentLoader.loadCss( + 'https://cdn.jsdelivr.net/npm/@laserfiche/lf-ui-components@14/cdn/lf-ms-office-lite.css' + ); + saveDocumentToLaserficheAsync(); }, []); @@ -428,19 +440,38 @@ function GetDocumentDialogData(props: { } return ( -
-
-
- +
+
+
+ +

Laserfiche

+
+ + +
+ +
{!(missingFields?.length > 0) && } {missingFields?.length > 0 && ( )}
+ +
+ +
); } @@ -456,7 +487,7 @@ function MissingFieldsDialog(props: { missingFields: JSX.Element[] }) { return (
-

{textInside}

+

{textInside}

); } diff --git a/src/extensions/savetoLaserfiche/SaveDocumentToLaserfiche.ts b/src/extensions/savetoLaserfiche/SaveDocumentToLaserfiche.ts index c62040a..8d45b38 100644 --- a/src/extensions/savetoLaserfiche/SaveDocumentToLaserfiche.ts +++ b/src/extensions/savetoLaserfiche/SaveDocumentToLaserfiche.ts @@ -6,6 +6,7 @@ import { FieldToUpdate, ValueToUpdate, PutFieldValsRequest, + Entry, } from '@laserfiche/lf-repository-api-client'; import { RepositoryClientExInternal } from '../../repository-client/repository-client'; import { IRepositoryApiClientExInternal } from '../../repository-client/repository-client-types'; @@ -21,6 +22,7 @@ export interface SavedToLaserficheDocumentData { fileLink: string; pathBack: string; metadataSaved: boolean; + fileName: string; } export class SaveDocumentToLaserfiche { @@ -68,7 +70,10 @@ export class SaveDocumentToLaserfiche { const spFileUrl = this.spFileMetadata.fileUrl; const fileNameWithExt = this.spFileMetadata.fileName; const encodedFileName = encodeURIComponent(fileNameWithExt); - const encodedSpFileUrl = spFileUrl?.replace(fileNameWithExt, encodedFileName); + const encodedSpFileUrl = spFileUrl?.replace( + fileNameWithExt, + encodedFileName + ); const fullSPDataUrl = window.location.origin + encodedSpFileUrl; try { const res = await fetch(fullSPDataUrl, { @@ -153,7 +158,8 @@ export class SaveDocumentToLaserfiche { filenameWithoutExt ); fileName = docNameReplacedWithFileName; - fileNameInEdoc = docNameReplacedWithFileName + `.${fileExtensionWithPeriod}`; + fileNameInEdoc = + docNameReplacedWithFileName + `.${fileExtensionWithPeriod}`; extension = fileExtensionWithPeriod; } const electronicDocument: FileParameter = { @@ -176,9 +182,9 @@ export class SaveDocumentToLaserfiche { const entryId = entryCreateResult.operations.entryCreate.entryId ?? 1; const fileLink = getEntryWebAccessUrl( entryId.toString(), - repoId, webClientUrl, - false + false, + repoId ); const fileUrl = this.spFileMetadata.fileUrl; const fileUrlWithoutDocName = fileUrl.slice(0, fileUrl.lastIndexOf('/')); @@ -193,8 +199,20 @@ export class SaveDocumentToLaserfiche { } else { // TODO what should happen? } + const fileInfo: SavedToLaserficheDocumentData = { + fileLink, + pathBack: path, + metadataSaved: true, + fileName, + }; - return { fileLink, pathBack: path, metadataSaved: true }; + await this.tryUpdateFileNameAsync( + repoClient, + repoId, + entryCreateResult, + fileInfo + ); + return fileInfo; } catch (error) { const conflict409 = error.operations.setFields.exceptions[0].statusCode === 409; @@ -203,9 +221,9 @@ export class SaveDocumentToLaserfiche { const fileLink = getEntryWebAccessUrl( entryId.toString(), - repoId, webClientUrl, - false + false, + repoId ); const fileUrl = this.spFileMetadata.fileUrl; const fileUrlWithoutDocName = fileUrl.slice( @@ -214,7 +232,15 @@ export class SaveDocumentToLaserfiche { ); const path = window.location.origin + fileUrlWithoutDocName; window.localStorage.removeItem(SP_LOCAL_STORAGE_KEY); - return { fileLink, pathBack: path, metadataSaved: false }; + const fileInfo: SavedToLaserficheDocumentData = { + fileLink, + pathBack: path, + metadataSaved: false, + fileName, + }; + + await this.tryUpdateFileNameAsync(repoClient, repoId, error, fileInfo); + return fileInfo; } else { window.alert(`Error uploading file: ${JSON.stringify(error)}`); window.localStorage.removeItem(SP_LOCAL_STORAGE_KEY); @@ -283,16 +309,28 @@ export class SaveDocumentToLaserfiche { const entryId = entryCreateResult.operations.entryCreate.entryId; const fileLink = getEntryWebAccessUrl( entryId.toString(), - repoId, webClientUrl, - false + false, + repoId ); const fileUrl = this.spFileMetadata.fileUrl; const fileUrlWithoutDocName = fileUrl.slice(0, fileUrl.lastIndexOf('/')); const path = window.location.origin + fileUrlWithoutDocName; window.localStorage.removeItem(SP_LOCAL_STORAGE_KEY); - return { fileLink, pathBack: path, metadataSaved: true }; + const fileInfo: SavedToLaserficheDocumentData = { + fileLink, + pathBack: path, + metadataSaved: true, + fileName: fileNameWithExt, + }; + await this.tryUpdateFileNameAsync( + repoClient, + repoId, + entryCreateResult, + fileInfo + ); + return fileInfo; } catch (error) { window.alert(`Error uploading file: ${JSON.stringify(error)}`); window.localStorage.removeItem(SP_LOCAL_STORAGE_KEY); @@ -300,6 +338,24 @@ export class SaveDocumentToLaserfiche { } } + private async tryUpdateFileNameAsync( + repoClient: IRepositoryApiClientExInternal, + repoId: string, + entryCreateResult: CreateEntryResult, + fileInfo: SavedToLaserficheDocumentData + ) { + try { + const entryInfo: Entry = await repoClient.entriesClient.getEntry({ + repoId, + entryId: entryCreateResult.operations.entryCreate.entryId, + }); + + fileInfo.fileName = entryInfo.name; + } catch { + // do nothing, keep default file name + } + } + async deleteSPFileAsync() { const encodedFileName = encodeURIComponent(this.spFileMetadata.fileName); const spUrlWithEncodedFileName = this.spFileMetadata.fileUrl.replace( @@ -349,7 +405,10 @@ export class SaveDocumentToLaserfiche { } } - async replaceFileWithLinkAsync(filenameWithoutExt: string, docFileLink: string) { + async replaceFileWithLinkAsync( + filenameWithoutExt: string, + docFileLink: string + ) { const resp = await fetch( this.spFileMetadata.contextPageAbsoluteUrl + '/_api/contextinfo', { diff --git a/src/extensions/savetoLaserfiche/SaveToLaserficheDialog.tsx b/src/extensions/savetoLaserfiche/SaveToLaserficheDialog.tsx index 4c8d04c..57417ba 100644 --- a/src/extensions/savetoLaserfiche/SaveToLaserficheDialog.tsx +++ b/src/extensions/savetoLaserfiche/SaveToLaserficheDialog.tsx @@ -3,8 +3,14 @@ import { LfLoginComponent } from '@laserfiche/types-lf-ui-components'; import * as React from 'react'; import { ISPDocumentData } from '../../Utils/Types'; import { clientId } from '../../webparts/constants'; -import LoadingDialog, { SavedToLaserficheSuccessDialog } from './CommonDialogs'; -import { SaveDocumentToLaserfiche } from './SaveDocumentToLaserfiche'; +import LoadingDialog, { + SavedToLaserficheSuccessDialogButtons, + SavedToLaserficheSuccessDialogText, +} from './CommonDialogs'; +import { + SaveDocumentToLaserfiche, + SavedToLaserficheDocumentData, +} from './SaveDocumentToLaserfiche'; import styles from './SendToLaserFiche.module.scss'; import { SPComponentLoader } from '@microsoft/sp-loader'; import * as ReactDOM from 'react-dom'; @@ -18,16 +24,18 @@ export default class SaveToLaserficheCustomDialog extends BaseDialog { this.successful = successful; }; - closeClick = async () => { + closeClick = async (success?: SavedToLaserficheDocumentData) => { await this.close(); if (this.closeParent) { - await this.closeParent(); + await this.closeParent(success); } }; constructor( private spFileData: ISPDocumentData, - private closeParent?: () => Promise + private closeParent?: ( + success?: SavedToLaserficheDocumentData + ) => Promise ) { super(); } @@ -56,7 +64,7 @@ export default class SaveToLaserficheCustomDialog extends BaseDialog { function SaveToLaserficheDialog(props: { successSave: (success: boolean) => void; - closeClick: () => Promise; + closeClick: (success?: SavedToLaserficheDocumentData) => Promise; spFileMetadata: ISPDocumentData; }) { const loginComponent = React.createRef< @@ -65,11 +73,11 @@ function SaveToLaserficheDialog(props: { const region = getRegion(); const [success, setSuccess] = React.useState< - { fileLink: string; pathBack: string; metadataSaved: boolean } | undefined + SavedToLaserficheDocumentData | undefined >(); const saveToDialogCloseClick = async () => { - await props.closeClick(); + await props.closeClick(success); }; React.useEffect(() => { @@ -100,31 +108,47 @@ function SaveToLaserficheDialog(props: { }, []); return ( -
-