[DEV] add drag & drop
This commit is contained in:
parent
334d68ac1f
commit
d8ceaef3f9
@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.kar</groupId>
|
||||
<artifactId>karideo</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
<properties>
|
||||
<maven.compiler.version>3.1</maven.compiler.version>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
@ -20,7 +20,7 @@
|
||||
<dependency>
|
||||
<groupId>kangaroo-and-rabbit</groupId>
|
||||
<artifactId>archidata</artifactId>
|
||||
<version>0.7.1</version>
|
||||
<version>0.7.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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));
|
||||
""");
|
||||
|
@ -49,4 +49,13 @@ public class Media extends GenericDataSoftDelete {
|
||||
// List of Id of the specific covers
|
||||
@DataJson(targetEntity = Data.class)
|
||||
public List<UUID> 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 + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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<Media> {
|
||||
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<Media> {
|
||||
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<Media> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -155,7 +155,7 @@ export namespace MediaResource {
|
||||
},
|
||||
restConfig,
|
||||
data,
|
||||
progress,
|
||||
callback,
|
||||
}, isMedia);
|
||||
};
|
||||
}
|
||||
|
@ -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()
|
||||
});
|
||||
|
@ -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<Response>;
|
||||
export function fetchProgress<TYPE>(generateUrl: string, { method, headers, body }: {
|
||||
export function fetchProgress(generateUrl: string, { method, headers, body }: {
|
||||
method: HTTPRequestModel,
|
||||
headers: any,
|
||||
body: any,
|
||||
}, progress: ProgressCallback): Promise<Response> {
|
||||
|
||||
//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<Response> {
|
||||
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;
|
||||
// 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);
|
||||
}
|
||||
console.log(` ==> has finish ...`);
|
||||
const response = new Response(xhr.response, {
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText
|
||||
});
|
||||
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;
|
||||
}
|
||||
console.log(` ==> open`);
|
||||
// open the socket
|
||||
xhr.open(method, action, true);
|
||||
console.log(` ==> set header`);
|
||||
// configure the header
|
||||
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
|
||||
});
|
||||
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<ModelResponseHttp> {
|
||||
export function RESTRequest({ restModel, restConfig, data, params, queries, callback }: RESTRequestType): Promise<ModelResponseHttp> {
|
||||
// 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<Response> = undefined;
|
||||
if (isNullOrUndefined(progress)) {
|
||||
let action: undefined | Promise<Response> = 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"
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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<Season> {
|
||||
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<Season> {
|
||||
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
|
||||
*/
|
||||
|
@ -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<Series> {
|
||||
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<Series> {
|
||||
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
|
||||
*/
|
||||
|
@ -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<Type> {
|
||||
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<Type> {
|
||||
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
|
||||
*/
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -147,7 +147,8 @@
|
||||
[mediaUploaded]="upload.mediaSendSize"
|
||||
[mediaSize]="upload.mediaSize"
|
||||
[result]="upload.result"
|
||||
[error]="upload.error"></upload-progress>
|
||||
[error]="upload.error"
|
||||
(abort)="abortUpload()"></upload-progress>
|
||||
<delete-confirm
|
||||
[comment]="confirmDeleteComment"
|
||||
[imageUrl]=confirmDeleteImageUrl
|
||||
|
@ -7,6 +7,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PopInService, UploadProgress, isNumberFinite } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Season, UUID } from 'app/back-api';
|
||||
import { RESTAbort } from 'app/back-api/rest-tools';
|
||||
|
||||
import { SeasonService, ArianeService, DataService } from 'app/service';
|
||||
|
||||
@ -29,11 +30,11 @@ export class SeasonEditScene implements OnInit {
|
||||
|
||||
error: string = '';
|
||||
|
||||
numberVal: number = null;
|
||||
numberVal: string = null;
|
||||
description: string = '';
|
||||
coverFile: File;
|
||||
coverFile?: File;
|
||||
uploadFileValue: string = '';
|
||||
selectedFiles: FileList;
|
||||
selectedFiles?: FileList;
|
||||
videoCount: string = null;
|
||||
|
||||
|
||||
@ -45,6 +46,7 @@ export class SeasonEditScene implements OnInit {
|
||||
public confirmDeleteImageUrl: string = null;
|
||||
private deleteCoverId: UUID = null;
|
||||
private deleteItemId: number = null;
|
||||
cancelHandle: RESTAbort = {};
|
||||
deleteConfirmed() {
|
||||
if (this.deleteCoverId !== null) {
|
||||
this.removeCoverAfterConfirm(this.deleteCoverId);
|
||||
@ -147,6 +149,10 @@ export class SeasonEditScene implements OnInit {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
abortUpload(): void {
|
||||
this.cancelHandle.abort();
|
||||
}
|
||||
|
||||
// At the file input element
|
||||
// (change)="selectFile($event)"
|
||||
onChangeCover(value: any): void {
|
||||
@ -169,7 +175,7 @@ export class SeasonEditScene implements OnInit {
|
||||
this.seasonService.uploadCover(this.idSeason, file, (count, total) => {
|
||||
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 ...
|
||||
|
@ -171,7 +171,8 @@
|
||||
[mediaUploaded]="upload.mediaSendSize"
|
||||
[mediaSize]="upload.mediaSize"
|
||||
[result]="upload.result"
|
||||
[error]="upload.error"></upload-progress>
|
||||
[error]="upload.error"
|
||||
(abort)="abortUpload()"></upload-progress>
|
||||
<delete-confirm
|
||||
[comment]="confirmDeleteComment"
|
||||
[imageUrl]=confirmDeleteImageUrl
|
||||
|
@ -7,6 +7,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PopInService, UploadProgress } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { UUID } from 'app/back-api';
|
||||
import { RESTAbort } from 'app/back-api/rest-tools';
|
||||
|
||||
import { SeriesService, DataService, TypeService, ArianeService } from 'app/service';
|
||||
|
||||
@ -55,6 +56,7 @@ export class SeriesEditScene implements OnInit {
|
||||
public confirmDeleteImageUrl: string = null;
|
||||
private deleteCoverId: UUID = null;
|
||||
private deleteItemId: number = null;
|
||||
cancelHandle: RESTAbort = {};
|
||||
deleteConfirmed() {
|
||||
if (this.deleteCoverId !== null) {
|
||||
this.removeCoverAfterConfirm(this.deleteCoverId);
|
||||
@ -129,6 +131,10 @@ export class SeriesEditScene implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
abortUpload(): void {
|
||||
this.cancelHandle.abort();
|
||||
}
|
||||
|
||||
updateCoverList(covers: any) {
|
||||
this.coversDisplay = [];
|
||||
if (covers !== undefined && covers !== null) {
|
||||
@ -208,7 +214,7 @@ export class SeriesEditScene implements OnInit {
|
||||
this.seriesService.uploadCover(this.idSeries, file, (count, total) => {
|
||||
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 ...
|
||||
|
44
front/src/app/scene/upload/file-drag-n-drop.directive.ts
Normal file
44
front/src/app/scene/upload/file-drag-n-drop.directive.ts
Normal file
@ -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<string> = ['png', 'jpg', 'bmp'];
|
||||
@Output() private filesChangeEmiter: EventEmitter<File[]> = new EventEmitter();
|
||||
//@Output() private filesInvalidEmiter : EventEmitter<File[]> = 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<File> = files;
|
||||
this.filesChangeEmiter.emit(valid_files);
|
||||
}
|
||||
}
|
@ -3,34 +3,19 @@
|
||||
Upload Media
|
||||
</div>
|
||||
<div class="clear"><br/></div>
|
||||
<div class="request_raw_table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style="width:10%">
|
||||
<col style="width:80%">
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="left-colomn">format:</td>
|
||||
<td class="right-colomn">
|
||||
<div class="request_raw_table drop-area" fileDragDrop
|
||||
(filesChangeEmiter)="onChangeFile($event)">
|
||||
<div class="clear"><br/></div>
|
||||
<div class="centered">
|
||||
<input type="file" name="file" id="file" (change)="onChangeFile($event.target.files)" multiple>
|
||||
<label for="file"><span class="textLink"><span class="material-icons">cloud_upload</span> Select your file</span> or <i>Drop it here!</i></label>
|
||||
</div>
|
||||
<div class="clear"><br/></div>
|
||||
<div class="centered">
|
||||
The format of the media permit to automatic find meta-data:<br/>
|
||||
Univers:Series name-sXX-eXX-my name of my media.mkv<br/>
|
||||
<b>example:</b> Stargate:SG1-s55-e22-Asgard.mkv <br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="left-colomn">Media:</td>
|
||||
<td class="right-colomn">
|
||||
<input type="file"
|
||||
(change)="onChangeFile($event.target)"
|
||||
placeholder="Select a media file"
|
||||
accept=".mkv,.webm"
|
||||
width="90%"
|
||||
multiple/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@if(parsedElement.length !== 0) {
|
||||
<div class="title">
|
||||
@ -210,11 +195,13 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<upload-progress [mediaTitle]="upload.labelMediaTitle"
|
||||
<upload-progress
|
||||
[mediaTitle]="upload.labelMediaTitle"
|
||||
[mediaUploaded]="upload.mediaSendSize"
|
||||
[mediaSize]="upload.mediaSize"
|
||||
[result]="upload.result"
|
||||
[error]="upload.error"></upload-progress>
|
||||
[error]="upload.error"
|
||||
(abort)="abortUpload()"></upload-progress>
|
||||
|
||||
<!--
|
||||
TODO: add a pop-in with:
|
||||
|
@ -1,43 +1,79 @@
|
||||
|
||||
|
||||
.title {
|
||||
//background-color: green;
|
||||
font-size: 45px;
|
||||
font-weight: bold;
|
||||
line-height: 60px;
|
||||
width:100%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
margin: 10px 0 10px 0;
|
||||
text-shadow: 1px 1px 2px white, 0 0 1em white, 0 0 0.2em white;
|
||||
text-transform: uppercase;
|
||||
font-family: "Roboto","Helvetica","Arial",sans-serif;
|
||||
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
.drop-area {
|
||||
height: 230px;
|
||||
display: table;
|
||||
width: 100%;
|
||||
background-color: #eee;
|
||||
border: dotted 1px #aaa;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.text-wrapper {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.centered {
|
||||
font-family: sans-serif;
|
||||
font-size: 1.3em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.textLink {
|
||||
background-color: #217500;
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
}
|
||||
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.request_raw_table {
|
||||
display: block;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.left-colomn {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
|
||||
input {
|
||||
width: 95%;
|
||||
font-size: 20px;
|
||||
border: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.right-colomn {
|
||||
input {
|
||||
width: 95%;
|
||||
font-size: 20px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
select {
|
||||
width: 95%;
|
||||
font-size: 20px;
|
||||
@ -45,11 +81,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
border-color: rgba(200,0,0,1.0);
|
||||
background-color: rgba(256,220,220,1.0);
|
||||
border-color: rgba(200, 0, 0, 1.0);
|
||||
background-color: rgba(256, 220, 220, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
.send_value {
|
||||
width: 300px;
|
||||
margin: 0 auto;
|
||||
|
@ -7,6 +7,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PopInService, UploadProgress } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Series } from 'app/back-api';
|
||||
import { RESTAbort } from 'app/back-api/rest-tools';
|
||||
|
||||
import { TypeService, SeriesService, MediaService, SeasonService } from 'app/service';
|
||||
|
||||
@ -51,7 +52,7 @@ export class UploadScene implements OnInit {
|
||||
selectedFiles: FileList;
|
||||
typeId: number = null;
|
||||
seriesId: number = null;
|
||||
saisonId: number = null;
|
||||
seasonId: number = null;
|
||||
needSend: boolean = false;
|
||||
|
||||
// list of all files already registered in the bdd to compare with the current list of files.
|
||||
@ -92,12 +93,14 @@ export class UploadScene implements OnInit {
|
||||
];
|
||||
globalSeries: string = '';
|
||||
globalSeason: number = null;
|
||||
cancelHandle: RESTAbort = {};
|
||||
constructor(
|
||||
private MediaService: MediaService,
|
||||
private seasonService: SeasonService,
|
||||
private seriesService: SeriesService,
|
||||
private typeService: TypeService,
|
||||
private popInService: PopInService) {
|
||||
private popInService: PopInService,
|
||||
) {
|
||||
// nothing to do.
|
||||
}
|
||||
|
||||
@ -238,7 +241,7 @@ export class UploadScene implements OnInit {
|
||||
|
||||
this.typeId = null;
|
||||
this.seriesId = null;
|
||||
this.saisonId = null;
|
||||
this.seasonId = null;
|
||||
this.listSeries = [{ value: null, label: '---' }];
|
||||
this.listSeason = [{ value: null, label: '---' }];
|
||||
}
|
||||
@ -302,7 +305,7 @@ export class UploadScene implements OnInit {
|
||||
if (isNaN(season)) {
|
||||
season = null;
|
||||
}
|
||||
// remove extention
|
||||
// remove extension
|
||||
title = title.replace(new RegExp('\\.(mkv|MKV|Mkv|webm|WEBM|Webm|mp4)'), '');
|
||||
let tmp = new FileParsedElement(file, series, season, episode, title);
|
||||
console.log(`==>${JSON.stringify(tmp)}`);
|
||||
@ -310,14 +313,13 @@ export class UploadScene implements OnInit {
|
||||
this.parsedElement.push(tmp);
|
||||
}
|
||||
|
||||
|
||||
// At the file input element
|
||||
// (change)="selectFile($event)"
|
||||
onChangeFile(value: any): void {
|
||||
onChangeFile(files: File[]): void {
|
||||
this.clearData();
|
||||
|
||||
for (let iii = 0; iii < value.files.length; iii++) {
|
||||
this.addFileWithMetaData(value.files[iii]);
|
||||
for (let iii = 0; iii < files.length; iii++) {
|
||||
this.addFileWithMetaData(files[iii]);
|
||||
}
|
||||
// check if all global parameters are generic:
|
||||
if (this.parsedElement.length === 0) {
|
||||
@ -350,7 +352,7 @@ export class UploadScene implements OnInit {
|
||||
|
||||
this.updateNeedSend();
|
||||
this.seriesId = null;
|
||||
this.saisonId = null;
|
||||
this.seasonId = null;
|
||||
let self = this;
|
||||
if (this.globalSeries !== '') {
|
||||
this.seriesService.getLike(this.globalSeries)
|
||||
@ -362,9 +364,9 @@ export class UploadScene implements OnInit {
|
||||
if (response.length === 0) {
|
||||
self.seriesId = null;
|
||||
} else if (response.length === 1) {
|
||||
let serieElem = response[0];
|
||||
self.seriesId = serieElem.id;
|
||||
self.updateType(serieElem.parentId);
|
||||
let seriesElem = response[0];
|
||||
self.seriesId = seriesElem.id;
|
||||
self.updateType(seriesElem.parentId);
|
||||
}
|
||||
self.updateListOfVideoToCheck();
|
||||
}).catch((response) => {
|
||||
@ -392,10 +394,11 @@ export class UploadScene implements OnInit {
|
||||
self.upload.result = 'Media creation done';
|
||||
}
|
||||
}, (value: string) => {
|
||||
console.log("Detect error from serveur ...********************");
|
||||
self.upload.error = `Error in the upload of the data...${value}`;
|
||||
});
|
||||
}
|
||||
uploadFile(eleemnent: FileParsedElement, id: number, total: number, sendDone: any, errorOccured: any): void {
|
||||
uploadFile(element: FileParsedElement, id: number, total: number, sendDone: () => void, errorOccurred: (string) => void): void {
|
||||
let self = this;
|
||||
|
||||
self.upload.labelMediaTitle = '';
|
||||
@ -414,37 +417,38 @@ export class UploadScene implements OnInit {
|
||||
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}s${self.globalSeason.toString()}`;
|
||||
}
|
||||
// add episode ID
|
||||
if (eleemnent.episode !== null && eleemnent.episode !== undefined && eleemnent.episode.toString().length !== 0) {
|
||||
if (element.episode !== null && element.episode !== undefined && element.episode.toString().length !== 0) {
|
||||
if (self.upload.labelMediaTitle.length !== 0) {
|
||||
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}-`;
|
||||
}
|
||||
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}e${eleemnent.episode.toString()}`;
|
||||
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}e${element.episode.toString()}`;
|
||||
}
|
||||
// add title
|
||||
if (self.upload.labelMediaTitle.length !== 0) {
|
||||
self.upload.labelMediaTitle = `${self.upload.labelMediaTitle}-`;
|
||||
}
|
||||
self.upload.labelMediaTitle = `[${id + 1}/${total}]${self.upload.labelMediaTitle}${eleemnent.title}`;
|
||||
self.upload.labelMediaTitle = `[${id + 1}/${total}]${self.upload.labelMediaTitle}${element.title}`;
|
||||
|
||||
self.MediaService.uploadFile(eleemnent.file,
|
||||
self.MediaService.uploadFile(element.file,
|
||||
self.globalSeries,
|
||||
self.seriesId,
|
||||
self.globalSeason,
|
||||
eleemnent.episode,
|
||||
eleemnent.title,
|
||||
element.episode,
|
||||
element.title,
|
||||
self.typeId,
|
||||
(count, totalTmp) => {
|
||||
// console.log("upload : " + count*100/totalTmp);
|
||||
self.upload.mediaSendSize = count;
|
||||
self.upload.mediaSize = totalTmp;
|
||||
})
|
||||
}, this.cancelHandle)
|
||||
.then((response) => {
|
||||
console.log(`get response of video : ${JSON.stringify(response, null, 2)}`);
|
||||
sendDone();
|
||||
}).catch((response) => {
|
||||
})
|
||||
.catch((response) => {
|
||||
// self.error = "Can not get the data";
|
||||
console.log('Can not add the data in the system...');
|
||||
errorOccured(JSON.stringify(response, null, 2));
|
||||
errorOccurred(JSON.stringify(response, null, 2));
|
||||
});
|
||||
}
|
||||
|
||||
@ -518,7 +522,7 @@ export class UploadScene implements OnInit {
|
||||
return;
|
||||
}
|
||||
|
||||
self.saisonId = null;
|
||||
self.seasonId = null;
|
||||
// set 1 find the ID of the season:
|
||||
this.seriesService.getSeason(this.seriesId)
|
||||
.then((response: any[]) => {
|
||||
@ -526,14 +530,14 @@ export class UploadScene implements OnInit {
|
||||
for (let iii = 0; iii < response.length; iii++) {
|
||||
// console.log(" - " + JSON.stringify(response[iii]) + 'compare with : ' + JSON.stringify(self.globalSeason));
|
||||
if (response[iii].name === `${self.globalSeason}`) {
|
||||
self.saisonId = response[iii].id;
|
||||
self.seasonId = response[iii].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (self.saisonId === null) {
|
||||
if (self.seasonId === null) {
|
||||
return;
|
||||
}
|
||||
self.seasonService.getVideo(self.saisonId)
|
||||
self.seasonService.getVideo(self.seasonId)
|
||||
.then((response2: any[]) => {
|
||||
self.listFileInBdd = response2;
|
||||
// console.log("find video: " + response2.length);
|
||||
@ -549,6 +553,10 @@ export class UploadScene implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
abortUpload(): void {
|
||||
this.cancelHandle.abort();
|
||||
}
|
||||
|
||||
eventPopUpSeason(event: string): void {
|
||||
console.log(`GET event: ${event}`);
|
||||
this.popInService.close('popin-new-season');
|
||||
@ -575,3 +583,7 @@ export class UploadScene implements OnInit {
|
||||
this.popInService.open('popin-create-type');
|
||||
}
|
||||
}
|
||||
function isNullOrUndefined(abort: () => boolean) {
|
||||
throw new Error('Function not implemented.');
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,8 @@
|
||||
[mediaUploaded]="upload.mediaSendSize"
|
||||
[mediaSize]="upload.mediaSize"
|
||||
[result]="upload.result"
|
||||
[error]="upload.error"></upload-progress>
|
||||
[error]="upload.error"
|
||||
(abort)="abortUpload()"></upload-progress>
|
||||
|
||||
<delete-confirm
|
||||
[comment]="confirmDeleteComment"
|
||||
|
@ -9,6 +9,7 @@ import { Component, OnInit } from '@angular/core';
|
||||
import { DataService, TypeService, SeriesService, MediaService, ArianeService } from 'app/service';
|
||||
import { PopInService, UploadProgress } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Media, Season, Series, UUID } from 'app/back-api';
|
||||
import { RESTAbort } from 'app/back-api/rest-tools';
|
||||
|
||||
export interface ElementList {
|
||||
value?: number;
|
||||
@ -90,6 +91,7 @@ export class VideoEditScene implements OnInit {
|
||||
listSeason: ElementList[] = [
|
||||
{ value: undefined, label: '---' },
|
||||
];
|
||||
cancelHandle: RESTAbort = {};
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
private MediaService: MediaService,
|
||||
@ -101,6 +103,10 @@ export class VideoEditScene implements OnInit {
|
||||
|
||||
}
|
||||
|
||||
abortUpload(): void {
|
||||
this.cancelHandle.abort();
|
||||
}
|
||||
|
||||
updateNeedSend(): boolean {
|
||||
this.needSend = false;
|
||||
if (this.data.name !== this.dataOri.name) {
|
||||
@ -371,7 +377,7 @@ export class VideoEditScene implements OnInit {
|
||||
this.MediaService.uploadCover(this.idVideo, file, (count, total) => {
|
||||
self.upload.mediaSendSize = count;
|
||||
self.upload.mediaSize = total;
|
||||
})
|
||||
}, this.cancelHandle)
|
||||
.then((response: any) => {
|
||||
console.log(`get response of cover : ${JSON.stringify(response, null, 2)}`);
|
||||
self.upload.result = 'Cover added done';
|
||||
|
@ -7,7 +7,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SessionService, DataStore } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Media, MediaResource, UUID } from 'app/back-api';
|
||||
import { ProgressCallback, RESTConfig } from 'app/back-api/rest-tools';
|
||||
import { ProgressCallback, RESTAbort, RESTConfig } from 'app/back-api/rest-tools';
|
||||
import { environment } from 'environments/environment';
|
||||
import { GenericDataService } from './GenericDataService';
|
||||
|
||||
@ -37,7 +37,8 @@ export class MediaService extends GenericDataService<Media> {
|
||||
episode?: number,
|
||||
title?: string,
|
||||
typeId?: number,
|
||||
progress: ProgressCallback | undefined = undefined) {
|
||||
progress: ProgressCallback | undefined = undefined,
|
||||
cancelHandle: RESTAbort | undefined = undefined) {
|
||||
const formData = {
|
||||
fileName: file.name,
|
||||
file,
|
||||
@ -52,7 +53,10 @@ export class MediaService extends GenericDataService<Media> {
|
||||
return MediaResource.uploadFile({
|
||||
restConfig: this.getRestConfig(),
|
||||
data: formData,
|
||||
progress
|
||||
callback: {
|
||||
progressUpload: progress,
|
||||
abortHandle: cancelHandle,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -110,7 +114,8 @@ export class MediaService extends GenericDataService<Media> {
|
||||
}
|
||||
uploadCover(id: number,
|
||||
file: File,
|
||||
progress: ProgressCallback | undefined = undefined): Promise<Media> {
|
||||
progress: ProgressCallback | undefined = undefined,
|
||||
cancelHandle: RESTAbort | undefined = undefined): Promise<Media> {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
MediaResource.uploadCover({
|
||||
@ -122,7 +127,10 @@ export class MediaService extends GenericDataService<Media> {
|
||||
file,
|
||||
fileName: file.name
|
||||
},
|
||||
progress
|
||||
callback: {
|
||||
progressUpload: progress,
|
||||
abortHandle: cancelHandle,
|
||||
}
|
||||
}).then((value) => {
|
||||
self.dataStore.updateValue(value);
|
||||
resolve(value);
|
||||
|
@ -7,7 +7,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { DataStore, SessionService, TypeCheck } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Media, Season, SeasonResource, UUID } from 'app/back-api';
|
||||
import { ProgressCallback, RESTConfig } from 'app/back-api/rest-tools';
|
||||
import { ProgressCallback, RESTAbort, RESTConfig } from 'app/back-api/rest-tools';
|
||||
import { environment } from 'environments/environment';
|
||||
import { GenericDataService } from './GenericDataService';
|
||||
import { MediaService } from './media';
|
||||
@ -141,7 +141,8 @@ export class SeasonService extends GenericDataService<Season> {
|
||||
}
|
||||
uploadCover(id: number,
|
||||
file: File,
|
||||
progress: ProgressCallback | undefined = undefined): Promise<Season> {
|
||||
progress: ProgressCallback | undefined = undefined,
|
||||
cancelHandle: RESTAbort | undefined = undefined): Promise<Season> {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
SeasonResource.uploadCover({
|
||||
@ -153,7 +154,10 @@ export class SeasonService extends GenericDataService<Season> {
|
||||
file,
|
||||
fileName: file.name
|
||||
},
|
||||
progress
|
||||
callback: {
|
||||
progressUpload: progress,
|
||||
abortHandle: cancelHandle,
|
||||
}
|
||||
}).then((value) => {
|
||||
self.dataStore.updateValue(value);
|
||||
resolve(value);
|
||||
|
@ -8,7 +8,7 @@ import { Injectable } from '@angular/core';
|
||||
|
||||
import { SessionService, DataStore, TypeCheck } from '@kangaroo-and-rabbit/kar-cw';
|
||||
import { Media, Season, Series, SeriesResource, UUID } from 'app/back-api';
|
||||
import { ProgressCallback, RESTConfig } from 'app/back-api/rest-tools';
|
||||
import { ProgressCallback, RESTAbort, RESTConfig } from 'app/back-api/rest-tools';
|
||||
import { environment } from 'environments/environment';
|
||||
import { GenericDataService } from './GenericDataService';
|
||||
import { SeasonService, MediaService } from '.';
|
||||
@ -196,7 +196,8 @@ export class SeriesService extends GenericDataService<Series> {
|
||||
}
|
||||
uploadCover(id: number,
|
||||
file: File,
|
||||
progress: ProgressCallback | undefined = undefined): Promise<Media> {
|
||||
progress: ProgressCallback | undefined = undefined,
|
||||
cancelHandle: RESTAbort | undefined = undefined): Promise<Media> {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
SeriesResource.uploadCover({
|
||||
@ -208,7 +209,10 @@ export class SeriesService extends GenericDataService<Series> {
|
||||
file,
|
||||
fileName: file.name
|
||||
},
|
||||
progress
|
||||
callback: {
|
||||
progressUpload: progress,
|
||||
abortHandle: cancelHandle,
|
||||
}
|
||||
}).then((value) => {
|
||||
self.dataStore.updateValue(value);
|
||||
resolve(value);
|
||||
|
Loading…
Reference in New Issue
Block a user