Skip to content
Snippets Groups Projects
Select Git revision
  • aa49911586587fa3a987c2bcdbf0ae648a2265d6
  • main default protected
  • renovate/lock-file-maintenance
  • demo protected
  • person-select-custom
  • dbp-translation-component
  • icon-set-mapping
  • port-i18next-parser
  • remove-sentry
  • favorites-and-recent-files
  • revert-6c632dc6
  • lit2
  • advertisement
  • wc-part
  • automagic
  • publish
  • wip-cleanup
  • demo-file-handling
18 results

.gitmodules

Blame
  • vpu-official-signature-pdf-upload.js 12.23 KiB
    import {createI18nInstance} from './i18n.js';
    import {humanFileSize} from 'vpu-common/i18next.js';
    import {css, html} from 'lit-element';
    import {ScopedElementsMixin} from '@open-wc/scoped-elements';
    import VPUSignatureLitElement from "./vpu-signature-lit-element";
    import * as commonUtils from 'vpu-common/utils';
    import {Icon, MiniSpinner, Button} from 'vpu-common';
    import * as utils from './utils';
    import JSZip from 'jszip/dist/jszip.js';
    import FileSaver from 'file-saver';
    import * as commonStyles from 'vpu-common/styles';
    import {classMap} from 'lit-html/directives/class-map.js';
    import {FileUpload} from 'vpu-file-upload';
    import JSONLD from "vpu-common/jsonld";
    
    const i18n = createI18nInstance();
    
    class OfficialSignaturePdfUpload extends ScopedElementsMixin(VPUSignatureLitElement) {
        constructor() {
            super();
            this.lang = i18n.language;
            this.entryPointUrl = commonUtils.getAPiUrl();
            this.signedFiles = [];
            this.signedFilesCount = 0;
            this.errorFiles = [];
            this.errorFilesCount = 0;
            this.uploadInProgress = false;
            this.uploadStatusFileName = "";
            this.uploadStatusText = "";
    
            // will be set in function update
            this.signingUrl = "";
        }
    
        static get scopedElements() {
            return {
              'vpu-icon': Icon,
              'vpu-fileupload': FileUpload,
              'vpu-mini-spinner': MiniSpinner,
              'vpu-button': Button,
            };
        }
    
        static get properties() {
            return {
                lang: { type: String },
                entryPointUrl: { type: String, attribute: 'entry-point-url' },
                signedFiles: { type: Array, attribute: false },
                signedFilesCount: { type: Number, attribute: false },
                errorFiles: { type: Array, attribute: false },
                errorFilesCount: { type: Number, attribute: false },
                uploadInProgress: { type: Boolean, attribute: false },
                uploadStatusFileName: { type: String, attribute: false },
                uploadStatusText: { type: String, attribute: false },
            };
        }
    
        connectedCallback() {
            super.connectedCallback();
        }
    
        /**
         * @param ev
         */
        onAllUploadStarted(ev) {
            console.log("Start upload process!");
            this.uploadInProgress = true;
        }
    
        /**
         * @param ev
         */
        onFileUploadStarted(ev) {
            console.log(ev);
            this.uploadStatusFileName = ev.detail.fileName;
            this.uploadStatusText = i18n.t('official-pdf-upload.upload-status-file-text', {
                fileName: ev.detail.fileName,
                fileSize: humanFileSize(ev.detail.fileSize, false),
            });
        }
    
        /**
         * @param ev
         */
        onFileUploadFinished(ev) {
            if (ev.detail.status !== 201) {
                // this doesn't seem to trigger an update() execution
                this.errorFiles[Math.floor(Math.random() * 1000000)] = ev.detail;
                // this triggers the correct update() execution
                this.errorFilesCount++;
            } else if (ev.detail.json["@type"] === "http://schema.org/MediaObject" ) {
                // this doesn't seem to trigger an update() execution
                this.signedFiles.push(ev.detail.json);
                // this triggers the correct update() execution
                this.signedFilesCount++;
            }
        }
    
        /**
         * @param ev
         */
        onAllUploadFinished(ev) {
            console.log("Finished upload process!");
            this.uploadInProgress = false;
        }
    
        update(changedProperties) {
            changedProperties.forEach((oldValue, propName) => {
                switch (propName) {
                    case "lang":
                        i18n.changeLanguage(this.lang);
                        break;
                    case "entryPointUrl":
                        JSONLD.initialize(this.entryPointUrl, (jsonld) => {
                            const apiUrlBase = jsonld.getApiUrlForEntityName("OfficiallySignedDocument");
                            this.signingUrl = apiUrlBase + "/sign";
                        });
                        break;
                }
    
                console.log(propName, oldValue);
            });
    
            super.update(changedProperties);
        }
    
        onLanguageChanged(e) {
            this.lang = e.detail.lang;
        }
    
        /**
         * Download signed pdf files as zip
         */
        zipDownloadClickHandler() {
            // see: https://stuk.github.io/jszip/
            let zip = new JSZip();
            const that = this;
            let fileNames = [];
    
            // add all signed pdf files
            this.signedFiles.forEach((file) => {
                let fileName = file.name;
    
                // add pseudo-random string on duplicate file name
                if (fileNames.indexOf(fileName) !== -1) {
                    fileName = utils.baseName(fileName) + "-" + Math.random().toString(36).substring(7) + ".pdf";
                }
    
                fileNames.push(fileName);
                zip.file(fileName, utils.getPDFFileBase64Content(file), {base64: true});
            });
    
            zip.generateAsync({type:"blob"})
                .then(function(content) {
                    FileSaver.saveAs(content, "signed-documents.zip");
    
                    that._("#zip-download-button").stop();
                });
        }
    
        /**
         * Re-Upload all failed files
         */
        reUploadAllClickHandler() {
            const that = this;
    
            // we need to make a copy and reset the queue or else our queue will run crazy
            const errorFilesCopy = {...this.errorFiles};
            this.errorFiles = [];
            this.errorFilesCount = 0;
    
            commonUtils.asyncObjectForEach(errorFilesCopy, async (file, id) => {
                await this.fileUploadClickHandler(file.file, id);
            });
    
            that._("#re-upload-all-button").stop();
        }
    
        /**
         * Download one signed pdf file
         *
         * @param file
         */
        fileDownloadClickHandler(file) {
            const arr = utils.convertDataURIToBinary(file.contentUrl);
            const blob = new Blob([arr], { type: utils.getDataURIContentType(file.contentUrl) });
    
            FileSaver.saveAs(blob, file.name);
        }
    
        /**
         * Uploads a failed pdf file again
         *
         * @param file
         * @param id
         */
        async fileUploadClickHandler(file, id) {
            this.uploadInProgress = true;
            this.errorFiles.splice(id, 1);
            this.errorFilesCount = Object.keys(this.errorFiles).length;
            await this._("#file-upload").uploadFile(file);
            this.uploadInProgress = false;
        }
    
        static get styles() {
            // language=css
            return css`
                ${commonStyles.getThemeCSS()}
                ${commonStyles.getGeneralCSS()}
                ${commonStyles.getButtonCSS()}
                ${commonStyles.getNotificationCSS()}
    
                h2 {
                    margin-bottom: inherit;
                }
    
                .hidden {
                    display: none;
                }
    
                .files-block .file {
                    margin: 10px 0;
                }
    
                .error-files .file {
                    display: grid;
                    grid-template-columns: 40px auto;
                }
    
                .files-block .file .button-box {
                    display: flex;
                    align-items: center;
                }
    
                .files-block .file .info {
                    display: inline-block;
                    vertical-align: middle;
                }
    
                .file .info strong {
                    font-weight: 600;
                }
    
                .notification vpu-mini-spinner {
                    position: relative;
                    top: 2px;
                    margin-right: 5px;
                }
    
                .error {
                    color: #e4154b;
                }
            `;
        }
    
        getSignedFilesHtml() {
            return this.signedFiles.map(file => html`
                <div class="file">
                    <a class="is-download"
                        title="${i18n.t('official-pdf-upload.download-file-button-title')}"
                        @click="${() => {this.fileDownloadClickHandler(file);}}">
                        ${file.name} (${humanFileSize(file.contentSize)}) <vpu-icon name="download"></vpu-icon></a>
                </div>
            `);
        }
    
        getErrorFilesHtml() {
            return this.errorFiles.map((data, id) => html`
                <div class="file">
                    <div class="button-box">
                        <button class="button is-small"
                                title="${i18n.t('official-pdf-upload.re-upload-file-button-title')}"
                                @click="${() => {this.fileUploadClickHandler(data.file, id);}}"><vpu-icon name="reload"></vpu-icon></button>
                    </div>
                    <div class="info">
                        ${data.file.name} (${humanFileSize(data.file.size)})
                        <strong class="error">${data.json["hydra:description"]}</strong>
                    </div>
                </div>
            `);
        }
    
        hasSignaturePermissions() {
            return this._hasSignaturePermissions('ROLE_SCOPE_OFFICIAL-SIGNATURE');
        }
    
        render() {
            return html`
                <div class="${classMap({hidden: !this.isLoggedIn() || !this.hasSignaturePermissions() || this.isLoading()})}">
                    <div class="field">
                        <h2>${i18n.t('official-pdf-upload.upload-field-label')}</h2>
                        <div class="control">
                            <vpu-fileupload id="file-upload" lang="${this.lang}" url="${this.signingUrl}" accept="application/pdf"
                                text="${i18n.t('official-pdf-upload.upload-area-text')}"
                                button-label="${i18n.t('official-pdf-upload.upload-button-label')}"
                                @vpu-fileupload-all-start="${this.onAllUploadStarted}"
                                @vpu-fileupload-file-start="${this.onFileUploadStarted}"
                                @vpu-fileupload-file-finished="${this.onFileUploadFinished}"
                                @vpu-fileupload-all-finished="${this.onAllUploadFinished}"
                                ></vpu-fileupload>
                        </div>
                    </div>
                    <div class="field notification is-info ${classMap({hidden: !this.uploadInProgress})}">
                        <vpu-mini-spinner></vpu-mini-spinner>
                        <strong>${this.uploadStatusFileName}</strong>
                        ${this.uploadStatusText}
                    </div>
                    <div class="files-block field ${classMap({hidden: this.signedFilesCount === 0})}">
                        <h2>${i18n.t('official-pdf-upload.signed-files-label')}</h2>
                        <div class="control">
                            ${this.getSignedFilesHtml()}
                        </div>
                    </div>
                    <div class="field ${classMap({hidden: this.signedFilesCount === 0})}">
                        <div class="control">
                            <vpu-button id="zip-download-button" value="${i18n.t('official-pdf-upload.download-zip-button')}" title="${i18n.t('official-pdf-upload.download-zip-button-tooltip')}" @click="${this.zipDownloadClickHandler}" type="is-primary"></vpu-button>
                        </div>
                    </div>
                    <div class="files-block error-files field ${classMap({hidden: this.errorFilesCount === 0})}">
                        <h2 class="error">${i18n.t('official-pdf-upload.error-files-label')}</h2>
                        <div class="control">
                            ${this.getErrorFilesHtml()}
                        </div>
                    </div>
                    <div class="field ${classMap({hidden: this.errorFilesCount === 0})}">
                        <div class="control">
                            <vpu-button id="re-upload-all-button" ?disabled="${this.uploadInProgress}" value="${i18n.t('official-pdf-upload.re-upload-all-button')}" title="${i18n.t('official-pdf-upload.re-upload-all-button-title')}" @click="${this.reUploadAllClickHandler}" type="is-primary"></vpu-button>
                        </div>
                    </div>
                </div>
                <div class="notification is-warning ${classMap({hidden: this.isLoggedIn() || this.isLoading()})}">
                    ${i18n.t('error-login-message')}
                </div>
                <div class="notification is-danger ${classMap({hidden: this.hasSignaturePermissions() || !this.isLoggedIn() || this.isLoading()})}">
                    ${i18n.t('error-permission-message')}
                </div>
                <div class="${classMap({hidden: !this.isLoading()})}">
                    <vpu-mini-spinner></vpu-mini-spinner>
                </div>
            `;
        }
    }
    
    commonUtils.defineCustomElement('vpu-official-signature-pdf-upload', OfficialSignaturePdfUpload);