Skip to content
This repository has been archived by the owner on Mar 14, 2023. It is now read-only.

Commit

Permalink
compressing multiple files jpg and png working
Browse files Browse the repository at this point in the history
  • Loading branch information
clouless committed Dec 29, 2018
1 parent 007ac7b commit 81ba6be
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 80 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kartoffelstampf-client",
"version": "0.1.2",
"version": "2.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
Expand All @@ -19,6 +19,7 @@
"@angular/platform-browser": "7.1.4",
"@angular/platform-browser-dynamic": "7.1.4",
"@angular/router": "7.1.4",
"@cloukit/icon": "^7.0.0",
"anser": "1.2.7",
"core-js": "^2.4.1",
"rxjs": "^6.3.3",
Expand Down
6 changes: 5 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { CloukitIconModule } from '@cloukit/icon';

import { AppComponent } from './app.component';
import { UploadPageComponent } from './upload-page/upload-page.component';
Expand All @@ -11,6 +12,7 @@ import { TerminalOutputComponent } from './terminal-output/terminal-output.compo
import { SpinnerComponent } from './stateless/spinner.component';
import { NumberedHeadlineComponent } from './stateless/numbered-headline.component';
import { ForceRouteReuseStrategy } from './stateless/force-route-reuse-strategy';
import { FileSizePipe } from './stateless/file-size.directive';

const appRoutes: Routes = [
{ path: 'upload', component: UploadPageComponent },
Expand All @@ -29,12 +31,14 @@ const appRoutes: Routes = [
TerminalOutputComponent,
SpinnerComponent,
NumberedHeadlineComponent,
FileSizePipe,
],
imports: [
RouterModule.forRoot(appRoutes, { useHash: true }),
BrowserModule,
FormsModule,
HttpClientModule
HttpClientModule,
CloukitIconModule,
],
providers: [
BackendService,
Expand Down
12 changes: 12 additions & 0 deletions src/app/stateless/file-size.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Pipe, PipeTransform } from '@angular/core';
import { formatNumber } from '@angular/common';


@Pipe({ name: 'fileSize', pure: false })
export class FileSizePipe implements PipeTransform {
transform(size: number) {
const sizeInMegaBytes = size / 1024 / 1024;
const formattedSize = formatNumber(sizeInMegaBytes, 'en_US', '.3');
return `${formattedSize} MB`;
}
}
5 changes: 2 additions & 3 deletions src/app/stateless/spinner.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import { Component } from '@angular/core';
</div>`,
styles: [
`.spinner {
margin: 20px auto 0;
width: 70px;
text-align: center;
}`,
`.spinner > div {
width: 18px;
height: 18px;
width: 12px;
height: 12px;
background-color: #00A200;
border-radius: 100%;
display: inline-block;
Expand Down
26 changes: 11 additions & 15 deletions src/app/terminal-output/terminal-output.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,30 @@ import { TerminalLine } from '../types/kartoffelstampf-client';
styles: [
`.stdout {
width: 90%;
background-color: #555;
background-color: #444;
color: #efefef;
padding: 8px;
border-left: 10px solid green;
padding: 4px 8px;
font-size:12px;
border-left: 4px solid green;
font-family: "Lucida Console", Monaco, monospace;
}`,
`.cmd {
width: 90%;
background-color: #333;
color: #fff;
font-weight:bold;
font-size:14px;
padding: 8px;
border-left: 10px solid #333;
border-left: 4px solid #333;
font-family: "Lucida Console", Monaco, monospace;
}`,
`.stderr {
width: 90%;
background-color: #555;
background-color: #444;
color: #efefef;
padding: 8px;
border-left: 10px solid red;
font-family: "Lucida Console", Monaco, monospace;
}`,
`.processStatus {
width: 90%;
background-color: #555;
color: #efefef;
padding: 8px;
border-left: 10px solid blue;
font-size:12px;
padding: 4px 8px;
border-left: 4px solid red;
font-family: "Lucida Console", Monaco, monospace;
}`,
]
Expand Down
12 changes: 12 additions & 0 deletions src/app/types/kartoffelstampf-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,15 @@ export class TerminalLine {
this.clearLine = this.json.clearLine;
}
}

export class CompressImageJobItem {
terminalLines: TerminalLine[] = [];
uploadedFileBase64URI: string;
originalFileName: string;
temporaryFileName: string;
originalSize: number;
compressedSize: number;
compressDone = false;
downloadClicked = false;
terminalLinesExpanded = false;
}
63 changes: 53 additions & 10 deletions src/app/upload-page/upload-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,57 @@
headline="Compress and Download"
[isActive]="activeStep == 2"
></app-numbered-headline>
<app-spinner *ngIf="originalFileName && !compressDone!"></app-spinner>
<div *ngIf="originalFileName">
<h3>{{originalFileName}}</h3>
<app-terminal-output
[temporaryFileName]="temporaryFileName"
[originalFileName]="originalFileName"
[lines]="terminalLines"
></app-terminal-output>
</div>
<a *ngIf="compressDone == true" [href]="getDownloadUrl()">download</a>
<table *ngIf="activeStep == 2" class="fileTable">
<tr>
<th>File</th>
<th>Original Size</th>
<th>Compressed Size</th>
<th>Saving</th>
<th>Download</th>
</tr>
<ng-container *ngFor="let imageCompressJob of imageCompressJobs">
<tr>
<td class="expandable" (click)="imageCompressJob.terminalLinesExpanded = !imageCompressJob.terminalLinesExpanded">
<cloukit-icon
style="height:24px"
*ngIf="imageCompressJob.terminalLinesExpanded == true"
foregroundIcon="chevronDown"
foregroundIconColor="#777"
></cloukit-icon>
<cloukit-icon
style="height:24px"
*ngIf="imageCompressJob.terminalLinesExpanded == false"
foregroundIcon="chevronRight"
foregroundIconColor="#777"
></cloukit-icon>
<strong>{{imageCompressJob.originalFileName}}</strong>
</td>
<td>{{imageCompressJob.originalSize | fileSize}}</td>
<td>{{imageCompressJob.compressedSize ? (imageCompressJob.compressedSize | fileSize) : '...'}}</td>
<td>
{{imageCompressJob.compressedSize ? (1 - (imageCompressJob.compressedSize / imageCompressJob.originalSize) | percent) : '...'}}
</td>
<td>
<app-spinner *ngIf="!imageCompressJob.compressDone"></app-spinner>
<a
*ngIf="imageCompressJob.compressDone == true"
[href]="getDownloadUrl(imageCompressJob)"
(click)="imageCompressJob.downloadClicked = true"
class="download"
[class.download---clicked]="imageCompressJob.downloadClicked"
download="download"
>download</a>
</td>
</tr>
<tr *ngIf="imageCompressJob.terminalLinesExpanded == true">
<td colspan="5" class="terminal-line-td">
<app-terminal-output
[temporaryFileName]="imageCompressJob.temporaryFileName"
[originalFileName]="imageCompressJob.originalFileName"
[lines]="imageCompressJob.terminalLines"
></app-terminal-output>
</td>
</tr>
</ng-container>
</table>
</div>
94 changes: 59 additions & 35 deletions src/app/upload-page/upload-page.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { BackendService } from '../services/backend.service';
import { KartoffelstampfTerminalOutputEntry, KartoffelstampfCompressInstruction } from '../types/kartoffelstampf-server';
import { TerminalLine } from '../types/kartoffelstampf-client';
import { TerminalLine, CompressImageJobItem } from '../types/kartoffelstampf-client';
import { finalize, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';

Expand All @@ -20,17 +20,33 @@ import { Subject } from 'rxjs';
`.drop-container---drag-over { border-color: #0DFF0D; }`,
`.drop-container---drag-leave { border-color: #ccc; }`,
`.drop-container---drag-drop { border-color: #00A200; }`,
`.fileTable {
width:100%;
}`,
`.fileTable th {
font-weight:bold;
text-align:left;
color:#999;
font-size:12px;
padding-bottom:8px;
}`,
`.download { background-color:#00A200; color:#fff; padding:3px 6px; text-decoration: none; }`,
`.download---clicked { background-color:#777; }`,
`.terminal-line-td { padding:5px 10px 20px 27px; }`,
`.expandable {
cursor: pointer;
display:flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}`,
],
providers: [BackendService]
})
export class UploadPageComponent implements OnInit, OnDestroy {

preDestroy = new Subject<boolean>();
terminalLines: TerminalLine[] = [];
uploadedFileBase64URI: string;
originalFileName: string;
temporaryFileName: string;
compressDone = false;
imageCompressJobs: CompressImageJobItem[] = [];

uiStateDrop = false;
uiStateDragOver = false;
Expand Down Expand Up @@ -84,53 +100,61 @@ export class UploadPageComponent implements OnInit, OnDestroy {
processFileToBase64DataURI(files: FileList) {
const self = this;
if (files && files[0]) {
const fileReader = new FileReader();
self.originalFileName = files[0].name;
fileReader.addEventListener('load', function(loadedEvent: any) {
self.uploadedFileBase64URI = loadedEvent.target.result;
// Upload via backend
self.backendService
.uploadImage(self.uploadedFileBase64URI, 'PNG')
.pipe(
takeUntil(self.preDestroy)
)
.subscribe(uploadResponse => {
console.log(uploadResponse.fileName);
self.temporaryFileName = uploadResponse.fileName;
self.runCompressCommand();
for (let i = 0; i < files.length; i++) {
const file = files[i];
const job = new CompressImageJobItem();
const fileReader = new FileReader();
job.originalFileName = file.name;
job.originalSize = file.size;
fileReader.addEventListener('load', function(loadedEvent: any) {
job.uploadedFileBase64URI = loadedEvent.target.result;
// Upload via backend
self.backendService
.uploadImage(job.uploadedFileBase64URI, 'PNG')
.pipe(
takeUntil(self.preDestroy)
)
.subscribe(uploadResponse => {
job.temporaryFileName = uploadResponse.fileName;
self.imageCompressJobs.push(job);
self.runCompressCommand(job);
});
});
});
fileReader.readAsDataURL(files[0]);
fileReader.readAsDataURL(file);
}
self.activeStep = 2;
}
}

getDownloadUrl() {
return this.backendService.getDownloadUrl(this.temporaryFileName, this.originalFileName);
getDownloadUrl(job: CompressImageJobItem) {
return this.backendService.getDownloadUrl(job.temporaryFileName, job.originalFileName);
}

runCompressCommand() {
runCompressCommand(job: CompressImageJobItem) {
const self = this;
self.backendService.runCompressCommand(<KartoffelstampfCompressInstruction>{
compressType: KartoffelstampfCompressInstruction.COMPRESS_TYPE_LOSSLESS,
temporaryFileName: this.temporaryFileName,
temporaryFileName: job.temporaryFileName,
})
.pipe(
finalize(() => {
console.log('compress-done!');
self.compressDone = true;
job.compressDone = true;
}),
takeUntil(self.preDestroy)
)
.subscribe(data => {
const terminalLine = new TerminalLine(data);
const previousTerminalLine = self.terminalLines[self.terminalLines.length - 1];
if (previousTerminalLine !== undefined &&
previousTerminalLine.clearLine === true &&
terminalLine.clearLine === true) {
self.terminalLines.pop();
if (data.type === 'compressResult') {
job.compressedSize = data.payload['compressedSize'];
} else {
const terminalLine = new TerminalLine(data);
const previousTerminalLine = job.terminalLines[job.terminalLines.length - 1];
if (previousTerminalLine !== undefined &&
previousTerminalLine.clearLine === true &&
terminalLine.clearLine === true) {
job.terminalLines.pop();
}
job.terminalLines.push(terminalLine);
}
self.terminalLines.push(terminalLine);
});
}

Expand Down
23 changes: 8 additions & 15 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,6 @@
"@angular-devkit/core" "7.0.7"
rxjs "6.3.3"

"@angular/[email protected]":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-7.0.0.tgz#b98d7378e84fed1af30c460aa91af4ada2cf252b"
integrity sha512-HX+gIJzST/Nu07ASg1XR583KSEmHI6kUbiSBdq0LqF3mIQgId5z3auBqQcXAgvB0Cg29+/38aj31hnoK/LswEQ==
dependencies:
tslib "^1.7.1"
optionalDependencies:
parse5 "^5.0.0"

"@angular/cli@~7.0.4":
version "7.0.7"
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-7.0.7.tgz#0f4500c5fcf22694c9c40f14d2a5b3dc90fbb4a3"
Expand Down Expand Up @@ -303,6 +294,13 @@
lodash "^4.17.10"
to-fast-properties "^2.0.0"

"@cloukit/icon@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@cloukit/icon/-/icon-7.0.0.tgz#675403d276e817ad5130cac97c360f1952c11647"
integrity sha512-FSrEQwFO1miDOQDT+pneadpa0U0hQAZ26q1dyEW7EjWN0+MDcqpUsABCJyS7ojp519VJuuPxV4FyDMJGLr4jmQ==
dependencies:
tslib "^1.9.0"

"@ngtools/[email protected]":
version "7.0.7"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-7.0.7.tgz#0cd933534a878f25f69448435302c82a861096a6"
Expand Down Expand Up @@ -5131,11 +5129,6 @@ [email protected]:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==

parse5@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==

[email protected]:
version "0.0.5"
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
Expand Down Expand Up @@ -6897,7 +6890,7 @@ tsickle@>=0.29.0:
mkdirp "^0.5.1"
source-map "^0.7.3"

tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
Expand Down

0 comments on commit 81ba6be

Please sign in to comment.