diff --git a/back/pom.xml b/back/pom.xml
index 91fb7a1..b4e6689 100644
--- a/back/pom.xml
+++ b/back/pom.xml
@@ -3,7 +3,7 @@
4.0.0org.karkarideo
- 0.2.0
+ 0.3.03.121
@@ -20,7 +20,7 @@
kangaroo-and-rabbitarchidata
- 0.7.1
+ 0.7.3org.slf4j
diff --git a/back/src/org/kar/karideo/api/MediaResource.java b/back/src/org/kar/karideo/api/MediaResource.java
index 38eaec7..82699a6 100644
--- a/back/src/org/kar/karideo/api/MediaResource.java
+++ b/back/src/org/kar/karideo/api/MediaResource.java
@@ -35,7 +35,6 @@ import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
@Path("/media")
@Produces(MediaType.APPLICATION_JSON)
@@ -63,7 +62,7 @@ public class MediaResource {
@Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Modify a specific Media", tags = "GLOBAL")
public Media patch(@PathParam("id") final Long id, @AsyncType(Media.class) final String jsonRequest) throws Exception {
- System.out.println("update video " + id + " ==> '" + jsonRequest + "'");
+ LOGGER.info("update video {} ==> '{}'", id, jsonRequest);
DataAccess.updateWithJson(Media.class, id, jsonRequest);
return DataAccess.get(Media.class, id);
}
@@ -85,12 +84,19 @@ public class MediaResource {
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@Operation(description = "Create a new Media", tags = "GLOBAL")
- @AsyncType(Media.class)
@TypeScriptProgress
- public Response uploadFile(@FormDataParam("fileName") String fileName, @FormDataParam("universe") String universe, @FormDataParam("series") String series,
- //@FormDataParam("seriesId") String seriesId, Not used ...
- @FormDataParam("season") String season, @FormDataParam("episode") String episode, @FormDataParam("title") String title, @FormDataParam("typeId") String typeId,
- @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws FailException {
+ public Media uploadFile( //
+ @FormDataParam("fileName") String fileName, //
+ @FormDataParam("universe") String universe, //
+ @FormDataParam("series") String series, //
+ //@FormDataParam("seriesId") String seriesId, // Not used ...
+ @FormDataParam("season") String season, //
+ @FormDataParam("episode") String episode, //
+ @FormDataParam("title") String title, //
+ @FormDataParam("typeId") String typeId, //
+ @FormDataParam("file") final InputStream fileInputStream, //
+ @FormDataParam("file") final FormDataContentDisposition fileMetaData //
+ ) throws FailException {
try {
// correct input string stream :
fileName = multipartCorrection(fileName);
@@ -102,16 +108,16 @@ public class MediaResource {
typeId = multipartCorrection(typeId);
//public NodeSmall uploadFile(final FormDataMultiPart form) {
- System.out.println("Upload media file: " + fileMetaData);
- System.out.println(" - fileName: " + fileName);
- System.out.println(" - universe: " + universe);
- System.out.println(" - series: " + series);
- System.out.println(" - season: " + season);
- System.out.println(" - episode: " + episode);
- System.out.println(" - title: " + title);
- System.out.println(" - type: " + typeId);
- System.out.println(" - fileInputStream: " + fileInputStream);
- System.out.println(" - fileMetaData: " + fileMetaData);
+ LOGGER.info("Upload media file: {}", fileMetaData);
+ LOGGER.info(" - fileName: {}", fileName);
+ LOGGER.info(" - universe: {}", universe);
+ LOGGER.info(" - series: {}", series);
+ LOGGER.info(" - season: {}", season);
+ LOGGER.info(" - episode: {}", episode);
+ LOGGER.info(" - title: {}", title);
+ LOGGER.info(" - type: {}", typeId);
+ LOGGER.info(" - fileInputStream: {}", fileInputStream);
+ LOGGER.info(" - fileMetaData: {}", fileMetaData);
System.out.flush();
if (typeId == null) {
throw new InputException("typeId", "TypiId is not specified");
@@ -121,7 +127,7 @@ public class MediaResource {
final String sha512 = DataResource.saveTemporaryFile(fileInputStream, tmpUID);
Data data = DataResource.getWithSha512(sha512);
if (data == null) {
- System.out.println("Need to add the data in the BDD ... ");
+ LOGGER.info("Need to add the data in the BDD ... ");
System.out.flush();
try {
data = DataResource.createNewData(tmpUID, fileName, sha512);
@@ -130,33 +136,33 @@ public class MediaResource {
ex.printStackTrace();
throw new FailException("can not create input media (the data model has an internal error");
}
- } else if (data!= null && data.deleted) {
- System.out.println("Data already exist but deleted");
+ } else if (data!= null && data.deleted != null && data.deleted) {
+ LOGGER.info("Data already exist but deleted");
System.out.flush();
DataTools.undelete(data.id);
data.deleted = false;
} else {
- System.out.println("Data already exist ... all good");
+ LOGGER.info("Data already exist ... all good");
System.out.flush();
}
// Fist step: retieve all the Id of each parents:...
- System.out.println("Find typeNode");
+ LOGGER.info("Find typeNode");
// check if id of type exist:
final Type typeNode = TypeResource.getId(Long.parseLong(typeId));
if (typeNode == null) {
DataResource.removeTemporaryFile(tmpUID);
throw new InputException("typeId", "TypeId does not exist ...");
}
- System.out.println(" ==> " + typeNode);
- System.out.println("Find seriesNode");
+ LOGGER.info(" ==> {}", typeNode);
+ LOGGER.info("Find seriesNode");
// get uid of group:
Series seriesNode = null;
if (series != null) {
seriesNode = SeriesResource.getOrCreate(series, typeNode.id);
}
- System.out.println(" ==> " + seriesNode);
- System.out.println("Find seasonNode");
+ LOGGER.info(" ==> {}", seriesNode);
+ LOGGER.info("Find seasonNode");
// get uid of season:
Season seasonNode = null;
if (seriesNode == null && season != null) {
@@ -167,10 +173,9 @@ public class MediaResource {
seasonNode = SeasonResource.getOrCreate(season, seriesNode.id);
}
- System.out.println(" ==> " + seasonNode);
- System.out.println("add media");
+ LOGGER.info(" ==> {}", seasonNode);
+ LOGGER.info("add media");
- final long uniqueSQLID = -1;
try {
final Media media = new Media();
media.name = title;
@@ -189,17 +194,17 @@ public class MediaResource {
media.episode = Integer.parseInt(episode);
}
final Media out = DataAccess.insert(media);
- DataResource.removeTemporaryFile(tmpUID);
- System.out.println("uploaded .... compleate: " + uniqueSQLID);
- final Media creation = get(uniqueSQLID);
- return Response.ok(creation).build();
+ LOGGER.info("Generate new media {}", out);
+ return out;
} catch (final SQLException ex) {
ex.printStackTrace();
- System.out.println("Catch error:" + ex.getMessage());
+ LOGGER.error("Catch error: {}", ex.getMessage());
throw new FailException("Catch SQLerror ==> check server logs");
+ } finally {
+ DataResource.removeTemporaryFile(tmpUID);
}
} catch (final Exception ex) {
- System.out.println("Catch an unexpected error ... " + ex.getMessage());
+ LOGGER.error("Catch an unexpected error ... {} ", ex.getMessage());
ex.printStackTrace();
throw new FailException("Catch Exception ==> check server logs");
}
diff --git a/back/src/org/kar/karideo/migration/Migration20240226.java b/back/src/org/kar/karideo/migration/Migration20240226.java
index ceda4f8..e088645 100644
--- a/back/src/org/kar/karideo/migration/Migration20240226.java
+++ b/back/src/org/kar/karideo/migration/Migration20240226.java
@@ -119,9 +119,17 @@ public class Migration20240226 extends MigrationSqlStep {
}
}
});
+ /* I am not sure then I prefer keep the primary key for the moment
addAction("""
ALTER TABLE `data` DROP `id`;
""");
+ */
+ addAction("""
+ ALTER TABLE `data` CHANGE `id` `idOld` bigint NOT NULL DEFAULT 0;
+ """);
+ addAction("""
+ ALTER TABLE `data` DROP PRIMARY KEY;
+ """);
addAction("""
ALTER TABLE `data` CHANGE `uuid` `id` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE));
""");
diff --git a/back/src/org/kar/karideo/model/Media.java b/back/src/org/kar/karideo/model/Media.java
index b8aeada..502adf4 100644
--- a/back/src/org/kar/karideo/model/Media.java
+++ b/back/src/org/kar/karideo/model/Media.java
@@ -49,4 +49,13 @@ public class Media extends GenericDataSoftDelete {
// List of Id of the specific covers
@DataJson(targetEntity = Data.class)
public List covers = null;
+
+ @Override
+ public String toString() {
+ return "Media [name=" + this.name + ", description=" + this.description + ", dataId=" + this.dataId + ", typeId=" + this.typeId
+ + ", seriesId=" + this.seriesId + ", seasonId=" + this.seasonId + ", episode=" + this.episode + ", date=" + this.date
+ + ", time=" + this.time + ", ageLimit=" + this.ageLimit + ", covers=" + this.covers + "]";
+ }
+
+
}
diff --git a/front/package.json b/front/package.json
index 0d40e22..6f93373 100644
--- a/front/package.json
+++ b/front/package.json
@@ -19,31 +19,31 @@
},
"private": true,
"dependencies": {
- "@angular/animations": "^17.3.4",
- "@angular/cdk": "^17.3.4",
- "@angular/common": "^17.3.4",
- "@angular/compiler": "^17.3.4",
- "@angular/core": "^17.3.4",
- "@angular/forms": "^17.3.4",
- "@angular/material": "^17.3.4",
- "@angular/platform-browser": "^17.3.4",
- "@angular/platform-browser-dynamic": "^17.3.4",
- "@angular/router": "^17.3.4",
+ "@angular/animations": "^17.3.5",
+ "@angular/cdk": "^17.3.5",
+ "@angular/common": "^17.3.5",
+ "@angular/compiler": "^17.3.5",
+ "@angular/core": "^17.3.5",
+ "@angular/forms": "^17.3.5",
+ "@angular/material": "^17.3.5",
+ "@angular/platform-browser": "^17.3.5",
+ "@angular/platform-browser-dynamic": "^17.3.5",
+ "@angular/router": "^17.3.5",
"rxjs": "^7.8.1",
"zone.js": "^0.14.4",
"zod": "3.22.4",
- "@kangaroo-and-rabbit/kar-cw": "^0.2.0"
+ "@kangaroo-and-rabbit/kar-cw": "^0.2.1"
},
"devDependencies": {
- "@angular-devkit/build-angular": "^17.3.4",
+ "@angular-devkit/build-angular": "^17.3.5",
"@angular-eslint/builder": "17.3.0",
"@angular-eslint/eslint-plugin": "17.3.0",
"@angular-eslint/eslint-plugin-template": "17.3.0",
"@angular-eslint/schematics": "17.3.0",
"@angular-eslint/template-parser": "17.3.0",
- "@angular/cli": "^17.3.4",
- "@angular/compiler-cli": "^17.3.4",
- "@angular/language-service": "^17.3.4",
+ "@angular/cli": "^17.3.5",
+ "@angular/compiler-cli": "^17.3.5",
+ "@angular/language-service": "^17.3.5",
"npm-check-updates": "^16.14.18",
"tslib": "^2.6.2"
}
diff --git a/front/src/app/app.module.ts b/front/src/app/app.module.ts
index 6fc05d5..9acd14d 100644
--- a/front/src/app/app.module.ts
+++ b/front/src/app/app.module.ts
@@ -37,6 +37,7 @@ import { environment } from 'environments/environment';
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { CommonModule } from '@angular/common';
+import { FileDragNDropDirective } from './scene/upload/file-drag-n-drop.directive';
@NgModule({
declarations: [
@@ -58,7 +59,8 @@ import { CommonModule } from '@angular/common';
VideoEditScene,
SeasonEditScene,
SeriesEditScene,
- UploadScene
+ UploadScene,
+ FileDragNDropDirective,
],
imports: [
FormsModule,
diff --git a/front/src/app/back-api/data-resource.ts b/front/src/app/back-api/data-resource.ts
index b18efa3..a12d927 100644
--- a/front/src/app/back-api/data-resource.ts
+++ b/front/src/app/back-api/data-resource.ts
@@ -1,7 +1,7 @@
/**
* API of the server (auto-generated code)
*/
-import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
+import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
import {UUID, } from "./model"
export namespace DataResource {
diff --git a/front/src/app/back-api/front.ts b/front/src/app/back-api/front.ts
index 3744fe7..d478ff9 100644
--- a/front/src/app/back-api/front.ts
+++ b/front/src/app/back-api/front.ts
@@ -1,7 +1,7 @@
/**
* API of the server (auto-generated code)
*/
-import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
+import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
import {} from "./model"
export namespace Front {
diff --git a/front/src/app/back-api/health-check.ts b/front/src/app/back-api/health-check.ts
index c4a8fe7..e87eff3 100644
--- a/front/src/app/back-api/health-check.ts
+++ b/front/src/app/back-api/health-check.ts
@@ -1,7 +1,7 @@
/**
* API of the server (auto-generated code)
*/
-import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
+import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
import {HealthResult, isHealthResult, } from "./model"
export namespace HealthCheck {
diff --git a/front/src/app/back-api/media-resource.ts b/front/src/app/back-api/media-resource.ts
index 4cff95c..b8ed4ed 100644
--- a/front/src/app/back-api/media-resource.ts
+++ b/front/src/app/back-api/media-resource.ts
@@ -1,7 +1,7 @@
/**
* API of the server (auto-generated code)
*/
-import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
+import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
import {UUID, Long, Media, isMedia, } from "./model"
export namespace MediaResource {
@@ -66,33 +66,6 @@ export namespace MediaResource {
data,
}, isMedia);
};
- /**
- * Upload a new season cover media
- */
- export function uploadCover({ restConfig, params, data, progress, }: {
- restConfig: RESTConfig,
- params: {
- id: Long,
- },
- data: {
- fileName: string,
- file: File,
- },
- progress?: ProgressCallback,
- }): Promise {
- return RESTRequestJson({
- restModel: {
- endPoint: "/media/{id}/cover",
- requestType: HTTPRequestModel.POST,
- contentType: HTTPMimeType.MULTIPART,
- accept: HTTPMimeType.JSON,
- },
- restConfig,
- params,
- data,
- progress,
- }, isMedia);
- };
/**
* Get all Media
*/
@@ -108,6 +81,33 @@ export namespace MediaResource {
restConfig,
}, isMedia);
};
+ /**
+ * Upload a new season cover media
+ */
+ export function uploadCover({ restConfig, params, data, callback, }: {
+ restConfig: RESTConfig,
+ params: {
+ id: Long,
+ },
+ data: {
+ fileName: string,
+ file: File,
+ },
+ callback?: RESTCallbacks,
+ }): Promise {
+ return RESTRequestJson({
+ restModel: {
+ endPoint: "/media/{id}/cover",
+ requestType: HTTPRequestModel.POST,
+ contentType: HTTPMimeType.MULTIPART,
+ accept: HTTPMimeType.JSON,
+ },
+ restConfig,
+ params,
+ data,
+ callback,
+ }, isMedia);
+ };
/**
* Remove a specific cover of a media
*/
@@ -132,7 +132,7 @@ export namespace MediaResource {
/**
* Create a new Media
*/
- export function uploadFile({ restConfig, data, progress, }: {
+ export function uploadFile({ restConfig, data, callback, }: {
restConfig: RESTConfig,
data: {
fileName: string,
@@ -144,7 +144,7 @@ export namespace MediaResource {
typeId: string,
title: string,
},
- progress?: ProgressCallback,
+ callback?: RESTCallbacks,
}): Promise {
return RESTRequestJson({
restModel: {
@@ -155,7 +155,7 @@ export namespace MediaResource {
},
restConfig,
data,
- progress,
+ callback,
}, isMedia);
};
}
diff --git a/front/src/app/back-api/model.ts b/front/src/app/back-api/model.ts
index cfadf63..0a0406b 100644
--- a/front/src/app/back-api/model.ts
+++ b/front/src/app/back-api/model.ts
@@ -122,9 +122,9 @@ export function isLocalTime(data: any): data is LocalTime {
export const ZodRestErrorResponse = zod.object({
uuid: ZodUUID.optional(),
- time: zod.string().max(255).optional(),
- error: zod.string().max(255).optional(),
+ name: zod.string().max(255).optional(),
message: zod.string().max(255).optional(),
+ time: zod.string().max(255).optional(),
status: ZodInteger,
statusMessage: zod.string().max(255).optional()
});
diff --git a/front/src/app/back-api/rest-tools.ts b/front/src/app/back-api/rest-tools.ts
index 4180752..d818f57 100644
--- a/front/src/app/back-api/rest-tools.ts
+++ b/front/src/app/back-api/rest-tools.ts
@@ -41,7 +41,7 @@ export interface RESTModel {
accept?: HTTPMimeType;
// Content of the local data.
contentType?: HTTPMimeType;
- // Mode of the TOKEN in urk or Header
+ // Mode of the TOKEN in URL or Header (?token:${tokenInUrl})
tokenInUrl?: boolean;
}
@@ -71,13 +71,28 @@ function isNullOrUndefined(data: any): data is undefined | null {
return data === undefined || data === null;
}
-export type RESTRequestType = {
+// generic progression callback
+export type ProgressCallback = (count: number, total: number) => void;
+
+export interface RESTAbort {
+ abort?: () => boolean
+}
+
+
+// Rest generic callback have a basic model to upload and download advancement.
+export interface RESTCallbacks {
+ progressUpload?: ProgressCallback,
+ progressDownload?: ProgressCallback,
+ abortHandle?: RESTAbort,
+};
+
+export interface RESTRequestType {
restModel: RESTModel,
restConfig: RESTConfig,
data?: any,
params?: object,
queries?: object,
- progress?: ProgressCallback,
+ callback?: RESTCallbacks,
};
function removeTrailingSlashes(input: string): string {
@@ -124,63 +139,91 @@ export function RESTUrl({ restModel, restConfig, params, queries }: RESTRequestT
}
-export type ProgressCallback = (count: number, total: number) => void;
-// input: RequestInfo | URL, init?: RequestInit): Promise;
-export function fetchProgress(generateUrl: string, { method, headers, body }: {
+export function fetchProgress(generateUrl: string, { method, headers, body }: {
method: HTTPRequestModel,
headers: any,
body: any,
-}, progress: ProgressCallback): Promise {
-
- //async function fetchForm(form, options = {}) {
- const action = generateUrl;
- const data = body;
- const xhr = new XMLHttpRequest();
- console.log(`call fetch progress ...`);
+}, { progressUpload, progressDownload, abortHandle }: RESTCallbacks): Promise {
+ const xhr = {
+ io: new XMLHttpRequest()
+ }
return new Promise((resolve, reject) => {
- xhr.responseType = 'blob';
- xhr.onreadystatechange = () => {
- if (xhr.readyState != 4) {
- console.log(` ==> READY state`);
- // done
- return;
- }
- console.log(` ==> has finish ...`);
- const response = new Response(xhr.response, {
- status: xhr.status,
- statusText: xhr.statusText
+ // Stream the upload progress
+ if (progressUpload) {
+ xhr.io.upload.addEventListener("progress", (dataEvent) => {
+ if (dataEvent.lengthComputable) {
+ //console.log(` ==> has a progress event: ${dataEvent.loaded} / ${dataEvent.total}`);
+ progressUpload(dataEvent.loaded, dataEvent.total);
+ }
});
- resolve(response);
}
- // If fail:
- xhr.addEventListener('error', () => {
- console.log(` ==> IS REJECTED`);
+ // Stream the download progress
+ if (progressDownload) {
+ xhr.io.addEventListener("progress", (dataEvent) => {
+ if (dataEvent.lengthComputable) {
+ //console.log(` ==> download progress:: ${dataEvent.loaded} / ${dataEvent.total}`);
+ progressUpload(dataEvent.loaded, dataEvent.total);
+ }
+ });
+ }
+ if (abortHandle) {
+ abortHandle.abort = () => {
+ if (xhr.io) {
+ console.log(`Request abort on the XMLHttpRequest: ${generateUrl}`);
+ xhr.io.abort();
+ return true;
+ }
+ console.log(`Request abort (FAIL) on the XMLHttpRequest: ${generateUrl}`);
+ return false;
+ }
+ }
+ // Check if we have an internal Fail:
+ xhr.io.addEventListener('error', () => {
+ xhr.io = undefined;
reject(new TypeError('Failed to fetch'))
});
- // Link the progression callback
- if (progress) {
- xhr.addEventListener('progress', (dataEvent) => {
- console.log(` ==> has a progress event: ${dataEvent.loaded} / ${dataEvent.total}`);
- progress(dataEvent.loaded, dataEvent.total);
+
+ // Capture the end of the stream
+ xhr.io.addEventListener("loadend", () => {
+ if (xhr.io.readyState !== XMLHttpRequest.DONE) {
+ //console.log(` ==> READY state`);
+ return;
+ }
+ if (xhr.io.status === 0) {
+ //the stream has been aborted
+ reject(new TypeError('Fetch has been aborted'));
+ return;
+ }
+ // Stream is ended, transform in a generic response:
+ const response = new Response(xhr.io.response, {
+ status: xhr.io.status,
+ statusText: xhr.io.statusText
});
- }
- console.log(` ==> open`);
- // open the socket
- xhr.open(method, action, true);
- console.log(` ==> set header`);
- // configure the header
+ const headersArray = xhr.io.getAllResponseHeaders().trim().replaceAll("\r\n", "\n").split('\n');
+ headersArray.forEach(function (header) {
+ const firstColonIndex = header.indexOf(':');
+ if (firstColonIndex !== -1) {
+ var key = header.substring(0, firstColonIndex).trim();
+ var value = header.substring(firstColonIndex + 1).trim();
+ response.headers.set(key, value);
+ } else {
+ response.headers.set(header, "");
+ }
+ });
+ xhr.io = undefined;
+ resolve(response);
+ });
+ xhr.io.open(method, generateUrl, true);
if (!isNullOrUndefined(headers)) {
for (const [key, value] of Object.entries(headers)) {
- xhr.setRequestHeader(key, value as string);
+ xhr.io.setRequestHeader(key, value as string);
}
}
- console.log(` ==> send`);
- xhr.send(data);
- console.log(` ==> send done`);
+ xhr.io.send(body);
});
}
-export function RESTRequest({ restModel, restConfig, data, params, queries, progress }: RESTRequestType): Promise {
+export function RESTRequest({ restModel, restConfig, data, params, queries, callback }: RESTRequestType): Promise {
// Create the URL PATH:
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
let headers: any = {};
@@ -207,21 +250,25 @@ export function RESTRequest({ restModel, restConfig, data, params, queries, prog
}
body = formData
}
- console.log(`Call ${generateUrl}`)
return new Promise((resolve, reject) => {
- let action: Promise = undefined;
- if (isNullOrUndefined(progress)) {
+ let action: undefined | Promise = undefined;
+ if (isNullOrUndefined(callback)
+ || (isNullOrUndefined(callback.progressDownload)
+ && isNullOrUndefined(callback.progressUpload)
+ && isNullOrUndefined(callback.abortHandle))) {
+ // No information needed: call the generic fetch interface
action = fetch(generateUrl, {
method: restModel.requestType,
headers,
body,
});
} else {
+ // need progression information: call old fetch model (XMLHttpRequest) that permit to keep % upload and % download for HTTP1.x
action = fetchProgress(generateUrl, {
- method: restModel.requestType,
+ method: restModel.requestType ?? HTTPRequestModel.GET,
headers,
body,
- }, progress);
+ }, callback);
}
action.then((response: Response) => {
if (response.status >= 200 && response.status <= 299) {
@@ -268,7 +315,7 @@ export function RESTRequest({ restModel, restConfig, data, params, queries, prog
status: 999,
error: error,
statusMessage: "Fetch catch error",
- message: "http-wrapper.ts detect an error in the fetch request"
+ message: "rest-tools.ts detect an error in the fetch request"
});
});
});
diff --git a/front/src/app/back-api/season-resource.ts b/front/src/app/back-api/season-resource.ts
index 4ae90eb..b419678 100644
--- a/front/src/app/back-api/season-resource.ts
+++ b/front/src/app/back-api/season-resource.ts
@@ -1,7 +1,7 @@
/**
* API of the server (auto-generated code)
*/
-import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
+import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
import {UUID, Long, Season, isSeason, } from "./model"
export namespace SeasonResource {
@@ -85,33 +85,6 @@ export namespace SeasonResource {
data,
}, isSeason);
};
- /**
- * Upload a new season cover season
- */
- export function uploadCover({ restConfig, params, data, progress, }: {
- restConfig: RESTConfig,
- params: {
- id: Long,
- },
- data: {
- fileName: string,
- file: File,
- },
- progress?: ProgressCallback,
- }): Promise {
- return RESTRequestJson({
- restModel: {
- endPoint: "/season/{id}/cover",
- requestType: HTTPRequestModel.POST,
- contentType: HTTPMimeType.MULTIPART,
- accept: HTTPMimeType.JSON,
- },
- restConfig,
- params,
- data,
- progress,
- }, isSeason);
- };
/**
* Get a specific Season with his ID
*/
@@ -127,6 +100,33 @@ export namespace SeasonResource {
restConfig,
}, isSeason);
};
+ /**
+ * Upload a new season cover season
+ */
+ export function uploadCover({ restConfig, params, data, callback, }: {
+ restConfig: RESTConfig,
+ params: {
+ id: Long,
+ },
+ data: {
+ fileName: string,
+ file: File,
+ },
+ callback?: RESTCallbacks,
+ }): Promise {
+ return RESTRequestJson({
+ restModel: {
+ endPoint: "/season/{id}/cover",
+ requestType: HTTPRequestModel.POST,
+ contentType: HTTPMimeType.MULTIPART,
+ accept: HTTPMimeType.JSON,
+ },
+ restConfig,
+ params,
+ data,
+ callback,
+ }, isSeason);
+ };
/**
* Remove a specific cover of a season
*/
diff --git a/front/src/app/back-api/series-resource.ts b/front/src/app/back-api/series-resource.ts
index aa2e6b4..daf8157 100644
--- a/front/src/app/back-api/series-resource.ts
+++ b/front/src/app/back-api/series-resource.ts
@@ -1,8 +1,8 @@
/**
* API of the server (auto-generated code)
*/
-import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
-import { UUID, Long, Series, isSeries, } from "./model"
+import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
+import {UUID, Long, Series, isSeries, } from "./model"
export namespace SeriesResource {
/**
@@ -85,33 +85,6 @@ export namespace SeriesResource {
data,
}, isSeries);
};
- /**
- * Upload a new season cover Series
- */
- export function uploadCover({ restConfig, params, data, progress, }: {
- restConfig: RESTConfig,
- params: {
- id: Long,
- },
- data: {
- fileName: string,
- file: File,
- },
- progress?: ProgressCallback,
- }): Promise {
- return RESTRequestJson({
- restModel: {
- endPoint: "/series/{id}/cover",
- requestType: HTTPRequestModel.POST,
- contentType: HTTPMimeType.MULTIPART,
- accept: HTTPMimeType.JSON,
- },
- restConfig,
- params,
- data,
- progress,
- }, isSeries);
- };
/**
* Get all Series
*/
@@ -127,6 +100,33 @@ export namespace SeriesResource {
restConfig,
}, isSeries);
};
+ /**
+ * Upload a new season cover Series
+ */
+ export function uploadCover({ restConfig, params, data, callback, }: {
+ restConfig: RESTConfig,
+ params: {
+ id: Long,
+ },
+ data: {
+ fileName: string,
+ file: File,
+ },
+ callback?: RESTCallbacks,
+ }): Promise {
+ return RESTRequestJson({
+ restModel: {
+ endPoint: "/series/{id}/cover",
+ requestType: HTTPRequestModel.POST,
+ contentType: HTTPMimeType.MULTIPART,
+ accept: HTTPMimeType.JSON,
+ },
+ restConfig,
+ params,
+ data,
+ callback,
+ }, isSeries);
+ };
/**
* Remove a specific Series of a season
*/
diff --git a/front/src/app/back-api/type-resource.ts b/front/src/app/back-api/type-resource.ts
index d2c0683..5fd39be 100644
--- a/front/src/app/back-api/type-resource.ts
+++ b/front/src/app/back-api/type-resource.ts
@@ -1,7 +1,7 @@
/**
* API of the server (auto-generated code)
*/
-import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
+import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
import {UUID, Long, Type, isType, } from "./model"
export namespace TypeResource {
@@ -85,33 +85,6 @@ export namespace TypeResource {
data,
}, isType);
};
- /**
- * Upload a new season cover Type
- */
- export function uploadCover({ restConfig, params, data, progress, }: {
- restConfig: RESTConfig,
- params: {
- id: Long,
- },
- data: {
- fileName: string,
- file: File,
- },
- progress?: ProgressCallback,
- }): Promise {
- return RESTRequestJson({
- restModel: {
- endPoint: "/type/{id}/cover",
- requestType: HTTPRequestModel.POST,
- contentType: HTTPMimeType.MULTIPART,
- accept: HTTPMimeType.JSON,
- },
- restConfig,
- params,
- data,
- progress,
- }, isType);
- };
/**
* Get all Type
*/
@@ -127,6 +100,33 @@ export namespace TypeResource {
restConfig,
}, isType);
};
+ /**
+ * Upload a new season cover Type
+ */
+ export function uploadCover({ restConfig, params, data, callback, }: {
+ restConfig: RESTConfig,
+ params: {
+ id: Long,
+ },
+ data: {
+ fileName: string,
+ file: File,
+ },
+ callback?: RESTCallbacks,
+ }): Promise {
+ return RESTRequestJson({
+ restModel: {
+ endPoint: "/type/{id}/cover",
+ requestType: HTTPRequestModel.POST,
+ contentType: HTTPMimeType.MULTIPART,
+ accept: HTTPMimeType.JSON,
+ },
+ restConfig,
+ params,
+ data,
+ callback,
+ }, isType);
+ };
/**
* Remove a specific cover of a type
*/
diff --git a/front/src/app/back-api/user-media-advancement-resource.ts b/front/src/app/back-api/user-media-advancement-resource.ts
index e27c2d9..e1e264b 100644
--- a/front/src/app/back-api/user-media-advancement-resource.ts
+++ b/front/src/app/back-api/user-media-advancement-resource.ts
@@ -1,7 +1,7 @@
/**
* API of the server (auto-generated code)
*/
-import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
+import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
import {Long, UserMediaAdvancement, MediaInformationsDelta, isUserMediaAdvancement, } from "./model"
export namespace UserMediaAdvancementResource {
diff --git a/front/src/app/back-api/user-resource.ts b/front/src/app/back-api/user-resource.ts
index c254028..872274a 100644
--- a/front/src/app/back-api/user-resource.ts
+++ b/front/src/app/back-api/user-resource.ts
@@ -1,7 +1,7 @@
/**
* API of the server (auto-generated code)
*/
-import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
+import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
import {Long, UserKarideo, UserOut, isUserKarideo, isUserOut, } from "./model"
export namespace UserResource {
diff --git a/front/src/app/scene/season-edit/season-edit.html b/front/src/app/scene/season-edit/season-edit.html
index d995a59..8d25c7d 100644
--- a/front/src/app/scene/season-edit/season-edit.html
+++ b/front/src/app/scene/season-edit/season-edit.html
@@ -147,7 +147,8 @@
[mediaUploaded]="upload.mediaSendSize"
[mediaSize]="upload.mediaSize"
[result]="upload.result"
- [error]="upload.error">
+ [error]="upload.error"
+ (abort)="abortUpload()">
{
self.upload.mediaSendSize = count;
self.upload.mediaSize = total;
- })
+ }, this.cancelHandle)
.then((response: any) => {
self.upload.result = 'Cover added done';
// we retrive the whiole media ==> update data ...
diff --git a/front/src/app/scene/series-edit/series-edit.html b/front/src/app/scene/series-edit/series-edit.html
index ff0e34d..2e9ef27 100644
--- a/front/src/app/scene/series-edit/series-edit.html
+++ b/front/src/app/scene/series-edit/series-edit.html
@@ -171,7 +171,8 @@
[mediaUploaded]="upload.mediaSendSize"
[mediaSize]="upload.mediaSize"
[result]="upload.result"
- [error]="upload.error">
+ [error]="upload.error"
+ (abort)="abortUpload()">
{
self.upload.mediaSendSize = count;
self.upload.mediaSize = total;
- })
+ }, this.cancelHandle)
.then((response: any) => {
self.upload.result = 'Cover added done';
// we retrive the whiole media ==> update data ...
diff --git a/front/src/app/scene/upload/file-drag-n-drop.directive.ts b/front/src/app/scene/upload/file-drag-n-drop.directive.ts
new file mode 100644
index 0000000..a55192a
--- /dev/null
+++ b/front/src/app/scene/upload/file-drag-n-drop.directive.ts
@@ -0,0 +1,44 @@
+import { Directive, HostListener, HostBinding, Output, EventEmitter, Input } from '@angular/core';
+
+@Directive({
+ selector: '[fileDragDrop]'
+})
+export class FileDragNDropDirective {
+ //@Input() private allowed_extensions : Array = ['png', 'jpg', 'bmp'];
+ @Output() private filesChangeEmiter: EventEmitter = new EventEmitter();
+ //@Output() private filesInvalidEmiter : EventEmitter = new EventEmitter();
+ @HostBinding('style.background') private background = '#eee';
+ @HostBinding('style.border') private borderStyle = '2px dashed';
+ @HostBinding('style.border-color') private borderColor = '#696D7D';
+ @HostBinding('style.border-radius') private borderRadius = '10px';
+
+ constructor() { }
+
+ @HostListener('dragover', ['$event']) public onDragOver(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ this.background = 'lightgray';
+ this.borderColor = 'cadetblue';
+ this.borderStyle = '3px solid';
+ }
+
+ @HostListener('dragleave', ['$event']) public onDragLeave(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ this.background = '#eee';
+ this.borderColor = '#696D7D';
+ this.borderStyle = '2px dashed';
+ }
+
+ @HostListener('drop', ['$event']) public onDrop(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ this.background = '#eee';
+ this.borderColor = '#696D7D';
+ this.borderStyle = '2px dashed';
+
+ let files = evt.dataTransfer.files;
+ let valid_files: Array = files;
+ this.filesChangeEmiter.emit(valid_files);
+ }
+}
\ No newline at end of file
diff --git a/front/src/app/scene/upload/upload.html b/front/src/app/scene/upload/upload.html
index 015038a..f44d140 100644
--- a/front/src/app/scene/upload/upload.html
+++ b/front/src/app/scene/upload/upload.html
@@ -3,34 +3,19 @@
Upload Media
-
-
-
-
-
-
-
-
-
format:
-
- The format of the media permit to automatic find meta-data:
- Univers:Series name-sXX-eXX-my name of my media.mkv
- example: Stargate:SG1-s55-e22-Asgard.mkv
-
-
-
-
Media:
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ The format of the media permit to automatic find meta-data:
+ Univers:Series name-sXX-eXX-my name of my media.mkv
+ example: Stargate:SG1-s55-e22-Asgard.mkv
+