import marked from 'marked'; import {Vue, Component, Prop, Watch} from 'vue-property-decorator'; import {FileData} from '@/interfaces/FileData'; @Component export default class ProcessFile extends Vue { /** * Props */ // The data for the file we are processing @Prop({default: {id: -1, file: '', path: ''}}) public readonly file!: FileData; // The list of available searchers @Prop({default: []}) public readonly searchers!: []; /** * Class members */ // The id of the interval used to query the file status private intervalId!: any; // The content of the file we are processing private fileContent: string = ''; // The processed document content private processedFileContent: string = ''; private processedFileContentPreview: string = ''; private documentDiffIndexes: { [key: string]: Array<{ start: number; end: number; }>; } = {}; // Flag to determine whether the text is processing or not private processing: boolean = false; // Toggles the visibility of the selected searchers sidebar private searchersSidebarVisible: boolean = false; // Toggles the visibility of the available searchers dialog private searchersDialogVisible: boolean = false; // Toggles the visibility of the document upload dialog private uploadDialogVisible: boolean = false; // The list of filters/searchers in a format usable by the datatable // private searchersData: Array<{ id: string; name: string; type: string; }> = []; // The list of filters applied to the selected searchers private searchersFilters: any = []; // The list of selected filters/searchers private selectedSearchers: any = {}; //The list of expanded rows in the selected filters/searchers table private expandedRows: Array = []; // The list of options applied to the searchers (for the moment, only replace_with) private searchersOptions: { [key: string]: string } = {}; // Flag to determine whether or not we will show the diff highlights private showDiffHighlight: boolean = false; private newlySelectedSearchers: Array<{ id: string; name: string; }> = []; /** * */ created() { this.intervalId = setInterval(this.waitForFile, 3000); } /** * MD-to-HTML compiled file content */ get compiledFileContent(): string { return marked(this.fileContent); } /** * MD-to-HTML compiled processed file content */ get compiledProcessedFileContent(): string { return marked(this.processedFileContent); } /** * MD-to-HTML compiled processed file content with diff highlight */ get compiledProcessedFileContentPreview(): string { return marked(this.processedFileContentPreview); } /** * Toggle the sidebar containing the searchers */ private toggleSearchersSidebar() { this.searchersSidebarVisible = !this.searchersSidebarVisible; } /** * Toggle the menu containing the list of available searchers * * @param {string} newValue The new value for the dialog visibility */ private toggleSearchersDialog(newValue?: boolean) { if (typeof newValue !== 'undefined') { this.searchersDialogVisible = newValue; } else { this.searchersDialogVisible = !this.searchersDialogVisible; } if ( ! this.searchersDialogVisible) { for (let selectedSearcher of this.newlySelectedSearchers) { // this.selectedSearchers[selectedSearcher.id] = selectedSearcher; this.$set(this.selectedSearchers, selectedSearcher.id, selectedSearcher); this.expandedRows = Object.values(this.selectedSearchers).filter((p: any) => p.id); } this.newlySelectedSearchers = []; } } /** * Toggle the dialog which lets the user upload a new document * * @param {boolean} newValue */ toggleUploadDialog(newValue?: boolean) { if (typeof newValue !== 'undefined') { this.uploadDialogVisible = newValue; } else { this.uploadDialogVisible = !this.searchersDialogVisible; } } /** * A method which uploads the files to the server for processing * * @param event The event containing the uploaded files information */ public async uploadFile(event: any): Promise { this.$confirm.require({ message: 'You will lose any progress on the current uploaded document. Are you sure you want to proceed?', header: 'Confirmation', icon: 'pi pi-exclamation-triangle', accept: () => { this.fileContent = this.processedFileContent = ''; let file = event.files[0]; this.toggleUploadDialog(false); this.$emit('newFile', file); }, reject: () => { // TODO: Show a message to the user that the action was cancelled. } }); } /** * Wait for the file to be processed in ingest */ private async waitForFile() { const response = await this.$api.getFileData(this.file.id); if (response.content !== null) { if (response.ingest_status === 'fail') { this.$toast.add({ severity: 'error', summary: 'File error', detail: 'THere was an error processing the file in ingest', life: 3000 }); } else { this.fileContent = response.content; this.$toast.add({ severity: 'success', summary: 'File loaded', detail: 'The file has been processed by ingest.', life: 3000 }); clearInterval(this.intervalId); } } } /** * * @param $event */ private onSelectedSearchersReorder($event: any) { Object.assign({}, this.selectedSearchers, $event.value); } private confirmDeleteProduct(searcher: any) { this.$delete(this.selectedSearchers, searcher.id); } /** * Run the searchers */ private async runSearchers() { this.processing = true; this.processedFileContent = ''; let searchers: Array<{ key: string; replace_with: string; }> = []; Object.values(this.selectedSearchers).forEach((searcher: any) => { searchers.push({ 'key': searcher.id, 'replace_with': this.searchersOptions[searcher.id] || '' }); }); const response = await this.$api.filterDocument(this.fileContent, searchers); this.processedFileContent = response.content; this.documentDiffIndexes = response.indexes; this.createDiffPreview(); this.processing = false; } /** * Create the diff preview for the document */ private createDiffPreview() { console.log('CREATING DIFF PREVIEW: ', this.processedFileContent); this.processedFileContentPreview = this.processedFileContent; let indexes: Array<{ start: number; end: number }> = []; for (let searcher in this.documentDiffIndexes) { const searcherIndexes = this.documentDiffIndexes[searcher]; searcherIndexes.forEach(index => { indexes.push(index); }); } indexes.sort((a, b) => { return b.start - a.start; }); this.processedFileContentPreview = indexes.reduce( (r, a) => { r[a.start] = '' + r[a.start]; r[a.end] += ''; return r; }, this.processedFileContent.split('') ).join(''); } /** * Download the document in ODT format */ private async downloadOdt() { let response = await this.$api.convertFile(this.processedFileContent); window.open(`${window.location.origin}/file/download/` + response.path); } /** * Watch the `showDiffHighlight` property for changes * * @param {boolean} newValue * @param {boolean} oldValue */ @Watch('showDiffHighlight') private onDiffHighlightChanged(newValue: boolean, oldValue: boolean): void { // } }