Upload snel en slim documenten met PCF Control

Herinner je je de standaard out-of-the-box file uploader in een model driven app?

Ja, deze! Zeer tijdrovend bij het uploaden van 20 documenten. Lees deze blog als je wil leren hoe je een drag-and-drop file uploader kunt maken in PCF control, die kan worden gebruikt in een model driven app.

Inhoudvan deze blog

  1. Dropzone van react-dropzone
  2. Meerdere bestanden vermeld
  3. De lijst controleren
  4. Lijst met bestanden om te uploaden
  5. Record(s) maken in Dataverse

Annotatie maken (note op timeline):

Maak een “activitymimeattachment” aan (bestand naar attachmentsGrid)

Waarom een ​​drag-and-dropzone?

Het gebruik van een drag-and-drop component in een PCF-besturingselement (Power Apps Component Framework) kan helpen bij de gebruikerservaring binnen een model driven app. De FileUploader PCF accepteert het drag-and-drop van bestanden of kan bestanden openen in de bestandsverkenner door erop te klikken. Deze functie zullen gebruikers direct herkennen en mee aan het werk gaan om snel de benodigde bestanden te verzamelen die uiteindelijk vanuit Dataverse kunnen worden geopend.

Voor deze PCF zullen we React gebruiken, zodat we de Microsoft FluentUI-component library kunnen gebruiken.

Stel je PCF in, zorg ervoor dat React is geïnstalleerd en stel de ControlManifest in:

Voeg twee velden toe, de ene bound en de andere als input. Het bound veld is het veld dat is verbonden met het veld in de model driven app. De andere is bedoeld voor de een invoer voor de naam van het veld dat we moeten vernieuwen na de upload. Dit zal waarschijnlijk attachmentsGrid of Timeline zijn.

Stap 1: De Dropzone van React-dropzone

Een Dropzone-component kan worden gemaakt met behulp van het react-dropzone npm-package (npm install react-dropzone). Je kunt meerdere bestanden toevoegen en deze onder de dropzone-component laten weergeven. Zo zie je eenvoudig welke bestanden naar de dropzone zijn gesleept en heb je de mogelijkheid om deze aan te passen voordat je op de uploadknop drukt. Wanneer je de lijst als voltooid beschouwt, wordt de upload gestart door op de uploadknop te drukken.

Maak een nieuwe component en return de volgende code:

            <Dropzone onDropAccepted={acceptedFiles => handleDrop(acceptedFiles)}>
                {({ getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject }) => (
                    <Container {...getRootProps({ isDragActive, isDragAccept, isDragReject })}>
                        <input {...getInputProps()} />
                        <p>Select files...</p>
                    </Container>
                )}
            </Dropzone>

Stap 2: De items vermelden

Wanneer bestanden zijn toegevoegd aan de dropzone, worden ze toegevoegd aan de React Hooks-context door de handleDrop-functie. Deze is gemaakt om de huidige bestanden bij te houden.

    const handleDrop = (acceptedFiles:File[]): void => {
        addAttachment(acceptedFiles);
    }

De functie addAttachment bevindt zich in de FilesContext.

    const addAttachment = async (files: File[]) => {
        try {
            dispatch({ type: ADD_ATTACHMENT, payload: files });
        } catch (error) {
            console.error(error);
        }
    };

Hiermee worden alle bestanden naar de verkleiner verzonden en samengevoegd met de bestanden die al in de lijst staan.

Als de context bestanden bevat, worden de bestanden weergegeven in een FluentUI-detailslijst onder de dropzone.

{files && files.length > 0 &&
                <>
                    <Text variant={"xLarge"} block={true}>Files ready to upload</Text>
                    <DetailsList
                        items={files}
                        columns={columns}
                        compact={true}
                        constrainMode={0}
                        selectionMode={2}
                        checkboxVisibility={2}

                    />
                </>
            }

Stap 3: Controleer of je lijst compleet en correct is

Je kunt items uit de lijst verwijderen als je nog niet tevreden bent met de lijst met bestanden. Door op het delete-icoon achter het bestand te drukken, wordt het bestand uit de context verwijderd.

Stap 4: Breng uw bestanden naar de uploadlijst

Voeg vervolgens een knop toe aan de dropzone-component die de uploadfunctie moet afhandelen. Door op de knop “Uploaden” te drukken, wordt de functie handleUpload geactiveerd om de upload te starten. Het uploaden betekent dat er records worden gemaakt in Dataverse. Er wordt een “activitymimeattachment” gemaakt op basis van het feit of de EntityTypeName van het huidige record “email” of “appointment” is. Als het niet een van deze twee is, wordt een “annotation” -record gemaakt.

Step 5: Dataverse record creation

Als er op de upload button wordt gedrukt start de “createAnnotation” functie. De functie loopt door alle bestanden die zich in de context bevinden. Met deze functie worden de juiste objecten aangemaakt om Dataverse-records correct te maken. Om een ​​record te maken, moet het bestand worden geconverteerd naar een Base64-string, zodat het de “body” correct kan invullen. Daarvoor wordt FileReader gebruikt. Met FileReader kunnen we asynchroon de inhoud lezen van de bestanden die we hebben toegevoegd.

        const toBase64 = async (file: any) => new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = () => resolve(reader.result);
            reader.onabort = () => reject();
            reader.onerror = error => reject(error);
        });

Dan kunnen we de Base64-string aan ons object toevoegen samen met enkele andere eigenschappen om vervolgens de createRecord-functie van de WebApi te af te vuren.

        const createAnnotationRecord = async (file: File): Promise<ComponentFramework.WebApi.Entity | undefined> => {
            const base64Data: string | ArrayBuffer | null = await toBase64(file);

            if (typeof base64Data === 'string') {
                const base64: string = base64Data.replace(/^data:.+;base64,/, '');
                const entitySetName: string = await getMeta();

                const attachmentRecord: ComponentFramework.WebApi.Entity = {
                    filename: file.name,
                    objecttypecode: entity
                }

                if (isActivityMimeAttachment) {
                    attachmentRecord["objectid_activitypointer@odata.bind"] = `/activitypointers(${entityId})`
                    attachmentRecord["body"] = base64;
                } else {
                    attachmentRecord[`objectid_${entity}@odata.bind`] = `/${entitySetName}(${entityId})`;
                    attachmentRecord["documentbody"] = base64;
                }

                if (file.type && file.type !== "") {
                    attachmentRecord["mimetype"] = file.type;
                }

                return attachmentRecord
            }
        }

Eerst wordt de entiteitSetName opgehaald omdat deze nodig is voor een “annotation”. Het kan worden opgehaald uit de context, de volgende functie retourneert het.

const getMeta = async () => context.utils.getEntityMetadata(entity).then((response) => {
            return response.EntitySetName;
        })

Nu we alle benodigde informatie verzameld hebben, kunnen we het object verzenden om het record te maken.

        let successfulUploads: number = 0;
        let unsuccessfulUploads: number = 0;
        let finished = false;

        files.forEach(async (file: File, i: number) => {
            const annotation: ComponentFramework.WebApi.Entity | undefined = await createAnnotationRecord(file);

            if (annotation) {
                await webapi.createRecord(attachmentEntity, annotation).then((res) => {
                    if (res.id) {
                        dispatch({ type: REMOVE_ATTACHMENT, payload: file });
                        successfulUploads++;
                    }
                }).catch((err) => {
                    unsuccessfulUploads++;
                    console.error(err);
                }).finally(() => {
                    if (unsuccessfulUploads === 0 && successfulUploads === files.length) {
                        finished = true;
                    }
                    if(unsuccessfulUploads !== 0) {
                        console.error("There were unsuccessful uploads")
                    }
                })
            }

            if (finished) {
                const control = Xrm.Page.getControl(ioConnector.controlToRefresh);
                // @ts-ignore
                control.refresh();
                setMessage(successfulUploads);
            }
        })

Nadat het record is gemaakt, wordt de context van de bestanden gewist.

We kunnen de control waaraan de bestanden zijn toegevoegd refreshen.

const control = Xrm.Page.getControl(ioConnector.controlToRefresh);
control.refresh();

We kunnen de control vernieuwen waaraan de bestanden zijn toegevoegd Dit is het proces van het maken van bijlagerecords in Dataverse. De bestanden zijn zichtbaar op de notes timeline of in het attachmentsGrid van het huidige record.

Check de code op github voor:

  • De dropzone styling
  • Maak een AppFunctionsContext
  • Een BestandsContext maken
  • Typen
  • Een bericht weergeven wanneer het uploaden is voltooid

Als je deze file uploader wilt gebruiken, zorg er dan voor dat je het van de PCFGallery haalt.

Ik wil dit eindigen met een dank aan ramarao9 voor annotation/activitymimeattachment code.

Meer Relevant Nieuws

Power Automate Connection References

Power Automate Connection References

Het low-code Power Platform maakt het gemakkelijk om verbinding te maken met de wereld, maar dit gemak heeft ook een keerzijde: rommel... Door bijvoorbeeld Power Automates (flows) of Canvas apps te bouwen zal het platform...

Lees meer
Eenvoudig interne registraties automatiseren

Eenvoudig interne registraties automatiseren

In deze blog neem ik jullie mee in een mogelijkheid tot digitalisering van interne events, via jullie standaard Office365 licenties. Wat veel mensen niet weten is dat het Microsoft Power Platform ook de mogelijkheid heeft...

Lees meer

Neem contact op

Accelerate your innovation capacity

Share This