Skip to content

Commit

Permalink
Design change document node (#5240)
Browse files Browse the repository at this point in the history
Co-authored-by: asylves1 <[email protected]>
  • Loading branch information
asylves1 and asylves1 authored Oct 24, 2024
1 parent 160756d commit 22bab3b
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,28 @@
<h6>
<span class="truncate-after-three-lines">{{ documentName }}</span>
</h6>
<tera-operator-placeholder :node="node" />
<tera-operator-placeholder v-if="!thumbnail" :node="node" />
<img v-else class="pdf-thumbnail" :src="thumbnail" alt="Pdf's first page" />

<section class="py-2">
<div v-if="isRunning(extractionStatus)" class="progressbar-container">
<p class="action">
<span v-if="extractionStatus?.progress !== undefined && isRunning(extractionStatus)">
{{ Math.round(extractionStatus?.progress * 100) }}%</span
>
</p>
<ProgressBar
v-if="extractionStatus !== null"
:value="isRunning(extractionStatus) ? extractionStatus.progress * 100 : 0"
/>
<div v-else class="done-container">
<div class="status-msg ok" v-if="isComplete(extractionStatus)">
<i class="pi pi-check-circle" />Completed
</div>
</div>
</div>
<p v-if="isRunning(extractionStatus)" class="action mx-auto">Processing PDF extractions</p>
</section>
<Button label="Open" @click="emit('open-drilldown')" severity="secondary" outlined />
</template>
<template v-else>
Expand All @@ -22,17 +43,20 @@
</template>

<script setup lang="ts">
import { onMounted, ref, watch } from 'vue';
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { cloneDeep, isEmpty } from 'lodash';
import Button from 'primevue/button';
import Dropdown from 'primevue/dropdown';
import type { DocumentAsset, DocumentExtraction, ProjectAsset } from '@/types/Types';
import { AssetType, ExtractionAssetType } from '@/types/Types';
import type { ClientEvent, DocumentAsset, DocumentExtraction, ProjectAsset } from '@/types/Types';
import { AssetType, ExtractionAssetType, ClientEventType, ProgressState } from '@/types/Types';
import { useProjects } from '@/composables/project';
import { getDocumentAsset } from '@/services/document-assets';
import { AssetBlock, WorkflowNode } from '@/types/workflow';
import TeraProgressSpinner from '@/components/widgets/tera-progress-spinner.vue';
import TeraOperatorPlaceholder from '@/components/operator/tera-operator-placeholder.vue';
import ProgressBar from 'primevue/progressbar';
import { subscribe, unsubscribe } from '@/services/ClientEventService';
import type { ExtractionStatusUpdate } from '@/types/common';
import { DocumentOperationState } from './document-operation';
const emit = defineEmits(['open-drilldown', 'update-state', 'append-output']);
Expand All @@ -44,8 +68,15 @@ const documents = useProjects().getActiveProjectAssets(AssetType.Document);
const document = ref<DocumentAsset | null>(null);
const fetchingDocument = ref(false);
const documentName = ref<DocumentAsset['name']>('');
const extractionStatus = ref();
const thumbnail = ref<string | null>(null);
const isRunning = (item) => item?.state === ProgressState.Running;
const isComplete = (item) => item?.status === ProgressState.Complete;
onMounted(async () => {
extractionStatus.value = null;
await subscribe(ClientEventType.ExtractionPdf, subscribeToExtraction);
if (props.node.state.documentId) {
// Quick get the name from the project
documentName.value = useProjects().getAssetName(props.node.state.documentId) || '';
Expand Down Expand Up @@ -125,17 +156,70 @@ watch(
});
}
}
if (document.value?.thumbnail?.length) {
thumbnail.value = `data:image/png;base64, ${document.value.thumbnail}`;
}
},
{ immediate: true }
);
async function subscribeToExtraction(event: ClientEvent<ExtractionStatusUpdate>) {
if (!event.data || event.data.data.documentId !== props.node.state.documentId) return;
extractionStatus.value = event.data;
}
onUnmounted(async () => {
await unsubscribe(ClientEventType.ExtractionPdf, subscribeToExtraction);
});
</script>

<style scoped>
/* Supported by Chromium, Safari, Webkit, Edge and others. Not supported by IE and Opera Mini */
.truncate-after-three-lines {
display: -webkit-box;
line-clamp: 3;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.progressbar-container {
margin-top: var(--gap-2);
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--gap-2);
}
.p-progressbar {
flex-grow: 1;
}
.action {
font-size: var(--font-caption);
color: var(--text-color-secondary);
text-align: center;
}
.pdf-thumbnail {
padding-bottom: var(--gap-2);
border: 1px solid var(--surface-border-light);
border-radius: var(--border-radius-medium);
}
.done-container {
margin-top: var(--gap-2);
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--gap-2);
.status-msg {
display: flex;
gap: var(--gap-2);
font-size: var(--font-caption);
}
.status-msg.ok {
color: var(--primary-color);
}
}
</style>
1 change: 1 addition & 0 deletions packages/client/hmi-client/src/types/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ export interface DocumentAsset extends TerariumAsset {
*/
assets?: DocumentExtraction[];
extractions?: ExtractedDocumentPage[];
thumbnail?: any;
}

export interface ExternalPublication extends TerariumAsset {
Expand Down
2 changes: 1 addition & 1 deletion packages/server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation 'com.github.ben-manes.caffeine:caffeine:3.1.8'

implementation 'org.apache.pdfbox:pdfbox:3.0.2'

implementation(platform("software.amazon.awssdk:bom:2.21.26"))
implementation("software.amazon.awssdk:s3")
Expand Down
4 changes: 4 additions & 0 deletions packages/server/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ com.zaxxer:HikariCP:5.0.1=aotCompileClasspath,aotTestCompileClasspath,compileCla
commons-codec:commons-codec:1.15=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-fileupload:commons-fileupload:1.5=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-io:commons-io:2.17.0=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-logging:commons-logging:1.3.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
edu.ucar:cdm-core:5.5.3=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
edu.ucar:httpservices:5.5.3=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
edu.ucar:udunits:5.5.3=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
Expand Down Expand Up @@ -189,6 +190,9 @@ org.apache.lucene:lucene-queryparser:8.11.3=aotCompileClasspath,aotTestCompileCl
org.apache.lucene:lucene-sandbox:8.11.3=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.lucene:lucene-spatial3d:8.11.3=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.lucene:lucene-suggest:8.11.3=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.pdfbox:fontbox:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.pdfbox:pdfbox-io:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.pdfbox:pdfbox:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.tomcat.embed:tomcat-embed-core:10.1.15=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.tomcat.embed:tomcat-embed-el:10.1.15=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.tomcat.embed:tomcat-embed-websocket:10.1.15=aotCompileClasspath,aotTestCompileClasspath,compileClasspath,nativeImageClasspath,nativeImageTestClasspath,processAotClasspath,processTestAotClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -362,16 +369,68 @@ private ResponseEntity<Void> uploadDocumentHelper(
try {
// upload file to S3
final Integer status = documentAssetService.uploadFile(documentId, fileName, fileEntity);
final Optional<DocumentAsset> document = documentAssetService.getAsset(documentId, permission);

if (document.isPresent()) {
Graphics2D g2d = null;
ByteArrayOutputStream outputStream = null;
PDDocument pdfDocument = null;

try {
// Convert BufferedImage to byte[]
pdfDocument = Loader.loadPDF(fileEntity.getContent().readAllBytes());
PDFRenderer pdfRenderer = new PDFRenderer(pdfDocument);
BufferedImage firstPageImage = pdfRenderer.renderImageWithDPI(0, 100);

int height = firstPageImage.getHeight();
int width = firstPageImage.getWidth();
int topHalfHeight = height / 2;

// Create a sub-image (top half)
BufferedImage topHalfImage = firstPageImage.getSubimage(0, 0, width, topHalfHeight);

// Resize the image to a width of 225px while maintaining aspect ratio
int newWidth = 225;
int newHeight = (newWidth * topHalfHeight) / width; // Maintain the aspect ratio

// Create a new BufferedImage for the resized image
Image resizedImage = topHalfImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
BufferedImage resizedBufferedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);

g2d = resizedBufferedImage.createGraphics();
g2d.drawImage(resizedImage, 0, 0, null);

outputStream = new ByteArrayOutputStream();
ImageIO.write(resizedBufferedImage, "png", outputStream);

byte[] thumbnailBytes = outputStream.toByteArray();
document.get().setThumbnail(thumbnailBytes);

documentAssetService.updateAsset(document.get(), projectId, permission);
} catch (final Exception e) {
final String error = "Unable to create thumbnail";
log.error(error, e);
} finally {
if (g2d != null) {
g2d.dispose();
}
if (outputStream != null) {
outputStream.close();
}
if (pdfDocument != null) {
pdfDocument.close();
}
}
}

// if the fileEntity is not a PDF, then we need to extract the text and update
// the document asset
if (!DownloadService.IsPdf(fileEntity.getContent().readAllBytes())) {
final Optional<DocumentAsset> document = documentAssetService.getAsset(documentId, permission);
if (document.isEmpty()) {
return ResponseEntity.notFound().build();
}

document.get().setText(IOUtils.toString(fileEntity.getContent(), StandardCharsets.UTF_8));

documentAssetService.updateAsset(document.get(), projectId, permission);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Lob;
import jakarta.persistence.OneToOne;
import java.io.Serial;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.annotations.Type;
import software.uncharted.terarium.hmiserver.annotations.TSModel;
import software.uncharted.terarium.hmiserver.annotations.TSOptional;
Expand Down Expand Up @@ -76,6 +79,11 @@ public class DocumentAsset extends TerariumAsset {
@Column(columnDefinition = "json")
private List<ExtractedDocumentPage> extractions = new ArrayList<>();

@TSOptional
@Lob
@JdbcTypeCode(Types.BINARY)
private byte[] thumbnail;

@Override
public List<String> getFileNames() {
if (this.fileNames == null) {
Expand Down

0 comments on commit 22bab3b

Please sign in to comment.