[DEV] basic usable version with use condition (webm or mkv(h264+opus))
This commit is contained in:
parent
4c226971f5
commit
682b36c167
51
.gitignore
vendored
Normal file
51
.gitignore
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/dist-server
|
||||
/tmp
|
||||
/out-tsc
|
||||
|
||||
# dependencies
|
||||
applicationFront/node_modules
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# e2e
|
||||
/e2e/*.js
|
||||
/e2e/*.map
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
backPY/env
|
||||
|
||||
*.pyc
|
||||
|
||||
__pycache__
|
||||
|
9
back/.gitignore
vendored
Normal file
9
back/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
config.*
|
||||
config.env
|
||||
.env
|
||||
config
|
||||
data
|
||||
cache
|
||||
|
||||
__pycache__
|
||||
*.pyc
|
@ -1 +0,0 @@
|
||||
[]
|
@ -1 +0,0 @@
|
||||
[]
|
@ -1,43 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Documentary",
|
||||
"description": "Documentary (annimals, space, earth...)"
|
||||
},{
|
||||
"id": 1,
|
||||
"name": "Movie",
|
||||
"description": "Movie with real humans (film)"
|
||||
},{
|
||||
"id": 2,
|
||||
"name": "Annimation",
|
||||
"description": "Annimation movies (film)"
|
||||
},{
|
||||
"id": 3,
|
||||
"name": "Short Films",
|
||||
"description": "Small movies (less 2 minutes)"
|
||||
},{
|
||||
"id": 4,
|
||||
"name": "tv show",
|
||||
"description": "Tv show form old peoples"
|
||||
}, {
|
||||
"id": 5,
|
||||
"name": "Anniation tv show",
|
||||
"description": "Tv show form young peoples"
|
||||
}, {
|
||||
"id": 6,
|
||||
"name": "Theater",
|
||||
"description": "recorder theater pices"
|
||||
}, {
|
||||
"id": 7,
|
||||
"name": "One man show",
|
||||
"description": "Recorded stand up"
|
||||
}, {
|
||||
"id": 8,
|
||||
"name": "Concert",
|
||||
"description": "Recorded concert"
|
||||
}, {
|
||||
"id": 9,
|
||||
"name": "Opera",
|
||||
"description": "Recorded Opera"
|
||||
}
|
||||
]
|
@ -1 +0,0 @@
|
||||
[]
|
@ -117,20 +117,66 @@ def add(_app, _name_api):
|
||||
return response.stream(streaming, content_type='application/json')
|
||||
|
||||
@elem_blueprint.get('/' + _name_api + '/<id:string>', strict_slashes=True)
|
||||
@doc.summary("Show resources")
|
||||
@doc.description("Display a listing of the resource.")
|
||||
@doc.summary("get a specific resource")
|
||||
@doc.description("Get a resource with all the needed datas ... It permeit seek for video stream.")
|
||||
@doc.produces(content_type='application/json')
|
||||
async def retrive(request, id):
|
||||
debug.warning("Request data media 2 : " + id);
|
||||
if id[-4:] == ".mp4":
|
||||
id = id[:-4]
|
||||
if id[-4:] == ".mkv":
|
||||
id = id[:-4]
|
||||
if id[-4:] == ".avi":
|
||||
id = id[:-4]
|
||||
if id[-4:] == ".ts":
|
||||
id = id[:-3]
|
||||
filename = os.path.join(_app.config['REST_MEDIA_DATA'], id)
|
||||
if os.path.isfile(filename) == True:
|
||||
file_stat = await async_os.stat(filename)
|
||||
headers = {"Content-Length": str(file_stat.st_size)}
|
||||
return await file_stream(
|
||||
filename,
|
||||
headers=headers,
|
||||
chunked=False,
|
||||
)
|
||||
raise ServerError("No data found", status_code=404)
|
||||
headers = {
|
||||
'Content-Type': 'video/x-matroska',
|
||||
'Accept-Ranges': 'Accept-Ranges: bytes'
|
||||
}
|
||||
try:
|
||||
with open(filename, 'rb') as fff:
|
||||
range_start = None
|
||||
range_end = None
|
||||
fff.seek(0, 2)
|
||||
file_length = fff.tell()
|
||||
fff.seek(0)
|
||||
try:
|
||||
range_ = '0-' + str(file_length)
|
||||
if 'range' in request.headers:
|
||||
range_ = request.headers['range'].split('=')[1]
|
||||
range_split = range_.split('-')
|
||||
range_start = int(range_split[0])
|
||||
fff.seek(range_start)
|
||||
range_end = int(range_split[1])
|
||||
except ValueError:
|
||||
pass
|
||||
if range_start and range_start != 0:
|
||||
if not range_end:
|
||||
range_end = file_length
|
||||
read_length = range_end - range_start
|
||||
else:
|
||||
range_start = 0
|
||||
read_length = file_length
|
||||
range_end = file_length
|
||||
fff.seek(range_start)
|
||||
headers['Content-Length'] = read_length
|
||||
headers['Content-Range'] = f'bytes {range_start}-{range_end-1}/{file_length}'
|
||||
async def streaming_fn(response):
|
||||
with open(filename, 'rb') as fff:
|
||||
chunk_size = 8192
|
||||
current_offset = range_start
|
||||
while (current_offset < file_length):
|
||||
chunk_start = current_offset
|
||||
fff.seek(current_offset)
|
||||
chunk_data = fff.read(min(chunk_size, file_length - current_offset))
|
||||
current_offset += chunk_size
|
||||
await response.write(chunk_data)
|
||||
return response.stream(streaming_fn, headers=headers, status=206)
|
||||
except FileNotFoundError:
|
||||
return response.HTTPResponse(status=404)
|
||||
|
||||
|
||||
_app.blueprint(elem_blueprint)
|
||||
|
||||
|
@ -75,6 +75,8 @@ def add(_app, _name_api):
|
||||
description = [str, type(None)]
|
||||
# creating time
|
||||
create_date = str
|
||||
# date of the video
|
||||
date = [int, type(None)]
|
||||
# number of second
|
||||
time = [int, type(None)]
|
||||
|
||||
@ -89,6 +91,8 @@ def add(_app, _name_api):
|
||||
description = str
|
||||
# creating time
|
||||
create_date = str
|
||||
# date of the video
|
||||
date = str
|
||||
# number of second
|
||||
time = int
|
||||
|
||||
@ -108,10 +112,10 @@ def add(_app, _name_api):
|
||||
for type_key in ["sha512","type_id","name"]:
|
||||
if type_key not in request.json.keys():
|
||||
raise ServerError("Bad Request: Missing Key '" + type_key + "'", status_code=400)
|
||||
for type_key in ["date"]:
|
||||
for type_key in ["create_date"]:
|
||||
if type_key in request.json.keys():
|
||||
raise ServerError("Forbidden: Must not be set Key '" + type_key + "'", status_code=403)
|
||||
for type_key in ["saison_id","episode","time","group_id","description"]:
|
||||
for type_key in ["saison_id","episode","date","time","group_id","description"]:
|
||||
if type_key not in request.json.keys():
|
||||
request.json[type_key] = None
|
||||
request.json["create_date"] = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
|
||||
|
@ -53,7 +53,7 @@ app.config['API_LICENSE_NAME'] = 'MPL 2.0'
|
||||
app.config['API_LICENSE_URL'] = 'https://www.mozilla.org/en-US/MPL/2.0/'
|
||||
app.config['schemes'] = ['http', 'https']
|
||||
if "REST_TMP_DATA" not in app.config.keys():
|
||||
app.config['REST_TMP_DATA'] = "tmp"
|
||||
app.config['REST_TMP_DATA'] = os.path.join("data", "tmp")
|
||||
if "REST_MEDIA_DATA" not in app.config.keys():
|
||||
app.config['REST_MEDIA_DATA'] = os.path.join("data", "media")
|
||||
if "REST_DATA" not in app.config.keys():
|
||||
@ -67,10 +67,58 @@ app.blueprint(openapi_blueprint)
|
||||
app.blueprint(swagger_blueprint)
|
||||
|
||||
|
||||
def add_interface(_name):
|
||||
data_global_elements.add_interface(_name, data_interface.DataInterface(_name, os.path.join(tools.get_run_path(), app.config['REST_DATA'], "bdd_" + _name + ".json")))
|
||||
default_values_type = [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Documentary",
|
||||
"description": "Documentary (annimals, space, earth...)"
|
||||
},{
|
||||
"id": 1,
|
||||
"name": "Movie",
|
||||
"description": "Movie with real humans (film)"
|
||||
},{
|
||||
"id": 2,
|
||||
"name": "Annimation",
|
||||
"description": "Annimation movies (film)"
|
||||
},{
|
||||
"id": 3,
|
||||
"name": "Short Films",
|
||||
"description": "Small movies (less 2 minutes)"
|
||||
},{
|
||||
"id": 4,
|
||||
"name": "tv show",
|
||||
"description": "Tv show form old peoples"
|
||||
}, {
|
||||
"id": 5,
|
||||
"name": "Anniation tv show",
|
||||
"description": "Tv show form young peoples"
|
||||
}, {
|
||||
"id": 6,
|
||||
"name": "Theater",
|
||||
"description": "recorder theater pices"
|
||||
}, {
|
||||
"id": 7,
|
||||
"name": "One man show",
|
||||
"description": "Recorded stand up"
|
||||
}, {
|
||||
"id": 8,
|
||||
"name": "Concert",
|
||||
"description": "Recorded concert"
|
||||
}, {
|
||||
"id": 9,
|
||||
"name": "Opera",
|
||||
"description": "Recorded Opera"
|
||||
}
|
||||
]
|
||||
|
||||
add_interface(data_global_elements.API_TYPE)
|
||||
|
||||
def add_interface(_name, _default_value = None):
|
||||
interface = data_interface.DataInterface(_name, os.path.join(tools.get_run_path(), app.config['REST_DATA'], "bdd_" + _name + ".json"))
|
||||
if _default_value != None:
|
||||
interface.reset_with_value(_default_value);
|
||||
data_global_elements.add_interface(_name, interface)
|
||||
|
||||
add_interface(data_global_elements.API_TYPE, default_values_type)
|
||||
add_interface(data_global_elements.API_GROUP)
|
||||
add_interface(data_global_elements.API_SAISON)
|
||||
add_interface(data_global_elements.API_VIDEO)
|
||||
|
@ -26,7 +26,6 @@ class DataInterface():
|
||||
self.last_id = 0
|
||||
if tools.exist(self.file) == False:
|
||||
self.mark_to_store()
|
||||
self.last_id = random.randint(20, 100)
|
||||
else:
|
||||
data = tools.file_read_data(self.file)
|
||||
self.bdd = json.loads(data)
|
||||
@ -35,6 +34,12 @@ class DataInterface():
|
||||
def set_data_model(self, _data_model):
|
||||
self.model = _data_model
|
||||
|
||||
def reset_with_value(self, _data):
|
||||
self.bdd = _data
|
||||
self.last_id = 0
|
||||
self.mark_to_store()
|
||||
self.upgrade_global_bdd_id();
|
||||
|
||||
def check_with_model(self, _data):
|
||||
if self.model == None:
|
||||
return True
|
||||
@ -78,11 +83,15 @@ class DataInterface():
|
||||
return True
|
||||
|
||||
def upgrade_global_bdd_id(self):
|
||||
self.last_id = 0
|
||||
for elem in self.bdd:
|
||||
if 'id' not in elem.keys():
|
||||
continue
|
||||
if elem["id"] >= self.last_id:
|
||||
self.last_id = elem["id"] + 1
|
||||
# start at a random value permit to vaidate the basis inctance test
|
||||
if self.last_id == 0:
|
||||
self.last_id = random.randint(20, 100)
|
||||
|
||||
def get_table_index(self, _id):
|
||||
id_in_bdd = 0
|
||||
|
@ -126,7 +126,7 @@ def push_video_file(_path, _basic_key={}):
|
||||
return True
|
||||
|
||||
debug.info("Add media : '" + _path + "'")
|
||||
if file_extension[1:] not in ["avi", "mkv", "mov", "mp4", "ts"] \
|
||||
if file_extension[1:] not in ["webm", "avi", "mkv", "mov", "mp4", "ts"] \
|
||||
and file_name not in ["cover_1.jpg","cover_1.png", "cover_1.till", "cover_1.bmp", "cover_1.tga"]:
|
||||
debug.warning("Not send file : " + _path + " Not manage file_extension... " + file_extension)
|
||||
return False
|
||||
|
63
front/.angular-cli.json
Normal file
63
front/.angular-cli.json
Normal file
@ -0,0 +1,63 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"project": {
|
||||
"name": "no-comment"
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"root": "src",
|
||||
"outDir": "dist",
|
||||
"assets": [
|
||||
"assets",
|
||||
"favicon.ico"
|
||||
],
|
||||
"index": "index.html",
|
||||
"main": "main.ts",
|
||||
"polyfills": "polyfills.ts",
|
||||
"test": "test.ts",
|
||||
"tsconfig": "tsconfig.app.json",
|
||||
"testTsconfig": "tsconfig.spec.json",
|
||||
"prefix": "app",
|
||||
"styles": [
|
||||
"styles.less",
|
||||
"theme.color.blue.less",
|
||||
"theme.checkbox.less",
|
||||
"theme.modal.less"
|
||||
],
|
||||
"scripts": [],
|
||||
"environmentSource": "environments/environment.ts",
|
||||
"environments": {
|
||||
"dev": "environments/environment.ts",
|
||||
"prod": "environments/environment.prod.ts"
|
||||
}
|
||||
}
|
||||
],
|
||||
"e2e": {
|
||||
"protractor": {
|
||||
"config": "./protractor.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": [
|
||||
{
|
||||
"project": "src/tsconfig.app.json",
|
||||
"exclude": "**/node_modules/**"
|
||||
},
|
||||
{
|
||||
"project": "src/tsconfig.spec.json",
|
||||
"exclude": "**/node_modules/**"
|
||||
},
|
||||
{
|
||||
"project": "e2e/tsconfig.e2e.json",
|
||||
"exclude": "**/node_modules/**"
|
||||
}
|
||||
],
|
||||
"test": {
|
||||
"karma": {
|
||||
"config": "./karma.conf.js"
|
||||
}
|
||||
},
|
||||
"defaults": {
|
||||
"styleExt": "less",
|
||||
"component": {}
|
||||
}
|
||||
}
|
13
front/.editorconfig
Normal file
13
front/.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
@ -10,6 +10,9 @@ import { ModuleWithProviders } from '@angular/core';
|
||||
|
||||
import { HomeComponent } from './home/home.component';
|
||||
import { TypeDetailComponent } from './type-detail/type-detail.component';
|
||||
import { GroupDetailComponent } from './group-detail/group-detail.component';
|
||||
import { SaisonDetailComponent } from './saison-detail/saison-detail.component';
|
||||
import { VideoDetailComponent } from './video-detail/video-detail.component';
|
||||
import { LoginComponent } from './login/login.component';
|
||||
import { SignUpComponent } from './sign-up/sign-up.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
@ -20,6 +23,9 @@ const routes: Routes = [
|
||||
{ path: '', redirectTo: '/home', pathMatch: 'full'},
|
||||
{ path: 'home', component: HomeComponent },
|
||||
{ path: 'type/:id', component: TypeDetailComponent },
|
||||
{ path: 'group/:id', component: GroupDetailComponent },
|
||||
{ path: 'saison/:id', component: SaisonDetailComponent },
|
||||
{ path: 'video/:id', component: VideoDetailComponent },
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: 'signup', component: SignUpComponent },
|
||||
{ path: 'settings', component: SettingsComponent },
|
||||
|
@ -24,9 +24,13 @@ import { SignUpComponent } from './sign-up/sign-up.component';
|
||||
import { ValidateEmailComponent } from './validate-email/validate-email.component';
|
||||
import { HomeComponent } from './home/home.component';
|
||||
import { TypeDetailComponent } from './type-detail/type-detail.component';
|
||||
import { GroupDetailComponent } from './group-detail/group-detail.component';
|
||||
import { SaisonDetailComponent } from './saison-detail/saison-detail.component';
|
||||
import { VideoDetailComponent } from './video-detail/video-detail.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import { ErrorViewerComponent } from './error-viewer/error-viewer.component';
|
||||
import { ErrorComponent } from './error/error.component';
|
||||
|
||||
import { CookiesService } from './cookies.service';
|
||||
import { HttpWrapperService } from './http-wrapper.service';
|
||||
import { UserService } from './user.service';
|
||||
@ -52,6 +56,9 @@ import { AppComponent } from './app.component';
|
||||
ValidateEmailComponent,
|
||||
HomeComponent,
|
||||
TypeDetailComponent,
|
||||
GroupDetailComponent,
|
||||
SaisonDetailComponent,
|
||||
VideoDetailComponent,
|
||||
SettingsComponent,
|
||||
ErrorViewerComponent,
|
||||
ErrorComponent
|
||||
|
@ -1,3 +1,11 @@
|
||||
<div>
|
||||
{{name}}
|
||||
{{name}}<br/>
|
||||
{{sha512}}<br/>
|
||||
|
||||
<!--<div [disabled]="display_video=='false' ? true : null">
|
||||
aaa sdfsdfsdfsdf aaa
|
||||
</div>
|
||||
-->
|
||||
<div *ngIf="video_enable">
|
||||
</div>
|
||||
</div>
|
@ -21,6 +21,7 @@ import { VideoService } from '../video.service';
|
||||
export class ElementVideoComponent implements OnInit {
|
||||
// input parameters
|
||||
@Input() id_video:number = -1;
|
||||
@Input() display_video:boolean = false;
|
||||
|
||||
error:string = ""
|
||||
|
||||
@ -33,6 +34,8 @@ export class ElementVideoComponent implements OnInit {
|
||||
time:number = undefined
|
||||
type_id:number = undefined
|
||||
generated_name:string = ""
|
||||
video_source:string = ""
|
||||
video_enable:boolean = false;
|
||||
constructor(private router: Router,
|
||||
private videoService: VideoService) {
|
||||
|
||||
@ -40,28 +43,40 @@ export class ElementVideoComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.name = "ll " + this.id_video
|
||||
let self = this;
|
||||
console.log("get parameter id: " + this.id_video);
|
||||
console.log("get video id: " + this.id_video);
|
||||
this.videoService.get(this.id_video)
|
||||
.then(function(response) {
|
||||
console.log("get response of video : " + JSON.stringify(response, null, 2));
|
||||
self.error = "";
|
||||
self.name = response.name
|
||||
self.description = response.description
|
||||
self.episode = response.episode
|
||||
self.group_id = response.group_id
|
||||
self.saison_id = response.saison_id
|
||||
self.sha512 = response.sha512
|
||||
self.time = response.time
|
||||
self.generated_name = response.generated_name
|
||||
self.name = response.name;
|
||||
self.description = response.description;
|
||||
self.episode = response.episode;
|
||||
self.group_id = response.group_id;
|
||||
self.saison_id = response.saison_id;
|
||||
self.sha512 = response.sha512;
|
||||
self.time = response.time;
|
||||
self.generated_name = response.generated_name;
|
||||
if (self.sha512 != "") {
|
||||
self.video_source = "http://localhost:15080/data/" + self.sha512 + ".mp4";
|
||||
self.video_enable = true;
|
||||
} else {
|
||||
self.video_source = "";
|
||||
self.video_enable = false;
|
||||
}
|
||||
console.log("101010 " + self.video_enable + " " + self.video_source);
|
||||
//console.log("set transformed : " + JSON.stringify(self, null, 2));
|
||||
}).catch(function(response) {
|
||||
self.error = "Can not get the data";
|
||||
self.name = ""
|
||||
self.description = ""
|
||||
self.episode = undefined
|
||||
self.group_id = undefined
|
||||
self.saison_id = undefined
|
||||
self.sha512 = ""
|
||||
self.time = undefined
|
||||
self.generated_name = ""
|
||||
self.name = "";
|
||||
self.description = "";
|
||||
self.episode = undefined;
|
||||
self.group_id = undefined;
|
||||
self.saison_id = undefined;
|
||||
self.sha512 = "";
|
||||
self.time = undefined;
|
||||
self.generated_name = "";
|
||||
self.video_source = "";
|
||||
self.video_enable = false;
|
||||
});
|
||||
}
|
||||
}
|
12
front/src/app/group-detail/group-detail.component.html
Normal file
12
front/src/app/group-detail/group-detail.component.html
Normal file
@ -0,0 +1,12 @@
|
||||
<div class="main-reduce">
|
||||
<div class="fill-all">
|
||||
<div *ngFor="let data of saisons" class="item" (click)="onSelectSaison(data)">
|
||||
<app-element-saison [id_saison]="data"></app-element-saison>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all">
|
||||
<div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo(data)">
|
||||
<app-element-video [id_video]="data"></app-element-video>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
62
front/src/app/group-detail/group-detail.component.less
Normal file
62
front/src/app/group-detail/group-detail.component.less
Normal file
@ -0,0 +1,62 @@
|
||||
.fill-all{
|
||||
width:100%;
|
||||
height:100%;
|
||||
margin:0;
|
||||
padding:0;
|
||||
border:0;
|
||||
background-color:#0F0;
|
||||
}
|
||||
|
||||
.item {
|
||||
font-size: 20px;
|
||||
height: 21%;
|
||||
width: 23%;
|
||||
margin: 1%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
//box-shadow: 0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24);
|
||||
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
|
||||
line-height: normal;
|
||||
border: none;
|
||||
font-family: "Roboto","Helvetica","Arial",sans-serif;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0;
|
||||
will-change: box-shadow;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
transition-duration: 0.4s;
|
||||
float:left;
|
||||
display:block;
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #F00;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: ~"translate(-12px,-12px)";
|
||||
line-height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.item-video {
|
||||
&:hover {
|
||||
background-color: #0F0;
|
||||
}
|
||||
}
|
||||
|
25
front/src/app/group-detail/group-detail.component.spec.ts
Normal file
25
front/src/app/group-detail/group-detail.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GroupDetailComponent } from './group-detail.component';
|
||||
|
||||
describe('GroupDetailComponent', () => {
|
||||
let component: GroupDetailComponent;
|
||||
let fixture: ComponentFixture<GroupDetailComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ GroupDetailComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(GroupDetailComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
64
front/src/app/group-detail/group-detail.component.ts
Normal file
64
front/src/app/group-detail/group-detail.component.ts
Normal file
@ -0,0 +1,64 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { Location } from '@angular/common';
|
||||
import { fadeInAnimation } from '../_animations/index';
|
||||
|
||||
import { GroupService } from '../group.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-group-detail',
|
||||
templateUrl: './group-detail.component.html',
|
||||
styleUrls: ['./group-detail.component.less'],
|
||||
animations: [fadeInAnimation],
|
||||
host: { '[@fadeInAnimation]': '' }
|
||||
})
|
||||
|
||||
export class GroupDetailComponent implements OnInit {
|
||||
id_group = -1;
|
||||
saisons_error = "";
|
||||
saisons = [];
|
||||
videos_error = "";
|
||||
videos = [];
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private locate: Location,
|
||||
private groupService: GroupService) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.id_group = parseInt(this.route.snapshot.paramMap.get('id'));
|
||||
let self = this;
|
||||
console.log("get parameter id: " + this.id_group);
|
||||
this.groupService.getSaison(this.id_group)
|
||||
.then(function(response) {
|
||||
self.saisons_error = "";
|
||||
self.saisons = response
|
||||
}).catch(function(response) {
|
||||
self.saisons_error = "Can not get the list of saison in this group";
|
||||
self.saisons = []
|
||||
});
|
||||
this.groupService.getVideoNoSaison(this.id_group)
|
||||
.then(function(response) {
|
||||
self.videos_error = "";
|
||||
self.videos = response
|
||||
}).catch(function(response) {
|
||||
self.videos_error = "Can not get the List of video without saison";
|
||||
self.videos = []
|
||||
});
|
||||
}
|
||||
onSelectSaison(_idSelected: number):void {
|
||||
this.router.navigate(['saison/' + _idSelected ]);
|
||||
}
|
||||
|
||||
onSelectVideo(_idSelected: number):void {
|
||||
this.router.navigate(['video/' + _idSelected ]);
|
||||
}
|
||||
|
||||
}
|
@ -10,10 +10,13 @@ export class GroupService {
|
||||
console.log("Start GroupService");
|
||||
}
|
||||
|
||||
get(_id:number):any {
|
||||
get_specific(_id:number, _subElement:string = ""):any {
|
||||
console.log("Get All data from types");
|
||||
const httpOption = { 'Content-Type': 'application/json' };
|
||||
let url = "group/" + _id;
|
||||
if (_subElement != "") {
|
||||
url += "/" + _subElement;
|
||||
}
|
||||
console.log("call GET " + url);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -33,7 +36,21 @@ export class GroupService {
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
get(_id:number):any {
|
||||
return this.get_specific(_id);
|
||||
};
|
||||
|
||||
getVideo(_id:number):any {
|
||||
return this.get_specific(_id, "video");
|
||||
};
|
||||
|
||||
getSaison(_id:number):any {
|
||||
return this.get_specific(_id, "saison");
|
||||
};
|
||||
|
||||
getVideoNoSaison(_id:number):any {
|
||||
return this.get_specific(_id, "video_no_saison");
|
||||
};
|
||||
}
|
||||
|
||||
|
7
front/src/app/saison-detail/saison-detail.component.html
Normal file
7
front/src/app/saison-detail/saison-detail.component.html
Normal file
@ -0,0 +1,7 @@
|
||||
<div class="main-reduce">
|
||||
<div class="fill-all">
|
||||
<div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo(data)">
|
||||
<app-element-video [id_video]="data"></app-element-video>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
62
front/src/app/saison-detail/saison-detail.component.less
Normal file
62
front/src/app/saison-detail/saison-detail.component.less
Normal file
@ -0,0 +1,62 @@
|
||||
.fill-all{
|
||||
width:100%;
|
||||
height:100%;
|
||||
margin:0;
|
||||
padding:0;
|
||||
border:0;
|
||||
background-color:#0F0;
|
||||
}
|
||||
|
||||
.item {
|
||||
font-size: 20px;
|
||||
height: 21%;
|
||||
width: 23%;
|
||||
margin: 1%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
//box-shadow: 0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24);
|
||||
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
|
||||
line-height: normal;
|
||||
border: none;
|
||||
font-family: "Roboto","Helvetica","Arial",sans-serif;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0;
|
||||
will-change: box-shadow;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
transition-duration: 0.4s;
|
||||
float:left;
|
||||
display:block;
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #F00;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: ~"translate(-12px,-12px)";
|
||||
line-height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.item-video {
|
||||
&:hover {
|
||||
background-color: #0F0;
|
||||
}
|
||||
}
|
||||
|
25
front/src/app/saison-detail/saison-detail.component.spec.ts
Normal file
25
front/src/app/saison-detail/saison-detail.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SaisonDetailComponent } from './saison-detail.component';
|
||||
|
||||
describe('SaisonDetailComponent', () => {
|
||||
let component: SaisonDetailComponent;
|
||||
let fixture: ComponentFixture<SaisonDetailComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SaisonDetailComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SaisonDetailComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
51
front/src/app/saison-detail/saison-detail.component.ts
Normal file
51
front/src/app/saison-detail/saison-detail.component.ts
Normal file
@ -0,0 +1,51 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { Location } from '@angular/common';
|
||||
import { fadeInAnimation } from '../_animations/index';
|
||||
|
||||
import { SaisonService } from '../saison.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-saison-detail',
|
||||
templateUrl: './saison-detail.component.html',
|
||||
styleUrls: ['./saison-detail.component.less'],
|
||||
animations: [fadeInAnimation],
|
||||
host: { '[@fadeInAnimation]': '' }
|
||||
})
|
||||
|
||||
export class SaisonDetailComponent implements OnInit {
|
||||
id_saison = -1;
|
||||
videos_error = "";
|
||||
videos = [];
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private locate: Location,
|
||||
private saisonService: SaisonService) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.id_saison = parseInt(this.route.snapshot.paramMap.get('id'));
|
||||
let self = this;
|
||||
console.log("get parameter id: " + this.id_saison);
|
||||
this.saisonService.getVideo(this.id_saison)
|
||||
.then(function(response) {
|
||||
self.videos_error = "";
|
||||
self.videos = response
|
||||
}).catch(function(response) {
|
||||
self.videos_error = "Can not get the List of video without saison";
|
||||
self.videos = []
|
||||
});
|
||||
}
|
||||
|
||||
onSelectVideo(_idSelected: number):void {
|
||||
this.router.navigate(['video/' + _idSelected ]);
|
||||
}
|
||||
|
||||
}
|
@ -10,10 +10,13 @@ export class SaisonService {
|
||||
console.log("Start SaisonService");
|
||||
}
|
||||
|
||||
get(_id:number):any {
|
||||
get_specific(_id:number, _subElement:string = ""):any {
|
||||
console.log("Get All data from types");
|
||||
const httpOption = { 'Content-Type': 'application/json' };
|
||||
let url = "saison/" + _id;
|
||||
if (_subElement != "") {
|
||||
url += "/" + _subElement;
|
||||
}
|
||||
console.log("call GET " + url);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -33,7 +36,15 @@ export class SaisonService {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
get(_id:number):any {
|
||||
return this.get_specific(_id);
|
||||
};
|
||||
|
||||
getVideo(_id:number):any {
|
||||
return this.get_specific(_id, "video");
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,9 @@ import { TypeService } from '../type.service';
|
||||
export class TypeDetailComponent implements OnInit {
|
||||
type_id = -1;
|
||||
groups_error = "";
|
||||
groups = [{name:"group1"}, {name:"group2"}, {name:"group3"}];
|
||||
groups = [];
|
||||
videos_error = "";
|
||||
videos = [{name:"video1"}, {name:"video2"}, {name:"video3"}];
|
||||
videos = [];
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private locate: Location,
|
||||
|
13
front/src/app/video-detail/video-detail.component.html
Normal file
13
front/src/app/video-detail/video-detail.component.html
Normal file
@ -0,0 +1,13 @@
|
||||
<div class="main-reduce">
|
||||
<div class="fill-all">
|
||||
<h1>{{name}}</h1>
|
||||
<p>{{description}}</p>
|
||||
|
||||
<div *ngIf="episode!=null">
|
||||
<p>Episode <b>{{episode}}</b></p>
|
||||
</div>
|
||||
<p>generated_name <b>{{generated_name}}</b></p>
|
||||
<video src="{{video_source}}" controls width="50%">
|
||||
<!--<p>Your browser des not suport HTML5 video player. download video: <a href="{{video_source}}>link here</a>.</p>-->
|
||||
</video>
|
||||
</div>
|
62
front/src/app/video-detail/video-detail.component.less
Normal file
62
front/src/app/video-detail/video-detail.component.less
Normal file
@ -0,0 +1,62 @@
|
||||
.fill-all{
|
||||
width:100%;
|
||||
height:100%;
|
||||
margin:0;
|
||||
padding:0;
|
||||
border:0;
|
||||
background-color:#0F0;
|
||||
}
|
||||
|
||||
.item {
|
||||
font-size: 20px;
|
||||
height: 21%;
|
||||
width: 23%;
|
||||
margin: 1%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
//box-shadow: 0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24);
|
||||
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
|
||||
line-height: normal;
|
||||
border: none;
|
||||
font-family: "Roboto","Helvetica","Arial",sans-serif;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0;
|
||||
will-change: box-shadow;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
transition-duration: 0.4s;
|
||||
float:left;
|
||||
display:block;
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #F00;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: ~"translate(-12px,-12px)";
|
||||
line-height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.item-video {
|
||||
&:hover {
|
||||
background-color: #0F0;
|
||||
}
|
||||
}
|
||||
|
25
front/src/app/video-detail/video-detail.component.spec.ts
Normal file
25
front/src/app/video-detail/video-detail.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { VideoDetailComponent } from './video-detail.component';
|
||||
|
||||
describe('VideoDetailComponent', () => {
|
||||
let component: VideoDetailComponent;
|
||||
let fixture: ComponentFixture<VideoDetailComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ VideoDetailComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(VideoDetailComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
81
front/src/app/video-detail/video-detail.component.ts
Normal file
81
front/src/app/video-detail/video-detail.component.ts
Normal file
@ -0,0 +1,81 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { Location } from '@angular/common';
|
||||
import { fadeInAnimation } from '../_animations/index';
|
||||
|
||||
import { VideoService } from '../video.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-video-detail',
|
||||
templateUrl: './video-detail.component.html',
|
||||
styleUrls: ['./video-detail.component.less'],
|
||||
animations: [fadeInAnimation],
|
||||
host: { '[@fadeInAnimation]': '' }
|
||||
})
|
||||
|
||||
export class VideoDetailComponent implements OnInit {
|
||||
id_video:number = -1;
|
||||
|
||||
error:string = ""
|
||||
|
||||
name:string = ""
|
||||
description:string = ""
|
||||
episode:number = undefined
|
||||
group_id:number = undefined
|
||||
saison_id:number = undefined
|
||||
sha512:string = ""
|
||||
time:number = undefined
|
||||
type_id:number = undefined
|
||||
generated_name:string = ""
|
||||
video_source:string = ""
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private locate: Location,
|
||||
private videoService: VideoService) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.id_video = parseInt(this.route.snapshot.paramMap.get('id'));
|
||||
let self = this;
|
||||
this.videoService.get(this.id_video)
|
||||
.then(function(response) {
|
||||
console.log("get response of video : " + JSON.stringify(response, null, 2));
|
||||
self.error = "";
|
||||
self.name = response.name;
|
||||
self.description = response.description;
|
||||
self.episode = response.episode;
|
||||
self.group_id = response.group_id;
|
||||
self.saison_id = response.saison_id;
|
||||
self.sha512 = response.sha512;
|
||||
self.time = response.time;
|
||||
self.generated_name = response.generated_name;
|
||||
if (self.sha512 != "") {
|
||||
self.video_source = "http://localhost:15080/data/" + self.sha512 + ".mp4";
|
||||
} else {
|
||||
self.video_source = "";
|
||||
}
|
||||
console.log("display source " + self.video_source);
|
||||
//console.log("set transformed : " + JSON.stringify(self, null, 2));
|
||||
}).catch(function(response) {
|
||||
self.error = "Can not get the data";
|
||||
self.name = "";
|
||||
self.description = "";
|
||||
self.episode = undefined;
|
||||
self.group_id = undefined;
|
||||
self.saison_id = undefined;
|
||||
self.sha512 = "";
|
||||
self.time = undefined;
|
||||
self.generated_name = "";
|
||||
self.video_source = "";
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -10,9 +10,13 @@ export class VideoService {
|
||||
console.log("Start VideoService");
|
||||
}
|
||||
|
||||
get(_id:number):any {
|
||||
get_specific(_id:number, _subElement:string = ""):any {
|
||||
console.log("Get All data from types");
|
||||
const httpOption = { 'Content-Type': 'application/json' };
|
||||
let url = "video/" + _id;
|
||||
if (_subElement != "") {
|
||||
url += "/" + _subElement;
|
||||
}
|
||||
console.log("call GET " + url);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -20,7 +24,7 @@ export class VideoService {
|
||||
.then(function(response: any) {
|
||||
if (response.status == 200) {
|
||||
resolve(response.data);
|
||||
console.log("get data from type : " + response.data);
|
||||
console.log("get data from response : " + JSON.stringify(response.data, null, 2));
|
||||
return;
|
||||
}
|
||||
reject("An error occured");
|
||||
@ -32,7 +36,9 @@ export class VideoService {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
get(_id:number):any {
|
||||
return this.get_specific(_id);
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user