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

Commit 81ba6be

Browse files
author
clouless
committed
compressing multiple files jpg and png working
1 parent 007ac7b commit 81ba6be

File tree

9 files changed

+164
-80
lines changed

9 files changed

+164
-80
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "kartoffelstampf-client",
3-
"version": "0.1.2",
3+
"version": "2.0.0",
44
"license": "MIT",
55
"scripts": {
66
"ng": "ng",
@@ -19,6 +19,7 @@
1919
"@angular/platform-browser": "7.1.4",
2020
"@angular/platform-browser-dynamic": "7.1.4",
2121
"@angular/router": "7.1.4",
22+
"@cloukit/icon": "^7.0.0",
2223
"anser": "1.2.7",
2324
"core-js": "^2.4.1",
2425
"rxjs": "^6.3.3",

src/app/app.module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { BrowserModule } from '@angular/platform-browser';
22
import { NgModule } from '@angular/core';
33
import { FormsModule } from '@angular/forms';
44
import { HttpClientModule } from '@angular/common/http';
5+
import { CloukitIconModule } from '@cloukit/icon';
56

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

1517
const appRoutes: Routes = [
1618
{ path: 'upload', component: UploadPageComponent },
@@ -29,12 +31,14 @@ const appRoutes: Routes = [
2931
TerminalOutputComponent,
3032
SpinnerComponent,
3133
NumberedHeadlineComponent,
34+
FileSizePipe,
3235
],
3336
imports: [
3437
RouterModule.forRoot(appRoutes, { useHash: true }),
3538
BrowserModule,
3639
FormsModule,
37-
HttpClientModule
40+
HttpClientModule,
41+
CloukitIconModule,
3842
],
3943
providers: [
4044
BackendService,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Pipe, PipeTransform } from '@angular/core';
2+
import { formatNumber } from '@angular/common';
3+
4+
5+
@Pipe({ name: 'fileSize', pure: false })
6+
export class FileSizePipe implements PipeTransform {
7+
transform(size: number) {
8+
const sizeInMegaBytes = size / 1024 / 1024;
9+
const formattedSize = formatNumber(sizeInMegaBytes, 'en_US', '.3');
10+
return `${formattedSize} MB`;
11+
}
12+
}

src/app/stateless/spinner.component.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ import { Component } from '@angular/core';
1010
</div>`,
1111
styles: [
1212
`.spinner {
13-
margin: 20px auto 0;
1413
width: 70px;
1514
text-align: center;
1615
}`,
1716
`.spinner > div {
18-
width: 18px;
19-
height: 18px;
17+
width: 12px;
18+
height: 12px;
2019
background-color: #00A200;
2120
border-radius: 100%;
2221
display: inline-block;

src/app/terminal-output/terminal-output.component.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,30 @@ import { TerminalLine } from '../types/kartoffelstampf-client';
77
styles: [
88
`.stdout {
99
width: 90%;
10-
background-color: #555;
10+
background-color: #444;
1111
color: #efefef;
12-
padding: 8px;
13-
border-left: 10px solid green;
12+
padding: 4px 8px;
13+
font-size:12px;
14+
border-left: 4px solid green;
1415
font-family: "Lucida Console", Monaco, monospace;
1516
}`,
1617
`.cmd {
1718
width: 90%;
1819
background-color: #333;
1920
color: #fff;
21+
font-weight:bold;
22+
font-size:14px;
2023
padding: 8px;
21-
border-left: 10px solid #333;
24+
border-left: 4px solid #333;
2225
font-family: "Lucida Console", Monaco, monospace;
2326
}`,
2427
`.stderr {
2528
width: 90%;
26-
background-color: #555;
29+
background-color: #444;
2730
color: #efefef;
28-
padding: 8px;
29-
border-left: 10px solid red;
30-
font-family: "Lucida Console", Monaco, monospace;
31-
}`,
32-
`.processStatus {
33-
width: 90%;
34-
background-color: #555;
35-
color: #efefef;
36-
padding: 8px;
37-
border-left: 10px solid blue;
31+
font-size:12px;
32+
padding: 4px 8px;
33+
border-left: 4px solid red;
3834
font-family: "Lucida Console", Monaco, monospace;
3935
}`,
4036
]

src/app/types/kartoffelstampf-client.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,15 @@ export class TerminalLine {
1818
this.clearLine = this.json.clearLine;
1919
}
2020
}
21+
22+
export class CompressImageJobItem {
23+
terminalLines: TerminalLine[] = [];
24+
uploadedFileBase64URI: string;
25+
originalFileName: string;
26+
temporaryFileName: string;
27+
originalSize: number;
28+
compressedSize: number;
29+
compressDone = false;
30+
downloadClicked = false;
31+
terminalLinesExpanded = false;
32+
}

src/app/upload-page/upload-page.component.html

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,57 @@
2626
headline="Compress and Download"
2727
[isActive]="activeStep == 2"
2828
></app-numbered-headline>
29-
<app-spinner *ngIf="originalFileName && !compressDone!"></app-spinner>
30-
<div *ngIf="originalFileName">
31-
<h3>{{originalFileName}}</h3>
32-
<app-terminal-output
33-
[temporaryFileName]="temporaryFileName"
34-
[originalFileName]="originalFileName"
35-
[lines]="terminalLines"
36-
></app-terminal-output>
37-
</div>
38-
<a *ngIf="compressDone == true" [href]="getDownloadUrl()">download</a>
29+
<table *ngIf="activeStep == 2" class="fileTable">
30+
<tr>
31+
<th>File</th>
32+
<th>Original Size</th>
33+
<th>Compressed Size</th>
34+
<th>Saving</th>
35+
<th>Download</th>
36+
</tr>
37+
<ng-container *ngFor="let imageCompressJob of imageCompressJobs">
38+
<tr>
39+
<td class="expandable" (click)="imageCompressJob.terminalLinesExpanded = !imageCompressJob.terminalLinesExpanded">
40+
<cloukit-icon
41+
style="height:24px"
42+
*ngIf="imageCompressJob.terminalLinesExpanded == true"
43+
foregroundIcon="chevronDown"
44+
foregroundIconColor="#777"
45+
></cloukit-icon>
46+
<cloukit-icon
47+
style="height:24px"
48+
*ngIf="imageCompressJob.terminalLinesExpanded == false"
49+
foregroundIcon="chevronRight"
50+
foregroundIconColor="#777"
51+
></cloukit-icon>
52+
<strong>{{imageCompressJob.originalFileName}}</strong>
53+
</td>
54+
<td>{{imageCompressJob.originalSize | fileSize}}</td>
55+
<td>{{imageCompressJob.compressedSize ? (imageCompressJob.compressedSize | fileSize) : '...'}}</td>
56+
<td>
57+
{{imageCompressJob.compressedSize ? (1 - (imageCompressJob.compressedSize / imageCompressJob.originalSize) | percent) : '...'}}
58+
</td>
59+
<td>
60+
<app-spinner *ngIf="!imageCompressJob.compressDone"></app-spinner>
61+
<a
62+
*ngIf="imageCompressJob.compressDone == true"
63+
[href]="getDownloadUrl(imageCompressJob)"
64+
(click)="imageCompressJob.downloadClicked = true"
65+
class="download"
66+
[class.download---clicked]="imageCompressJob.downloadClicked"
67+
download="download"
68+
>download</a>
69+
</td>
70+
</tr>
71+
<tr *ngIf="imageCompressJob.terminalLinesExpanded == true">
72+
<td colspan="5" class="terminal-line-td">
73+
<app-terminal-output
74+
[temporaryFileName]="imageCompressJob.temporaryFileName"
75+
[originalFileName]="imageCompressJob.originalFileName"
76+
[lines]="imageCompressJob.terminalLines"
77+
></app-terminal-output>
78+
</td>
79+
</tr>
80+
</ng-container>
81+
</table>
3982
</div>

src/app/upload-page/upload-page.component.ts

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Component, OnInit, OnDestroy } from '@angular/core';
22
import { BackendService } from '../services/backend.service';
33
import { KartoffelstampfTerminalOutputEntry, KartoffelstampfCompressInstruction } from '../types/kartoffelstampf-server';
4-
import { TerminalLine } from '../types/kartoffelstampf-client';
4+
import { TerminalLine, CompressImageJobItem } from '../types/kartoffelstampf-client';
55
import { finalize, takeUntil } from 'rxjs/operators';
66
import { Subject } from 'rxjs';
77

@@ -20,17 +20,33 @@ import { Subject } from 'rxjs';
2020
`.drop-container---drag-over { border-color: #0DFF0D; }`,
2121
`.drop-container---drag-leave { border-color: #ccc; }`,
2222
`.drop-container---drag-drop { border-color: #00A200; }`,
23+
`.fileTable {
24+
width:100%;
25+
}`,
26+
`.fileTable th {
27+
font-weight:bold;
28+
text-align:left;
29+
color:#999;
30+
font-size:12px;
31+
padding-bottom:8px;
32+
}`,
33+
`.download { background-color:#00A200; color:#fff; padding:3px 6px; text-decoration: none; }`,
34+
`.download---clicked { background-color:#777; }`,
35+
`.terminal-line-td { padding:5px 10px 20px 27px; }`,
36+
`.expandable {
37+
cursor: pointer;
38+
display:flex;
39+
flex-direction: row;
40+
justify-content: flex-start;
41+
align-items: center;
42+
}`,
2343
],
2444
providers: [BackendService]
2545
})
2646
export class UploadPageComponent implements OnInit, OnDestroy {
2747

2848
preDestroy = new Subject<boolean>();
29-
terminalLines: TerminalLine[] = [];
30-
uploadedFileBase64URI: string;
31-
originalFileName: string;
32-
temporaryFileName: string;
33-
compressDone = false;
49+
imageCompressJobs: CompressImageJobItem[] = [];
3450

3551
uiStateDrop = false;
3652
uiStateDragOver = false;
@@ -84,53 +100,61 @@ export class UploadPageComponent implements OnInit, OnDestroy {
84100
processFileToBase64DataURI(files: FileList) {
85101
const self = this;
86102
if (files && files[0]) {
87-
const fileReader = new FileReader();
88-
self.originalFileName = files[0].name;
89-
fileReader.addEventListener('load', function(loadedEvent: any) {
90-
self.uploadedFileBase64URI = loadedEvent.target.result;
91-
// Upload via backend
92-
self.backendService
93-
.uploadImage(self.uploadedFileBase64URI, 'PNG')
94-
.pipe(
95-
takeUntil(self.preDestroy)
96-
)
97-
.subscribe(uploadResponse => {
98-
console.log(uploadResponse.fileName);
99-
self.temporaryFileName = uploadResponse.fileName;
100-
self.runCompressCommand();
103+
for (let i = 0; i < files.length; i++) {
104+
const file = files[i];
105+
const job = new CompressImageJobItem();
106+
const fileReader = new FileReader();
107+
job.originalFileName = file.name;
108+
job.originalSize = file.size;
109+
fileReader.addEventListener('load', function(loadedEvent: any) {
110+
job.uploadedFileBase64URI = loadedEvent.target.result;
111+
// Upload via backend
112+
self.backendService
113+
.uploadImage(job.uploadedFileBase64URI, 'PNG')
114+
.pipe(
115+
takeUntil(self.preDestroy)
116+
)
117+
.subscribe(uploadResponse => {
118+
job.temporaryFileName = uploadResponse.fileName;
119+
self.imageCompressJobs.push(job);
120+
self.runCompressCommand(job);
121+
});
101122
});
102-
});
103-
fileReader.readAsDataURL(files[0]);
123+
fileReader.readAsDataURL(file);
124+
}
104125
self.activeStep = 2;
105126
}
106127
}
107128

108-
getDownloadUrl() {
109-
return this.backendService.getDownloadUrl(this.temporaryFileName, this.originalFileName);
129+
getDownloadUrl(job: CompressImageJobItem) {
130+
return this.backendService.getDownloadUrl(job.temporaryFileName, job.originalFileName);
110131
}
111132

112-
runCompressCommand() {
133+
runCompressCommand(job: CompressImageJobItem) {
113134
const self = this;
114135
self.backendService.runCompressCommand(<KartoffelstampfCompressInstruction>{
115136
compressType: KartoffelstampfCompressInstruction.COMPRESS_TYPE_LOSSLESS,
116-
temporaryFileName: this.temporaryFileName,
137+
temporaryFileName: job.temporaryFileName,
117138
})
118139
.pipe(
119140
finalize(() => {
120-
console.log('compress-done!');
121-
self.compressDone = true;
141+
job.compressDone = true;
122142
}),
123143
takeUntil(self.preDestroy)
124144
)
125145
.subscribe(data => {
126-
const terminalLine = new TerminalLine(data);
127-
const previousTerminalLine = self.terminalLines[self.terminalLines.length - 1];
128-
if (previousTerminalLine !== undefined &&
129-
previousTerminalLine.clearLine === true &&
130-
terminalLine.clearLine === true) {
131-
self.terminalLines.pop();
146+
if (data.type === 'compressResult') {
147+
job.compressedSize = data.payload['compressedSize'];
148+
} else {
149+
const terminalLine = new TerminalLine(data);
150+
const previousTerminalLine = job.terminalLines[job.terminalLines.length - 1];
151+
if (previousTerminalLine !== undefined &&
152+
previousTerminalLine.clearLine === true &&
153+
terminalLine.clearLine === true) {
154+
job.terminalLines.pop();
155+
}
156+
job.terminalLines.push(terminalLine);
132157
}
133-
self.terminalLines.push(terminalLine);
134158
});
135159
}
136160

yarn.lock

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,6 @@
112112
"@angular-devkit/core" "7.0.7"
113113
rxjs "6.3.3"
114114

115-
"@angular/cdk@7.0.0":
116-
version "7.0.0"
117-
resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-7.0.0.tgz#b98d7378e84fed1af30c460aa91af4ada2cf252b"
118-
integrity sha512-HX+gIJzST/Nu07ASg1XR583KSEmHI6kUbiSBdq0LqF3mIQgId5z3auBqQcXAgvB0Cg29+/38aj31hnoK/LswEQ==
119-
dependencies:
120-
tslib "^1.7.1"
121-
optionalDependencies:
122-
parse5 "^5.0.0"
123-
124115
"@angular/cli@~7.0.4":
125116
version "7.0.7"
126117
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-7.0.7.tgz#0f4500c5fcf22694c9c40f14d2a5b3dc90fbb4a3"
@@ -303,6 +294,13 @@
303294
lodash "^4.17.10"
304295
to-fast-properties "^2.0.0"
305296

297+
"@cloukit/icon@^7.0.0":
298+
version "7.0.0"
299+
resolved "https://registry.yarnpkg.com/@cloukit/icon/-/icon-7.0.0.tgz#675403d276e817ad5130cac97c360f1952c11647"
300+
integrity sha512-FSrEQwFO1miDOQDT+pneadpa0U0hQAZ26q1dyEW7EjWN0+MDcqpUsABCJyS7ojp519VJuuPxV4FyDMJGLr4jmQ==
301+
dependencies:
302+
tslib "^1.9.0"
303+
306304
"@ngtools/webpack@7.0.7":
307305
version "7.0.7"
308306
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-7.0.7.tgz#0cd933534a878f25f69448435302c82a861096a6"
@@ -5131,11 +5129,6 @@ parse5@4.0.0:
51315129
resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
51325130
integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
51335131

5134-
parse5@^5.0.0:
5135-
version "5.1.0"
5136-
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
5137-
integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==
5138-
51395132
parseqs@0.0.5:
51405133
version "0.0.5"
51415134
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
@@ -6897,7 +6890,7 @@ tsickle@>=0.29.0:
68976890
mkdirp "^0.5.1"
68986891
source-map "^0.7.3"
68996892

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

0 commit comments

Comments
 (0)