[DEV] first application

This commit is contained in:
Edouard DUPIN 2019-12-21 21:53:18 +01:00
parent bdc2e7d176
commit 4c226971f5
129 changed files with 18888 additions and 0 deletions

14
front/e2e/app.e2e-spec.ts Normal file
View File

@ -0,0 +1,14 @@
import { AppPage } from './app.po';
describe('karideo App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to app!');
});
});

11
front/e2e/app.po.ts Normal file
View File

@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}

View File

@ -0,0 +1,14 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"baseUrl": "./",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

33
front/karma.conf.js Normal file
View File

@ -0,0 +1,33 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular/cli'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular/cli/plugins/karma')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};

13309
front/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

48
front/package.json Normal file
View File

@ -0,0 +1,48 @@
{
"name": "karideo",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^5.2.0",
"@angular/common": "^5.2.0",
"@angular/compiler": "^5.2.0",
"@angular/core": "^5.2.0",
"@angular/forms": "^5.2.0",
"@angular/http": "^5.2.0",
"@angular/platform-browser": "^5.2.0",
"@angular/platform-browser-dynamic": "^5.2.0",
"@angular/router": "^5.2.0",
"core-js": "^2.4.1",
"rxjs": "^5.5.6",
"zone.js": "^0.8.19"
},
"devDependencies": {
"@angular/cli": "~1.7.3",
"@angular/compiler-cli": "^5.2.0",
"@angular/language-service": "^5.2.0",
"@types/jasmine": "~2.8.3",
"@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60",
"codelyzer": "^4.0.1",
"jasmine-core": "~2.8.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~2.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-node": "~4.1.0",
"tslint": "~5.9.1",
"typescript": "~2.5.3"
}
}

28
front/protractor.conf.js Normal file
View File

@ -0,0 +1,28 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

22
front/readme.md Normal file
View File

@ -0,0 +1,22 @@
Start the application:
```
npm install
```
upgrade package
```
npm audit fix
```
start the application:
```
npx ng serve
```

View File

@ -0,0 +1,16 @@
import { trigger, state, animate, transition, style } from '@angular/animations';
export const fadeInAnimation =
trigger('fadeInAnimation', [
// route 'enter' transition
transition(':enter', [
// styles at start of transition
style({ opacity: 0 }),
// animation and styles at end of transition
animate('.5s', style({ opacity: 1 }))
]),
]);

View File

@ -0,0 +1,2 @@
export * from './fade-in.animation';
export * from './slide-in-out.animation';

View File

@ -0,0 +1,51 @@
import { trigger, state, animate, transition, style } from '@angular/animations';
export const slideInOutAnimation =
trigger('slideInOutAnimation', [
// end state styles for route container (host)
state('*', style({
// the view covers the whole screen with a semi tranparent background
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.8)'
})),
// route 'enter' transition
transition(':enter', [
// styles at start of transition
style({
// start with the content positioned off the right of the screen,
// -400% is required instead of -100% because the negative position adds to the width of the element
right: '-400%',
// start with background opacity set to 0 (invisible)
backgroundColor: 'rgba(0, 0, 0, 0)'
}),
// animation and styles at end of transition
animate('.5s ease-in-out', style({
// transition the right position to 0 which slides the content into view
right: 0,
// transition the background opacity to 0.8 to fade it in
backgroundColor: 'rgba(0, 0, 0, 0.8)'
}))
]),
// route 'leave' transition
transition(':leave', [
// animation and styles at end of transition
animate('.5s ease-in-out', style({
// transition the right position to -400% which slides the content out of view
right: '-400%',
// transition the background opacity to 0 to fade it out
backgroundColor: 'rgba(0, 0, 0, 0)'
}))
])
]);

View File

@ -0,0 +1,42 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ModuleWithProviders } from '@angular/core';
import { HomeComponent } from './home/home.component';
import { TypeDetailComponent } from './type-detail/type-detail.component';
import { LoginComponent } from './login/login.component';
import { SignUpComponent } from './sign-up/sign-up.component';
import { SettingsComponent } from './settings/settings.component';
//import { HelpComponent } from './help/help.component';
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full'},
{ path: 'home', component: HomeComponent },
{ path: 'type/:id', component: TypeDetailComponent },
{ path: 'login', component: LoginComponent },
{ path: 'signup', component: SignUpComponent },
{ path: 'settings', component: SettingsComponent },
/*{ path: 'help', component: HelpComponent }*/
];
/*
@NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule {}
*/
export const routing: ModuleWithProviders = RouterModule.forRoot(routes);

View File

@ -0,0 +1,10 @@
<!-- exercice section -->
<app-top-menu></app-top-menu>
<!--
<div class="main-content" ng-include="currentDisplay" ng-if="currentDisplay != ''"></div>
<div class="main-modal" ng-include="currentModal" ng-if="currentModal != ''" ></div> <!-- (click)="onOutModal()" -->
-->
<div class="main-content">
<router-outlet></router-outlet>
</div>

View File

@ -0,0 +1,42 @@
#create-exercice-button {
position: fixed;
display: block;
right: 0;
bottom: 0;
margin-right: 40px;
margin-bottom: 40px;
z-index: 900;
}
#save-exercice-button {
position: fixed;
display: block;
right: 0;
bottom: 0;
margin-right: 110px;
margin-bottom: 40px;
z-index: 900;
}
.main-content {
position: absolute;
width: 100%;
height: ~"calc(100% - 56px)";
top: 56px;
left: 0;
margin: 0;
padding: 0;
display: block;
position: fixed;
//background-color:#FF0;
.main-reduce {
width: 80%;
height: 100%;
margin: 0;
padding: 0px 10% 0px 10%;
display: block;
overflow-y:scroll;
}
}

View File

@ -0,0 +1,27 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});

View File

@ -0,0 +1,54 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit} from '@angular/core';
import { UserService } from './user.service';
import { SessionService } from './session.service';
import { CookiesService } from './cookies.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: [
'./app.component.less',
]
})
export class AppComponent implements OnInit {
title = 'Karideo';
constructor(private cookiesService: CookiesService,
private userService: UserService,
private sessionService: SessionService) {
}
ngOnInit() {
let login = this.cookiesService.get("yota-login");
let password = this.cookiesService.get("yota-password");
if ( login != ""
&& password != ""
&& password.length > 40) {
console.log("Get previous connection ... " + login + ":xxxxxx");
let self = this;
this.userService.loginSha(login, password)
.then(function(response) {
console.log("auto log ==> OK");
self.sessionService.create(response['sessionId'],
response['login'],
response['email'],
response['role'],
response['avatar']);
//self.router.navigate(['home']);
}).catch(function(response) {
console.log("auto log ==> Error");
self.cookiesService.remove("yota-login");
self.cookiesService.remove("yota-password");
});
}
}
}

View File

@ -0,0 +1,81 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { routing } from './app-routing.module';
import { CardListComponent } from './card-list/card-list.component';
import { AuthService } from './auth.service';
import { TopMenuComponent } from './top-menu/top-menu.component';
import { ElementGroupComponent } from './element-group/element-group.component';
import { ElementSaisonComponent } from './element-saison/element-saison.component';
import { ElementVideoComponent } from './element-video/element-video.component';
import { LoginComponent } from './login/login.component';
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 { 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';
import { GroupService } from './group.service';
import { TypeService } from './type.service';
import { SaisonService } from './saison.service';
import { VideoService } from './video.service';
import { SessionService } from './session.service';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
TopMenuComponent,
ElementGroupComponent,
ElementSaisonComponent,
ElementVideoComponent,
LoginComponent,
SignUpComponent,
ValidateEmailComponent,
HomeComponent,
TypeDetailComponent,
SettingsComponent,
ErrorViewerComponent,
ErrorComponent
],
imports: [
BrowserModule,
RouterModule,
routing,
BrowserAnimationsModule,
HttpClientModule
],
providers: [
HttpWrapperService,
AuthService,
SessionService,
CookiesService,
UserService,
TypeService,
GroupService,
SaisonService,
VideoService
],
bootstrap: [
AppComponent
]
})
export class AppModule { }

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { AuthService } from './auth.service';
describe('AuthService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [AuthService]
});
});
it('should be created', inject([AuthService], (service: AuthService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,15 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable } from '@angular/core';
@Injectable()
export class AuthService {
constructor() {
}
}

View File

@ -0,0 +1,3 @@
<p>
card-list works!
</p>

View File

@ -0,0 +1,21 @@
.main-content {
position: absolute;
width: 100%;
height: ~"calc(100% - 56px)";
top: 56px;
left: 0;
margin: 0;
padding: 0;
display: block;
position: fixed;
background-color:#FF0;
.main-reduce {
width: 80%;
height: 100%;
margin: 0;
padding: 0px 10% 0px 10%;
display: block;
overflow-y:scroll;
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CardListComponent } from './card-list.component';
describe('CardListComponent', () => {
let component: CardListComponent;
let fixture: ComponentFixture<CardListComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CardListComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CardListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-card-list',
templateUrl: './card-list.component.html',
styleUrls: ['./card-list.component.less']
})
export class CardListComponent implements OnInit {
//@Input() cards: Array<any>;
constructor() { }
ngOnInit() {
}
}

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { CookiesService } from './cookies.service';
describe('CookiesService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [CookiesService]
});
});
it('should be created', inject([CookiesService], (service: CookiesService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,46 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable } from '@angular/core';
@Injectable()
export class CookiesService {
constructor() {
}
set(cname, cvalue, exdays) {
if (this.get(cname) != "") {
// reset previous cookies...
document.cookie = cname + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/";
}
let d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
let expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
remove(cname) {
this.set(cname, "", 0);
}
get(cname) {
let name = cname + "=";
let ca = document.cookie.split(';');
for(let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
}

View File

@ -0,0 +1,3 @@
<div>
{{name}}
</div>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ElementGroupComponent } from './top-menu.component';
describe('ElementGroupComponent', () => {
let component: ElementGroupComponent;
let fixture: ComponentFixture<ElementGroupComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ElementGroupComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ElementGroupComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,46 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable, Component, OnInit, Input } from '@angular/core';
//import { AppRoutingModule } from "../app-routing.module";
import { Router } from "@angular/router";
import { ActivatedRoute, Params } from '@angular/router';
import { GroupService } from '../group.service';
@Component({
selector: 'app-element-group',
templateUrl: './element-group.component.html',
styleUrls: ['./element-group.component.less']
})
@Injectable()
export class ElementGroupComponent implements OnInit {
// input parameters
@Input() id_group:number = -1;
@Input() id_type:number = -1;
error:string = ""
name:string = "plouf"
constructor(private router: Router,
private groupService: GroupService) {
}
ngOnInit() {
this.name = "ll " + this.id_type + "+" + this.id_group
let self = this;
console.log("get parameter id: " + this.id_type);
this.groupService.get(this.id_group)
.then(function(response) {
self.error = "";
self.name = response.name
}).catch(function(response) {
self.error = "Can not get the data";
self.name = ""
});
}
}

View File

@ -0,0 +1,3 @@
<div>
Saison {{numberSaison}}
</div>

View File

@ -0,0 +1,2 @@

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ElementSaisonComponent } from './top-menu.component';
describe('ElementSaisonComponent', () => {
let component: ElementSaisonComponent;
let fixture: ComponentFixture<ElementSaisonComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ElementSaisonComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ElementSaisonComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,43 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable, Component, OnInit, Input } from '@angular/core';
//import { AppRoutingModule } from "../app-routing.module";
import { Router } from "@angular/router";
import { ActivatedRoute, Params } from '@angular/router';
import { SaisonService } from '../saison.service';
@Component({
selector: 'app-element-saison',
templateUrl: './element-saison.component.html',
styleUrls: ['./element-saison.component.less']
})
@Injectable()
export class ElementSaisonComponent implements OnInit {
// input parameters
@Input() id_saison:number = -1;
error:string = ""
numberSaison:number = -1
constructor(private router: Router,
private saisonService: SaisonService) {
}
ngOnInit() {
let self = this;
console.log("get saison properties id: " + this.id_saison);
this.saisonService.get(this.id_saison)
.then(function(response) {
self.error = "";
self.numberSaison = response.number
}).catch(function(response) {
self.error = "Can not get the data";
self.numberSaison = -1
});
}
}

View File

@ -0,0 +1,4 @@
<div>
{{name}}<br/>
{{description}}
</div>

View File

@ -0,0 +1,2 @@

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ElementTypeComponent } from './top-menu.component';
describe('ElementTypeComponent', () => {
let component: ElementTypeComponent;
let fixture: ComponentFixture<ElementTypeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ElementTypeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ElementTypeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,47 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable, Component, OnInit, Input } from '@angular/core';
//import { AppRoutingModule } from "../app-routing.module";
import { Router } from "@angular/router";
import { ActivatedRoute, Params } from '@angular/router';
import { TypeService } from '../type.service';
@Component({
selector: 'app-element-type',
templateUrl: './element-type.component.html',
styleUrls: ['./element-type.component.less']
})
@Injectable()
export class ElementTypeComponent implements OnInit {
// input parameters
@Input() id_type:number = -1;
error:string = ""
name:string = ""
description:string = ""
constructor(private router: Router,
private typeService: TypeService) {
}
ngOnInit() {
this.name = "ll " + this.id_type
let self = this;
console.log("get parameter id: " + this.id_type);
this.typeService.get(this.id_type)
.then(function(response) {
self.error = "";
self.name = response.name
self.description = response.description
}).catch(function(response) {
self.error = "Can not get the data";
self.name = ""
self.description = ""
});
}
}

View File

@ -0,0 +1,3 @@
<div>
{{name}}
</div>

View File

@ -0,0 +1,3 @@

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ElementVideoComponent } from './top-menu.component';
describe('ElementVideoComponent', () => {
let component: ElementVideoComponent;
let fixture: ComponentFixture<ElementVideoComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ElementVideoComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ElementVideoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,67 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable, Component, OnInit, Input } from '@angular/core';
//import { AppRoutingModule } from "../app-routing.module";
import { Router } from "@angular/router";
import { ActivatedRoute, Params } from '@angular/router';
import { VideoService } from '../video.service';
@Component({
selector: 'app-element-video',
templateUrl: './element-video.component.html',
styleUrls: ['./element-video.component.less']
})
@Injectable()
export class ElementVideoComponent implements OnInit {
// input parameters
@Input() 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 = ""
constructor(private router: Router,
private videoService: VideoService) {
}
ngOnInit() {
this.name = "ll " + this.id_video
let self = this;
console.log("get parameter id: " + this.id_video);
this.videoService.get(this.id_video)
.then(function(response) {
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
}).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 = ""
});
}
}

View File

@ -0,0 +1,3 @@
<p>
error-viewer works!
</p>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ErrorViewerComponent } from './error-viewer.component';
describe('ErrorViewerComponent', () => {
let component: ErrorViewerComponent;
let fixture: ComponentFixture<ErrorViewerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ErrorViewerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ErrorViewerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,21 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-error-viewer',
templateUrl: './error-viewer.component.html',
styleUrls: ['./error-viewer.component.less']
})
export class ErrorViewerComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

View File

@ -0,0 +1,3 @@
<p>
error works!
</p>

View File

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ErrorComponent } from './error.component';
describe('ErrorComponent', () => {
let component: ErrorComponent;
let fixture: ComponentFixture<ErrorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ErrorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ErrorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,21 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-error',
templateUrl: './error.component.html',
styleUrls: ['./error.component.less']
})
export class ErrorComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { GroupService } from './group.service';
describe('GroupService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [GroupService]
});
});
it('should be created', inject([GroupService], (service: GroupService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,39 @@
import { Injectable } from '@angular/core';
import { HttpWrapperService } from 'app/http-wrapper.service';
@Injectable()
export class GroupService {
// 0: Not hide password; 1 hide password;
private identificationVersion: number = 1;
constructor(private http: HttpWrapperService) {
console.log("Start GroupService");
}
get(_id:number):any {
console.log("Get All data from types");
const httpOption = { 'Content-Type': 'application/json' };
let url = "group/" + _id;
console.log("call GET " + url);
return new Promise((resolve, reject) => {
this.http.get(url, httpOption, {})
.then(function(response: any) {
if (response.status == 200) {
resolve(response.data);
console.log("get data from type : " + response.data);
return;
}
reject("An error occured");
}, function(response: any) {
if (typeof response.data === 'undefined') {
reject("return ERROR undefined");
} else {
reject("return ERROR " + JSON.stringify(response.data, null, 2));
}
});
});
};
}

View File

@ -0,0 +1,3 @@
<p>
help works!
</p>

View File

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HelpComponent } from './help.component';
describe('HelpComponent', () => {
let component: HelpComponent;
let fixture: ComponentFixture<HelpComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HelpComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HelpComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-help',
templateUrl: './help.component.html',
styleUrls: ['./help.component.less']
})
export class HelpComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

View File

@ -0,0 +1,11 @@
<div class="main-reduce">
<div class="fill-all">
<div *ngFor="let data of data_list">
<div class="item" (click)="onSelectType(data.id)">
<!--<img src="../../assets/images/type/{{data.id}}.svg" width="45px"/><br/>-->
{{data.name}}
<!--{{data.description}}-->
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,55 @@
.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;
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HomeComponent } from './home.component';
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HomeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,46 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { Router } from "@angular/router";
import { Location } from '@angular/common';
import { fadeInAnimation } from '../_animations/index';
import { TypeService } from '../type.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.less'],
animations: [fadeInAnimation],
host: { '[@fadeInAnimation]': '' }
})
export class HomeComponent implements OnInit {
data_list = [{name:"lkjlkjlkj"}, {name:"lkjlkj222lkj"}, {name:"lkjlk333jlkj"}];
error = "";
constructor(private router: Router,
private locate: Location,
private typeService: TypeService) {
}
ngOnInit() {
let self = this
this.typeService.getData()
.then(function(response) {
self.error = "";
self.data_list = response
}).catch(function(response) {
self.error = "Wrong e-mail/login or password";
self.data_list = []
});
}
onSelectType(_idSelected: number):void {
//this.router.navigate(['type/', { id: _idSelected} ]);
this.router.navigate(['type/' + _idSelected ]);
}
}

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { HttpWrapperService } from './http-wrapper.service';
describe('HttpWrapperService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [HttpWrapperService]
});
});
it('should be created', inject([HttpWrapperService], (service: HttpWrapperService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,85 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map, tap } from 'rxjs/operators';
import { createRESTCall } from 'environments/environment';
@Injectable()
export class HttpWrapperService {
private displayReturn:boolean = true;
constructor(private http: HttpClient) {
}
get(_uriRest:string, _headerOption:any, _params:any) {
let connectionAdresse = createRESTCall(_uriRest, {});
let config = {
params: _params,
headers: new HttpHeaders(_headerOption)
};
return new Promise((resolve, reject) => {
if (this.displayReturn == true) {
console.log("call GET " + connectionAdresse + " params=" + JSON.stringify(_params, null, 2));
}
let request = this.http.get<any>(connectionAdresse, config);
let self = this;
request.subscribe((res: any) => {
if (self.displayReturn == true) {
console.log("!! data " + JSON.stringify(res, null, 2));
}
if (res) {
if (res.httpCode) {
resolve({status:res.httpCode, data:res});
} else {
resolve({status:200, data:res});
}
} else {
resolve({status:200, data:""});
}
},
error => {
if (self.displayReturn == true) {
console.log("an error occured status: " + error.status);
console.log("answer: " + JSON.stringify(error, null, 2));
}
reject({status:error.status, data:error.error});
});
});
}
post(_uriRest:string, _headerOption:any, _data:any) {
let connectionAdresse = createRESTCall(_uriRest, {});
const httpOption = {
headers: new HttpHeaders(_headerOption)
};
return new Promise((resolve, reject) => {
if (this.displayReturn == true) {
console.log("call POST " + connectionAdresse + " data=" + JSON.stringify(_data, null, 2));
}
let request = this.http.post<any>(connectionAdresse, _data, httpOption);
let self = this;
request.subscribe((res: any) => {
if (self.displayReturn == true) {
console.log("!! data " + JSON.stringify(res, null, 2));
}
if (res) {
if (res.httpCode) {
resolve({status:res.httpCode, data:res});
} else {
resolve({status:200, data:res});
}
} else {
resolve({status:200, data:""});
}
},
error => {
if (self.displayReturn == true) {
console.log("an error occured status: " + error.status);
console.log("answer: " + JSON.stringify(error, null, 2));
}
reject({status:error.status, data:error.error});
});
});
}
}

View File

@ -0,0 +1,41 @@
<div class="full">
<div class="color-background-vignette container-global">
<div class="imgContainer">
<img src="assets/images/avatar_generic.svg" alt="Avatar" class="avatar"/>
</div>
<div class="container">
<label for="login_field"><b>{{loginType}}</b></label>
<input id="username"
name="username"
type="text"
required=""
placeholder="Enter Username/e-mail"
[value]="login"
(input)="checkLogin($event.target.value)"
/>
<div class="error color-shadow-black" *ngIf="loginHelp">{{loginHelp}}</div>
<label for="password"><b>Password</b></label> <a class="forgot" href="#">Forgot password?</a>
<input type="password"
id="password"
name="password"
placeholder="Enter Password"
required=""
[value]="password"
(input)="checkPassword($event.target.value)"
/>
<div class="error color-shadow-black" *ngIf="passHelp">{{passHelp}}</div>
<label class="container-checkbox">
Remember me
<input type="checkbox" ng-model="rememberMe"/>
<span class="checkmark"></span>
</label>
</div>
<div class="container">
<button class="button cancel color-button-cancel color-shadow-black" (click)="onCancel()">Cancel</button>
<button class="button login color-button-validate color-shadow-black" id="login-button" [disabled]="loginButtonDisabled" (click)="onLogin()" type="submit">Login</button>
</div>
<div class="container">
{{error}}
</div>
</div>
</div>

View File

@ -0,0 +1,104 @@
.full{
width:100%;
height:100%;
right:0;
margin:0;
padding:0;
border:0;
float:right;
display:block;
}
input[type=text], input[type=password] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
.login {
margin: 2% 2%;
width: 45%;
}
.cancel {
margin: 2% 2%;
width: 45%;
}
.imgContainer {
text-align: center;
margin: 15px 0 0 0;
}
img.avatar {
width: 150px;
border-radius: 50%;
}
.container-global {
padding: 16px 32px 16px 32px;
}
.container {
padding: 16px 0 0 0;
}
span.psw {
float: right;
padding-top: 16px;
}
.forgot {
color: #00B;
font-size: 14px;
float: right;
buttum: 0;
line-height: 24px;
}
.error {
background-color: #f44336;
position: absolute;
z-index: 10;
display: block;
max-width: 450px;
padding: 5px 8px;
margin: 2px 0 0;
font-size: 16px;
font-weight: 400;
border-style: solid;
border-width: 0px;
box-sizing: border-box;
&:after, &:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-bottom-color: #f44336;
border-width: 10px;
margin-left: -10px;
}
}
.container-global {
position:relative;
max-width:400px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~"translate(-50%, -50%)";
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoginComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,167 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { Router } from "@angular/router";
import { Location } from '@angular/common';
import { fadeInAnimation } from '../_animations/index';
import { slideInOutAnimation } from '../_animations/index';
import { UserService } from '../user.service';
import { SessionService } from '../session.service';
import { CookiesService } from '../cookies.service';
export let checkLoginValidity = function(_value:string):boolean {
let regexCheck = new RegExp("^[a-zA-Z0-9_\.-]+$");
if (regexCheck.test(_value)) {
return true;
}
return false;
};
export let checkEmailValidity = function(_value:string):boolean {
let regexCheck = new RegExp("^[a-zA-Z0-9_\.@-]+@[a-zA-Z0-9_\.-]+\\.[a-zA-Z]+$");
if (regexCheck.test(_value)) {
return true;
}
return false;
};
export let checkPasswordValidity = function(_value:string):boolean {
let regexCheck = new RegExp("^[a-zA-Z0-9_\.@ %:;,=}{\?\!\*\+\(\)\[\]\|&#%~°/\\\<\>-]+$");
if (regexCheck.test(_value)) {
return true;
}
return false;
};
declare function SHA512(param1: any): any;
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.less'],
animations: [fadeInAnimation],
host: { '[@fadeInAnimation]': '' }
})
export class LoginComponent implements OnInit {
public loginOK:boolean = false;
public loginHelp:string = "";
public login:string = "";
public passOK:boolean = false;
public passHelp:string = "";
public password:string = "";
public loginButtonDisabled:boolean = true;
public error:string = "";
public loginType:string = "Username/E-mail";
public rememberMe:boolean = true;
constructor(private router: Router,
private locate: Location,
private cookiesService: CookiesService,
private userService: UserService,
private sessionService: SessionService) {
}
ngOnInit() {
// TODO : If already loaded ==> jusp in the home page ...
}
updateButtonVisibility():void {
if ( this.loginOK == true
&& this.passOK == true) {
this.loginButtonDisabled = false;
} else {
this.loginButtonDisabled = true;
}
this.error = "";
}
checkLogin(_newValue:string):void {
this.login = _newValue;
if (this.login == null) {
this.loginOK = false;
this.loginHelp = "";
this.updateButtonVisibility();
return;
}
if (this.login.length < 6) {
this.loginOK = false;
this.loginHelp = "Need 6 characters";
this.loginType = "Username/E-mail";
this.updateButtonVisibility();
return;
}
if (checkLoginValidity(this.login) == true) {
this.loginOK = true;
this.loginHelp = "";
this.loginType = "Username";
} else {
if (checkEmailValidity(this.login) == true) {
this.loginOK = true;
this.loginHelp = "";
this.loginType = "E-mail";
} else {
this.loginOK = false;
this.loginHelp = 'Not valid: characters, numbers, "_-." and email format: you@example.com';
}
}
this.updateButtonVisibility();
}
checkPassword(_newValue:string):void {
this.password = _newValue;
if (this.password == null) {
this.passOK = false;
this.passHelp = "";
this.updateButtonVisibility();
return;
}
if (this.password.length < 6) {
this.passOK = false;
this.passHelp = "Need 6 characters";
} else {
if (checkPasswordValidity(this.password) == true) {
this.passOK = true;
this.passHelp = "";
} else {
this.passOK = false;
this.passHelp = 'Not valid: characters, numbers and "_-:;.,?!*+=}{([|)]% @&~#/\<>"';
}
}
this.updateButtonVisibility();
}
onLogin():void {
this.sessionService.destroy();
let self = this
this.userService.login(this.login, this.password)
.then(function(response) {
self.error = "Login ...";
self.sessionService.create(response['sessionId'],
response['login'],
response['email'],
response['role'],
response['avatar']);
if (self.rememberMe == true) {
self.cookiesService.set("yota-login", response['login'], 365);
self.cookiesService.set("yota-password", SHA512(self.password), 365);
}
self.router.navigate(['home']);
}).catch(function(response) {
self.error = "Wrong e-mail/login or password";
});
}
onCancel():void {
console.log("onCancel ... '" + this.login + "':'" + this.password + "'");
this.locate.back();
}
}

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { SaisonService } from './saison.service';
describe('SaisonService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [SaisonService]
});
});
it('should be created', inject([SaisonService], (service: SaisonService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,39 @@
import { Injectable } from '@angular/core';
import { HttpWrapperService } from 'app/http-wrapper.service';
@Injectable()
export class SaisonService {
// 0: Not hide password; 1 hide password;
private identificationVersion: number = 1;
constructor(private http: HttpWrapperService) {
console.log("Start SaisonService");
}
get(_id:number):any {
console.log("Get All data from types");
const httpOption = { 'Content-Type': 'application/json' };
let url = "saison/" + _id;
console.log("call GET " + url);
return new Promise((resolve, reject) => {
this.http.get(url, httpOption, {})
.then(function(response: any) {
if (response.status == 200) {
resolve(response.data);
console.log("get data from type : " + response.data);
return;
}
reject("An error occured");
}, function(response: any) {
if (typeof response.data === 'undefined') {
reject("return ERROR undefined");
} else {
reject("return ERROR " + JSON.stringify(response.data, null, 2));
}
});
});
};
}

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { SessionService } from './session.service';
describe('SessionService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [SessionService]
});
});
it('should be created', inject([SessionService], (service: SessionService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,90 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable, Output, EventEmitter } from '@angular/core'
enum USER_ROLES {
admin = 10000,
user = 1,
guest = 10
}
@Injectable()
export class SessionService {
public id = null;
public userId = null;
public userRole = null;
public userEMail = null;
public userAvatar = null;
//public tocken = null;
@Output() change: EventEmitter<boolean> = new EventEmitter();
constructor() {
}
/**
* @brief Create a new session.
*/
create(sessionId,
userId,
userEMail:string,
userRole:string,
userAvatar:string) {
console.log("Session Create");
this.id = sessionId;
this.userId = userId;
this.userRole = userRole;
this.userEMail = userEMail;
this.userAvatar = userAvatar;
this.change.emit(true);
};
/**
* @brief destroy the current session.
*/
destroy() {
console.log("Session REMOVE");
//Cookies.remove("yota-login");
//Cookies.remove("yota-password");
let last = this.id;
this.id = null;
this.userId = null;
this.userRole = null;
this.userEMail = null;
this.userAvatar = null;
this.change.emit(false);
};
islogged() {
return this.id != null;
}
hasRight(type) {
if (type == USER_ROLES.admin) {
return this.userRole == USER_ROLES.admin;
}
if (type == USER_ROLES.user) {
return this.userRole == USER_ROLES.admin
|| this.userRole == USER_ROLES.user;
}
if (type == USER_ROLES.guest) {
return this.userRole == USER_ROLES.admin
|| this.userRole == USER_ROLES.user
|| this.userRole == USER_ROLES.guest;
}
return false;
}
hasNotRight(type) {
return !this.hasRight(type);
}
getLogin() {
return this.userId;
}
getAvatar() {
if (this.userAvatar == "") {
return "assets/images/avatar_generic.svg";
}
return this.userAvatar;
}
}

View File

@ -0,0 +1,3 @@
<p>
settings works!
</p>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SettingsComponent } from './settings.component';
describe('SettingsComponent', () => {
let component: SettingsComponent;
let fixture: ComponentFixture<SettingsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SettingsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SettingsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,21 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-settings',
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.less']
})
export class SettingsComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

View File

@ -0,0 +1,63 @@
<div class="left">
<div class="global-help">
<div class="comment"><label class="unselectable">Rate and comment your medias</label></div>
<div class="share"><label class="unselectable">Shared personal media at home</label></div>
<div class="time"><label>Keep last view position</label></div>
</div>
</div>
<div class="right">
<div class="modal-content color-background-vignette container-global">
<div class="logo">
</div>
<div class="container">
<label for="login_field" ><b>Login</b></label>
<input id="username"
name="username"
class="{{loginIcon}}"
type="text"
required=""
placeholder="Pick a Username"
[value]="login"
(input)="checkLogin($event.target.value)"
/>
<div class="error color-shadow-black" *ngIf="loginHelp">{{loginHelp}}</div>
<label for="login_field" ><b>E-mail</b></label>
<input id="email"
name="e-mail"
class="{{emailIcon}}"
type="text"
required=""
placeholder="you@example.com"
[value]="email"
(input)="checkEmail($event.target.value)"
/>
<div class="error color-shadow-black" *ngIf="emailHelp">{{emailHelp}}</div>
<label for="password"><b>Password</b></label>
<input type="password"
id="password"
name="password"
class="{{passIcon}}"
placeholder="Enter Password"
required=""
[value]="password"
(input)="checkPassword($event.target.value)"
/>
<div class="error color-shadow-black" *ngIf="passHelp">{{passHelp}}</div>
</div>
<div class="container">
<button class="button fill-x color-button-validate color-shadow-black" id="onSignUp-button" [disabled]="signUpButtonDisabled" (click)="onSignUp()" type="submit"><i class="material-icons">mode_edit</i> Sign up for Karideo</button>
</div>
<div class="container commmon-policy">
By clicking "Sign up for Karideo", you agree to our <a class="" href="https://help.karideo.com/terms" target="_blank">terms of service</a> and <a class="" href="https://help.karideo.com/privacy" target="_blank">privacy policy</a>.<br/>
Well occasionally send you account related emails.
</div>
<div class="container">
<a class="forgot" href="#">Forgot password?</a>
</div>
<div class="container">
{{error}}
</div>
</div>
</div>

View File

@ -0,0 +1,162 @@
.right{
width:50%;
height:100%;
right:0;
margin:0;
padding:0;
border:0;
float:right;
display:block;
}
.left{
width:50%;
height:100%;
left:0;
margin:0;
padding:0;
border:0;
float:left;
display:block;
color: white;
.comment {
background-image: url("../../assets/images/comments.svg");
background-repeat: no-repeat;
background-size: 45px;
/*background-attachment: fixed;*/
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #2b3137;
}
.share {
background-image: url("../../assets/images/share.svg");
background-repeat: no-repeat;
background-size: 45px;
/*background-attachment: fixed;*/
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #2b3137;
}
.time {
background-image: url("../../assets/images/time.svg");
background-repeat: no-repeat;
background-size: 45px;
/*background-attachment: fixed;*/
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #2b3137;
}
}
input[type=text], input[type=password] {
width: 100%;
padding: 12px 35px 12px 15px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
.global-help {
position:relative;
max-width:500px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~"translate(-50%, -50%)";
font-size: 30px;
font-weight: 600;
text-align: left;
line-height: 200%;
}
.container-global {
position:relative;
max-width:400px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~"translate(-50%, -50%)";
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
}
.container {
padding: 16px 0 0 0;
}
span.psw {
float: right;
padding-top: 16px;
}
.help {
color: #E44;
font-size: 14px;
}
.forgot {
color: #00B;
font-size: 14px;
float: right;
buttum: 0;
line-height: 24px;
}
.commmon-policy {
font-size: 13px;
font-weight: 300;
text-align: center;
}
.icon-right-load {
background: white url("../../assets/images/load.svg") right no-repeat;
background-size: 35px;
padding-right: 17px;
}
.icon-right-validate {
background: white url("../../assets/images/validate.svg") right no-repeat;
background-size: 35px;
padding-right: 17px;
}
.icon-right-not-validate {
background: white url("../../assets/images/validate-not.svg") right no-repeat;
background-size: 35px;
padding-right: 17px;
}
.error {
background-color: #f44336;
position: absolute;
z-index: 10;
display: block;
max-width: 450px;
padding: 5px 8px;
margin: 2px 0 0;
font-size: 16px;
font-weight: 400;
border-style: solid;
border-width: 0px;
box-sizing: border-box;
&:after, &:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-bottom-color: #f44336;
border-width: 10px;
margin-left: -10px;
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SignUpComponent } from './sign-up.component';
describe('SignUpComponent', () => {
let component: SignUpComponent;
let fixture: ComponentFixture<SignUpComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SignUpComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SignUpComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,234 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, OnInit } from '@angular/core';
import { Router } from "@angular/router";
import { checkLoginValidity, checkEmailValidity, checkPasswordValidity } from '../login/login.component';
import { fadeInAnimation } from '../_animations/index';
import { UserService } from '../user.service';
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.less'],
animations: [fadeInAnimation],
host: { '[@fadeInAnimation]': '' }
})
export class SignUpComponent implements OnInit {
private signUp_iconWrong:string = "icon-right-not-validate";
private signUp_iconWait:string = "icon-right-load";
private signUp_iconRight:string = "icon-right-validate";
public login:string = "";
public loginOK:boolean = false;
public loginHelp:string = "";
public loginIcon:string = "";
public email:string = "";
public emailOK:boolean = false;
public emailHelp:string = "";
public emailIcon:string = "";
public password:string = "";
public passOK:boolean = false;
public passHelp:string = "";
public passIcon:string = "";
public signUpButtonDisabled:boolean = true;
public error:string = "";
public rememberMe:boolean = true;
constructor(private userService: UserService,
private router: Router) {
}
ngOnInit() {
}
updateButtonVisibility():void {
if ( this.loginOK == true
&& this.passOK == true
&& this.emailOK == true) {
this.signUpButtonDisabled = false;
} else {
this.signUpButtonDisabled = true;
}
this.error = "";
}
checkLogin(_newValue:string):void {
//this.userService.loginSha("loooogin", "ekljkj", true);
this.login = _newValue;
if ( this.login == null
|| this.login.length == 0) {
this.loginOK = false;
this.loginIcon = "";
this.loginHelp = "";
this.updateButtonVisibility();
return;
}
if (this.login.length < 6) {
this.loginOK = false;
this.loginHelp = "Need 6 characters";
this.loginIcon = "";
this.updateButtonVisibility();
return;
}
if (checkLoginValidity(this.login) == true) {
this.loginOK = false;
//this.loginHelp = "check in progress...";
this.loginIcon = this.signUp_iconWait;
let self = this;
this.userService.checkLogin(this.login).then(function() {
// check if the answer is correct with the question
if (_newValue != self.login) {
return;
}
// the login exist ... ==> it is found...
self.loginOK = false;
self.loginHelp = "Login already used ...";
self.loginIcon = self.signUp_iconWrong;
self.updateButtonVisibility();
}, function(error: number) {
console.log("1 " + self);
// check if the answer is correct with the question
if (_newValue != self.login) {
return;
}
if (error == 404) {
self.loginOK = true;
self.loginHelp = "";
self.loginIcon = self.signUp_iconRight;
self.updateButtonVisibility();
return;
}
console.log("Status " + error);
self.loginOK = false;
self.loginHelp = "Login already used ...";
self.loginIcon = self.signUp_iconWrong;
self.updateButtonVisibility();
});
} else {
this.loginOK = false;
this.loginHelp = 'Not valid: characters, numbers and "_-."';
}
this.updateButtonVisibility();
}
checkEmail(_newValue:string):void {
this.email = _newValue
if ( this.email == null
|| this.email.length == 0) {
this.emailOK = false;
this.updateButtonVisibility();
this.emailIcon = "";
this.emailHelp = "";
return;
}
if (this.email.length < 6) {
this.emailOK = false;
this.emailHelp = "Need 6 characters";
this.updateButtonVisibility();
this.passIcon = "";
return;
}
if (checkEmailValidity(this.email) == true) {
this.emailOK = false;
this.emailHelp = "";
//this.loginHelp = "check in progress...";
this.emailIcon = this.signUp_iconWait;
let self = this;
this.userService.checkEMail(this.email).then(function() {
// check if the answer is correct with the question
if (_newValue != self.email) {
return;
}
// the email exist ... ==> it is found...
self.emailOK = false;
self.emailHelp = "email already used ...";
self.emailIcon = self.signUp_iconWrong;
self.updateButtonVisibility();
}, function(error: number) {
// check if the answer is correct with the question
if (_newValue != self.email) {
return;
}
if (error == 404) {
self.emailOK = true;
self.emailHelp = "";
self.emailIcon = self.signUp_iconRight;
self.updateButtonVisibility();
return;
}
console.log("Status " + error);
self.emailOK = false;
self.emailHelp = "email already used ...";
self.emailIcon = self.signUp_iconWrong;
self.updateButtonVisibility();
});
} else {
this.emailOK = false;
this.emailHelp = 'Not valid: characters, numbers, "_-." and email format: you@example.com';
}
this.updateButtonVisibility();
}
checkPassword(_newValue:string):void {
this.password = _newValue
console.log("ooooooooooooooo " + this.password);
if (this.password == null) {
this.passOK = false;
this.passHelp = "";
this.updateButtonVisibility();
return;
}
if (this.password.length < 6) {
this.passOK = false;
this.passHelp = "Need 6 characters";
} else {
if (checkPasswordValidity(this.password) == true) {
this.passOK = true;
this.passHelp = "";
} else {
this.passOK = false;
this.passHelp = 'Not valid: characters, numbers and "_-:;.,?!*+=}{([|)]% @&~#/\<>"';
}
}
this.updateButtonVisibility();
}
onSignUp():void {
console.log("Validate ... ");
if (this.signUpButtonDisabled == true) {
// TODO: ... notify user ...
console.log("Not permited action ... ==> control does not validate this action ...");
return;
}
let self = this;
// disable the currect button
this.signUpButtonDisabled = true;
this.userService.create(this.login, this.email, this.password).then(
function(value) {
console.log("User created");
self.router.navigate(['login']);
//TODO : send a generic message in the pop-up enevts... self.emailHelp = "email already used ... (error 2)";
}, function(value) {
console.log("User NOT created");
//TODO : send a generic message in the pop-up enevts... self.emailHelp = "email already used ... (error 2)";
});
}
onCancel():void {
console.log("onCancel ... '" + this.login + "':'" + this.password + "'");
//$rootScope.currentModal = "";
}
}

View File

@ -0,0 +1,43 @@
<div class="top">
<div id="main-menu" class="main-menu color-menu-background">
<button class="item"
(click)="onHome()">
<i class="material-icons">home</i> Home
</button>
<button class="item"
*ngIf="login == null"
style="float:right;"
(click)="onSignIn()">
<i class="material-icons">add_circle_outline</i> Sign-up
</button>
<button class="item"
*ngIf="login == null"
style="float:right;"
(click)="onLogin()"> <!-- [routerLink]="['./login']" routerLinkActive="active" -->
<i class="material-icons">account_circle</i> Sign-in
</button>
<button class="item"
*ngIf="login != null"
style="float:right; height:56px;"
(click)="onAvatar()">
<img class="avatar" src="{{avatar}}"/>
</button>
</div>
<div class="fill-all" *ngIf="login != null &amp;&amp; displayUserMenu == true" (click)="onOutUserProperty()">
<!-- (click)="onOutUserProperty()" -->
<div class="user-menu color-menu-background">
<button class="item" disabled="disabled">
Sign in as <b>{{login}}</b>
</button>
<button class="item" (click)="onHelp()" >
<i class="material-icons">help_outline</i> Help
</button>
<button class="item" (click)="onSetting()" >
<i class="material-icons">settings</i> Settings
</button>
<button class="item" (click)="onLogout()" >
<i class="material-icons">exit_to_app</i> Sign out
</button>
</div>
</div>
</div>

View File

@ -0,0 +1,123 @@
.top {
.user-menu {
position: fixed;
top:75px;
right:15px;
min-width:150px;
min-height:70px;
display: block;
overflow: visible;
box-shadow: none;
flex-direction: column;
flex-wrap: nowrap;
justify-content: flex-start;
box-sizing: border-box;
flex-shrink: 0;
margin: 0;
padding: 0 3px 0 3px;
border: none;
z-index: 300;
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
.item {
display:block;
float: top;
line-height: 56px;
z-index: 4;
margin: 3px 0px 3px 0px;
/*padding: 0px 3px 0px 3px;*/
border: 0px; /*0px 3px 0px 3px solid transparent;*/
/*text-transform: uppercase;*/
font-weight: bold;
font-size: 17px;
width:100%;
}
.material-icons {
vertical-align: middle;
}
/* Create an Arraw on the top ob the box ... */
&:after, &:before {
bottom: 100%;
right: 13px;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-color: rgba(136, 183, 213, 0);
border-bottom-color: #263238;
border-width: 15px;
margin-left: -15px;
}
}
.fill-all {
position: absolute;
top: 0;
left: 0;
width:100%;
height:100%;
/*
background-color: #0F0;
*/
z-index:400;
}
.main-menu {
position: fixed;
top:0px;
left:0px;
display: block;
overflow: visible;
box-shadow: none;
min-height: 56px;
flex-direction: column;
flex-wrap: nowrap;
justify-content: flex-start;
box-sizing: border-box;
flex-shrink: 0;
width: 100%;
margin: 0;
padding: 0 12px 0 12px;
border: none;
max-height: 1000px;
z-index: 3;
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
.item {
display:block;
float: left;
line-height: 56px;
z-index: 4;
margin: 0 3px 0 3px;
border: 0;
text-transform: uppercase;
font-weight: bold;
font-size: 17px;
}
.material-icons {
vertical-align: middle;
}
.avatar {
height:42px;
width:42px;
border-radius: 50%;
vertical-align: middle;
}
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TopMenuComponent } from './top-menu.component';
describe('TopMenuComponent', () => {
let component: TopMenuComponent;
let fixture: ComponentFixture<TopMenuComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TopMenuComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TopMenuComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,165 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable, Component, OnInit } from '@angular/core';
//import { AppRoutingModule } from "../app-routing.module";
import { Router } from "@angular/router";
import { ActivatedRoute, Params } from '@angular/router';
import { SessionService } from '../session.service';
@Component({
selector: 'app-top-menu',
templateUrl: './top-menu.component.html',
styleUrls: ['./top-menu.component.less']
})
@Injectable()
export class TopMenuComponent implements OnInit {
public login: string = null;//Session.getLogin();
public avatar: string = null;//Session.getAvatar();
public displayUserMenu: boolean = false;
constructor(private router: Router,
private sessionService: SessionService) {
}
ngOnInit() {
this.sessionService.change.subscribe(isConnected => {
console.log("receive event from session ..." + isConnected);
if (isConnected == false) {
this.login = null;
this.avatar = null;
this.displayUserMenu = false;
} else {
this.login = this.sessionService.getLogin();
this.avatar = this.sessionService.getAvatar();
this.displayUserMenu = false;
console.log(" login:" + this.sessionService.getLogin());
console.log(" avatar:" + this.avatar);
}
});
}
onAvatar(): void {
console.log("onAvatar() " + this.displayUserMenu);
this.displayUserMenu = !this.displayUserMenu;
}
onHome(): void {
console.log("onHome()");
this.router.navigate(['home']);
}
onSignIn(): void {
console.log("onSignIn()");
//Session.destroy();
this.router.navigate(['signup']);
}
onLogin(): void {
console.log("onLogin()");
//Session.destroy();
this.router.navigate(['login']);
this.displayUserMenu = false;
}
onLogout(): void {
console.log("onLogout()");
this.sessionService.destroy();
this.router.navigate(['home']);
this.displayUserMenu = false;
}
onSetting(): void {
console.log("onSetting()");
this.router.navigate(['settings']);
this.displayUserMenu = false;
}
onHelp(): void {
console.log("onHelp()");
this.router.navigate(['help']);
this.displayUserMenu = false;
}
onOutUserProperty(): void {
console.log("onOutUserProperty ==> event...");
this.displayUserMenu = false;
}
}
/*
app.controller("controlerTop", function($scope, $rootScope, SESSION_EVENTS, Session, USER_ROLES) {
$rootScope.$on(SESSION_EVENTS.login, function(event) {
console.log("event ... " + SESSION_EVENTS.login);
$scope.login = Session.getLogin();
$scope.avatar = Session.getAvatar();
$scope.displayUserMenu = false;
$rootScope.currentDisplay = "home.html";
$rootScope.currentModal = "";
$rootScope.currentModalCanRemove = false;
});
$rootScope.$on(SESSION_EVENTS.logout, function(event) {
console.log("event ... " + SESSION_EVENTS.login);
$scope.login = Session.getLogin();
$scope.avatar = Session.getAvatar();
$scope.displayUserMenu = false;
$rootScope.currentDisplay = "home.html";
$rootScope.currentModal = "";
$rootScope.currentModalCanRemove = false;
});
$scope.login = Session.getLogin();
$scope.avatar = Session.getAvatar();
$scope.displayUserMenu = false;
$scope.onAvatar = function() {
$scope.displayUserMenu = !$scope.displayUserMenu;
}
$scope.onHome = function() {
$rootScope.currentDisplay = "home.html";
}
$scope.onSignIn = function() {
Session.destroy();
$rootScope.currentDisplay = "signUp.html";
}
$scope.onLogin = function() {
Session.destroy();
$rootScope.currentModal = "login.html";
$scope.displayUserMenu = false;
}
$scope.onLogout = function() {
Session.destroy();
$rootScope.currentDisplay = "home.html";
$scope.displayUserMenu = false;
}
$scope.onSetting = function() {
$rootScope.currentModal = "";
$rootScope.currentDisplay = "setting.html";
$scope.displayUserMenu = false;
}
$scope.onHelp = function() {
$rootScope.currentModal = "";
$rootScope.currentDisplay = "help.html";
$scope.displayUserMenu = false;
}
$scope.onOutUserProperty = function() {
console.log("onOutUserProperty ==> event...");
$rootScope.currentModal = "";
$scope.displayUserMenu = false;
}
});
*/

View File

@ -0,0 +1,12 @@
<div class="main-reduce">
<div class="fill-all">
<div *ngFor="let data of groups" class="item" (click)="onSelectGroup(data)">
<app-element-group [id_type]="type_id" [id_group]="data"></app-element-group>
</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>

View 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;
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TypeDetailComponent } from './type-detail.component';
describe('TypeDetailComponent', () => {
let component: TypeDetailComponent;
let fixture: ComponentFixture<TypeDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TypeDetailComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TypeDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,71 @@
/** @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 { TypeService } from '../type.service';
@Component({
selector: 'app-type-detail',
templateUrl: './type-detail.component.html',
styleUrls: ['./type-detail.component.less'],
animations: [fadeInAnimation],
host: { '[@fadeInAnimation]': '' }
})
export class TypeDetailComponent implements OnInit {
type_id = -1;
groups_error = "";
groups = [{name:"group1"}, {name:"group2"}, {name:"group3"}];
videos_error = "";
videos = [{name:"video1"}, {name:"video2"}, {name:"video3"}];
constructor(private route: ActivatedRoute,
private router: Router,
private locate: Location,
private typeService: TypeService) {
/*
this.route.params.subscribe(params => {
console.log(params);
if (params["id"]) {
this.doSearch(params["id"]);
}
});
*/
}
ngOnInit() {
this.type_id = parseInt(this.route.snapshot.paramMap.get('id'));
let self = this;
console.log("get parameter id: " + this.type_id);
this.typeService.getSubGroup(this.type_id)
.then(function(response) {
self.groups_error = "";
self.groups = response
}).catch(function(response) {
self.groups_error = "Wrong e-mail/login or password";
self.groups = []
});
this.typeService.getSubVideoNoGroup(this.type_id)
.then(function(response) {
self.videos_error = "";
self.videos = response
}).catch(function(response) {
self.videos_error = "Wrong e-mail/login or password";
self.videos = []
});
}
onSelectGroup(_idSelected: number):void {
this.router.navigate(['group/' + _idSelected ]);
}
onSelectVideo(_idSelected: number):void {
this.router.navigate(['video/' + _idSelected ]);
}
}

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { UserService } from './user.service';
describe('TypeService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [testService]
});
});
it('should be created', inject([TypeService], (service: TypeService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,131 @@
import { Injectable } from '@angular/core';
import { HttpWrapperService } from 'app/http-wrapper.service';
//import { SHA512 } from 'assets/js_3rd_party/sha512';
export interface MessageLogIn {
id: number;
name: string;
description: string;
};
declare function SHA512(param1: any): any;
declare function dateFormat(param1: any, param2: any): any;
@Injectable()
export class TypeService {
// 0: Not hide password; 1 hide password;
private identificationVersion: number = 1;
constructor(private http: HttpWrapperService) {
console.log("Start TypeService");
}
getData():any {
console.log("Get All data from types");
let currentDate:number = dateFormat(new Date(), 'm-d-Y h:i:s ms');
const httpOption = { 'Content-Type': 'application/json' };
let url = "type";
console.log("call GET " + url);
return new Promise((resolve, reject) => {
this.http.get(url, httpOption, {})
.then(function(response: any) {
if (response.status == 200) {
resolve(response.data);
console.log("get data from type : " + response.data);
return;
}
reject("An error occured");
}, function(response: any) {
if (typeof response.data === 'undefined') {
reject("return ERROR undefined");
} else {
reject("return ERROR " + JSON.stringify(response.data, null, 2));
}
});
});
};
get(_id:number):any {
console.log("Get All data from types");
let currentDate:number = dateFormat(new Date(), 'm-d-Y h:i:s ms');
const httpOption = { 'Content-Type': 'application/json' };
let url = "type/" + _id;
console.log("call GET " + url);
return new Promise((resolve, reject) => {
this.http.get(url, httpOption, {})
.then(function(response: any) {
if (response.status == 200) {
resolve(response.data);
console.log("get data from type : " + response.data);
return;
}
reject("An error occured");
}, function(response: any) {
if (typeof response.data === 'undefined') {
reject("return ERROR undefined");
} else {
reject("return ERROR " + JSON.stringify(response.data, null, 2));
}
});
});
};
getSubGroup(_id: number):any {
console.log("Get All data from types");
let currentDate:number = dateFormat(new Date(), 'm-d-Y h:i:s ms');
const httpOption = { 'Content-Type': 'application/json' };
let url = "type/" + _id + "/group";
console.log("call GET " + url);
return new Promise((resolve, reject) => {
this.http.get(url, httpOption, {})
.then(function(response: any) {
if (response.status == 200) {
resolve(response.data);
console.log("get data from type : " + response.data);
return;
}
reject("An error occured");
}, function(response: any) {
if (typeof response.data === 'undefined') {
reject("return ERROR undefined");
} else {
reject("return ERROR " + JSON.stringify(response.data, null, 2));
}
});
});
};
getSubVideoNoGroup(_id: number):any {
console.log("Get All data from types");
let currentDate:number = dateFormat(new Date(), 'm-d-Y h:i:s ms');
const httpOption = { 'Content-Type': 'application/json' };
let url = "type/" + _id + "/video_no_group";
console.log("call GET " + url);
return new Promise((resolve, reject) => {
this.http.get(url, httpOption, {})
.then(function(response: any) {
if (response.status == 200) {
resolve(response.data);
console.log("get data from type : " + response.data);
return;
}
reject("An error occured");
}, function(response: any) {
if (typeof response.data === 'undefined') {
reject("return ERROR undefined");
} else {
reject("return ERROR " + JSON.stringify(response.data, null, 2));
}
});
});
};
}

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { UserService } from './user.service';
describe('UserService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [UserService]
});
});
it('should be created', inject([UserService], (service: UserService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,162 @@
import { Injectable } from '@angular/core';
import { HttpWrapperService } from 'app/http-wrapper.service';
//import { SHA512 } from 'assets/js_3rd_party/sha512';
interface MessageLogIn {
login: string;
methode: string;
time: number;
password: string;
};
interface MessageAnswer_USER_CONNECT {
sessionId: string,
login: string,
eMail: string,
role: string,
avatar: string
};
declare function SHA512(param1: any): any;
declare function dateFormat(param1: any, param2: any): any;
@Injectable()
export class UserService {
// 0: Not hide password; 1 hide password;
private identificationVersion: number = 1;
constructor(private http: HttpWrapperService) {
console.log("Start UserService");
}
login(_login: string, _password: string):any {
return this.loginSha(_login, SHA512(_password));
}
loginSha(_login : string, _password : string) {
console.log("AuthService.login ... '" + _login + "':'" + _password + "'");
let currentDate:number = dateFormat(new Date(), 'm-d-Y h:i:s ms');
let data:MessageLogIn;
// create request:
if (this.identificationVersion == 0) {
data = {
login: _login,
methode: "v0",
time: currentDate,
password: _password
};
} else if (this.identificationVersion == 1) {
data = {
login: _login,
methode: "v1",
time: currentDate,
// we mix the password to be sure that it can not be used an other time ...
password: SHA512("login='" + _login + "';pass='" + _password + "';date='" + currentDate + "'")
};
}
const httpOption = { 'Content-Type': 'application/json' };
console.log("call users/connect data=" + JSON.stringify(data, null, 2));
return new Promise((resolve, reject) => {
this.http.post("rest-auth/login", httpOption, data)
.then(function(response: any) {
if (response.status == 200) {
resolve(response.data);
return;
}
reject("An error occured");
}, function(response: any) {
if (typeof response.data === 'undefined') {
reject("return ERROR undefined");
} else {
reject("return ERROR " + JSON.stringify(response.data, null, 2));
}
});
});
};
create(_login : string, _email : string, _password : string) {
return this.createSha(_login, _email, SHA512(_password));
}
createSha(_login : string, _email : string, _password : string, ) {
let data = {
"methode": "v?",
"login": _login,
"email": _email,
"password": _password
}
const httpOption = { 'Content-Type': 'application/json' };
console.log("call users data=" + JSON.stringify(data, null, 2));
if (this.identificationVersion == 0) {
data["methode"] = "v0"
} else if (this.identificationVersion == 1) {
data["methode"] = "v1"
}
return new Promise((resolve, reject) => {
this.http.post("users", httpOption, data)
.then(function(response: any) {
if (response.status == 200) {
resolve(response.data)
}
reject("An error occured");
}, function(response: any) {
if (typeof response.data === 'undefined') {
reject("return ERROR undefined");
} else {
reject("return ERROR " + JSON.stringify(response.data, null, 2));
}
});
});
};
isAuthenticated():boolean {
//return !!Session.userId;
return false;
};
isAuthorized(_authorizedRoles: string): boolean {
/*
if (!angular.isArray(_authorizedRoles)) {
authorizedRoles = [_authorizedRoles];
}
return ( authService.isAuthenticated()
&& _authorizedRoles.indexOf(Session.userRole) !== -1
);
*/
return false;
};
checkLogin(_login: string) {
let params = {
login: _login
};
return new Promise((resolve, reject) => {
this.http.get("users/check_login", {}, params).then(
(res: Response) => {
resolve()
},
error => {
reject(error.status);
});
});
}
checkEMail(_email: string) {
let params = {
"email": _email
};
return new Promise((resolve, reject) => {
this.http.get("users/check_email", {}, params).then(
(res: Response) => {
resolve()
},
error => {
reject(error.status);
});
});
}
}

View File

@ -0,0 +1,14 @@
<div class="sign" ng-controller="controlerValidateEmail">
<div class="full-back">
<div class="global-help">
<i class="material-icons big-one">email</i>
<div>Waiting email validation ...</div>
</div>
</div>
<button class="button sender color-button-validate color-shadow-light" ng-disabled="syncButtonDisabled" (click)="onSend()">
<i class="material-icons">send</i> re-send the validation code.
</button>
<button class="button last-update color-button-normal color-shadow-light" ng-disabled="sendButtonDisabled" (click)="onCheck()">
<i class="material-icons">loop</i> 18h15
</button>
</div>

View File

@ -0,0 +1,122 @@
sign {
.full-back{
position:absolute;
width:100%;
height:100%;
right:100;
background-color:#2b3137;
background-image: url("../../assets/images/ikon_gray.svg");
background-repeat: no-repeat;
/*
background-size: contain;
*/
background-size: 80%;
background-attachment: fixed;
background-position: 50% 50%;
z-index:-1;
}
.left{
width:50%;
height:100%;
left:0;
margin:0;
padding:0;
border:0;
float:left;
display:block;
color: white;
.comment {
background-image: url("../../assets/images/comments.svg");
background-repeat: no-repeat;
background-size: 45px;
background-attachment: fixed;
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #2b3137;
}
.share {
background-image: url("../../assets/images/share.svg");
background-repeat: no-repeat;
background-size: 45px;
background-attachment: fixed;
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #2b3137;
}
.forget {
background-image: url("../../assets/images/erase.svg");
background-repeat: no-repeat;
background-size: 45px;
background-attachment: fixed;
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #2b3137;
}
.time {
background-image: url("../../assets/images/time.svg");
background-repeat: no-repeat;
background-size: 45px;
background-attachment: fixed;
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #2b3137;
}
}
.global-help {
color: white;
text-shadow:0px 0px 4px #2b3137;
position:relative;
max-width:500px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 30px;
font-weight: 600;
text-align: center;
line-height: 200%;
.big-one {
font-size: 90px;
}
}
.sender {
position: fixed;
display: block;
float: buttom;
top: 80%;
left:50%;
transform: translate(-50%, 0%);
//background-color: #4CAF50;
//padding: 14px 20px;
margin: 1%;
vertical-align: middle;
width:350px;
}
.last-update {
position: fixed;
display: block;
float: buttom;
top: 90%;
left:50%;
transform: translate(-50%, 0%);
//background-color: transparent;
//background-color: #2b3137;
//padding: 14px 20px;
margin: 1%;
vertical-align: middle;
width:350px;
color:white;
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ValidateEmailComponent } from './validate-email.component';
describe('ValidateEmailComponent', () => {
let component: ValidateEmailComponent;
let fixture: ComponentFixture<ValidateEmailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ValidateEmailComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ValidateEmailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,248 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-validate-email',
templateUrl: './validate-email.component.html',
styleUrls: ['./validate-email.component.less']
})
export class ValidateEmailComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
/*
app.controller("controlerValidateEmail", function($scope, $http, $rootScope, AuthService) {
$scope.sendButtonDisabled = false;
$scope.syncButtonDisabled = false;
$scope.error = "";
$scope.rememberMe = true;
$rootScope.currentModalCanRemove = true;
$scope.updateButtonVisibility = function() {
if ( $scope.loginOK == true
&& $scope.passOK == true
&& $scope.emailOK == true) {
$scope.signUpButtonDisabled = false;
} else {
$scope.signUpButtonDisabled = true;
}
$scope.error = "";
}
$scope.checkLogin = function() {
if ( $scope.login == null
|| $scope.login.length == 0) {
$scope.loginOK = false;
$scope.loginIcon = "";
$scope.loginHelp = "";
$scope.updateButtonVisibility();
return;
}
if ($scope.login.length < 6) {
$scope.loginOK = false;
$scope.loginHelp = "Need 6 characters";
$scope.loginIcon = "";
$scope.updateButtonVisibility();
return;
}
if (checkLoginValidity($scope.login) == true) {
$scope.loginOK = false;
//$scope.loginHelp = "check in progress...";
$scope.loginIcon = signUp_iconWait;
let data = {
"login": $scope.login
}
let connectionAdresse = createRESTCall("user/check/login");
let config = {
params: data
};
let tmpLogin = "" + $scope.login;
console.log("call " + connectionAdresse + " data=" + JSON.stringify(data, null, 2));
$http.get(connectionAdresse, config)
.then(function(response) {
// check if the answer is correct with the question
if (tmpLogin != $scope.login) {
return;
}
console.log("Status " + response.status);
console.log("data " + JSON.stringify(response.data, null, 2));
if (response.status == 200) {
// the login exist ... ==> it is found...
$scope.loginOK = false;
$scope.loginHelp = "Login already used ...";
$scope.loginIcon = signUp_iconWrong;
return;
}
$scope.loginOK = false;
$scope.loginHelp = "Login already used ... (error 2)";
}, function(response) {
// check if the answer is correct with the question
if (tmpLogin != $scope.login) {
return;
}
if (response.status == 404) {
$scope.loginOK = true;
$scope.loginHelp = "";
$scope.loginIcon = signUp_iconRight;
return;
}
console.log("Status " + response.status);
console.log("data " + JSON.stringify(response.data, null, 2));
$scope.loginOK = false;
$scope.loginHelp = "Login already used ...";
$scope.loginIcon = signUp_iconWrong;
});
} else {
$scope.loginOK = false;
$scope.loginHelp = 'Not valid: characters, numbers and "_-."';
}
$scope.updateButtonVisibility();
}
$scope.checkEmail = function() {
if ( $scope.email == null
|| $scope.email.length == 0) {
$scope.emailOK = false;
$scope.updateButtonVisibility();
$scope.emailIcon = "";
$scope.emailHelp = "";
return;
}
if ($scope.email.length < 6) {
$scope.emailOK = false;
$scope.emailHelp = "Need 6 characters";
$scope.updateButtonVisibility();
$scope.passIcon = "";
return;
}
if (checkEmailValidity($scope.email) == true) {
$scope.emailOK = true;
$scope.emailHelp = "";
//$scope.loginHelp = "check in progress...";
$scope.emailIcon = signUp_iconWait;
let data = {
"e-mail": $scope.email
}
let connectionAdresse = createRESTCall("user/check/email");
let config = {
params: data
};
let tmpEmail = "" + $scope.email;
console.log("call " + connectionAdresse + " data=" + JSON.stringify(data, null, 2));
$http.get(connectionAdresse, config)
.then(function(response) {
// check if the answer is correct with the question
if (tmpEmail != $scope.email) {
return;
}
console.log("Status " + response.status);
console.log("data " + JSON.stringify(response.data, null, 2));
if (response.status == 200) {
// the email exist ... ==> it is found...
$scope.emailOK = false;
$scope.emailHelp = "email already used ...";
$scope.emailIcon = signUp_iconWrong;
return;
}
$scope.emailOK = false;
$scope.emailHelp = "email already used ... (error 2)";
}, function(response) {
// check if the answer is correct with the question
if (tmpEmail != $scope.email) {
return;
}
if (response.status == 404) {
$scope.emailOK = true;
$scope.emailHelp = "";
$scope.emailIcon = signUp_iconRight;
return;
}
console.log("Status " + response.status);
console.log("data " + JSON.stringify(response.data, null, 2));
$scope.emailOK = false;
$scope.emailHelp = "email already used ...";
$scope.emailIcon = signUp_iconWrong;
});
} else {
$scope.emailOK = false;
$scope.emailHelp = 'Not valid: characters, numbers, "_-." and email format: you@example.com';
}
$scope.updateButtonVisibility();
}
$scope.checkPassword = function() {
if ($scope.password == null) {
$scope.passOK = false;
$scope.passHelp = "";
$scope.updateButtonVisibility();
return;
}
if ($scope.password.length < 6) {
$scope.passOK = false;
$scope.passHelp = "Need 6 characters";
} else {
if (checkPasswordValidity($scope.password) == true) {
$scope.passOK = true;
$scope.passHelp = "";
} else {
$scope.passOK = false;
$scope.passHelp = 'Not valid: characters, numbers and "_-:;.,?!*+=}{([|)]% @&~#/\<>"';
}
}
$scope.updateButtonVisibility();
}
$scope.onSignUp = function() {
if ($scope.signUpButtonDisabled == true) {
// TODO: ... notify user ...
console.log("Not permited action ... ==> control does not validate this action ...");
return;
}
let data = {
"methode": "v0",
"login": $scope.login,
"e-mail": $scope.email,
"password": btoa(CryptoJS.SHA1($scope.password)) // btoa encode i base64
}
let connectionAdresse = createRESTCall("user/add");
let config = {
headers: {
"Content-Type": "application/json"
}
};
let tmpEmail = "" + $scope.email;
console.log("call " + connectionAdresse + " data=" + JSON.stringify(data, null, 2));
$http.post(connectionAdresse, data, config)
.then(function(response) {
console.log("Status " + response.status);
console.log("data " + JSON.stringify(response.data, null, 2));
if (response.status == 200) {
return;
}
$scope.emailOK = false;
$scope.emailHelp = "email already used ... (error 2)";
}, function(response) {
console.log("Status " + response.status);
console.log("data " + JSON.stringify(response.data, null, 2));
});
}
$scope.onCancel = function() {
console.log("onCancel ... '" + $scope.login + "':'" + $scope.password + "'");
$rootScope.currentModal = "";
}
});
*/

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { VideoService } from './video.service';
describe('VideoService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [VideoService]
});
});
it('should be created', inject([VideoService], (service: VideoService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,38 @@
import { Injectable } from '@angular/core';
import { HttpWrapperService } from 'app/http-wrapper.service';
@Injectable()
export class VideoService {
// 0: Not hide password; 1 hide password;
private identificationVersion: number = 1;
constructor(private http: HttpWrapperService) {
console.log("Start VideoService");
}
get(_id:number):any {
const httpOption = { 'Content-Type': 'application/json' };
let url = "video/" + _id;
console.log("call GET " + url);
return new Promise((resolve, reject) => {
this.http.get(url, httpOption, {})
.then(function(response: any) {
if (response.status == 200) {
resolve(response.data);
console.log("get data from type : " + response.data);
return;
}
reject("An error occured");
}, function(response: any) {
if (typeof response.data === 'undefined') {
reject("return ERROR undefined");
} else {
reject("return ERROR " + JSON.stringify(response.data, null, 2));
}
});
});
};
}

View File

View File

@ -0,0 +1,24 @@
/**
* @brief create the rest call element of the link
*/
let createRESTCall = function(api, options) {
// http://localhost/exercice
let basePage = "" + window.location;
if (basePage.endsWith("index.xhtml") == true) {
basePage = basePage.substring(0, basePage.length - 11);
}
if (basePage.endsWith("index.php") == true) {
basePage = basePage.substring(0, basePage.length - 10);
}
let addressServerRest =basePage + "/api/v1/index.php";
if (typeof options === 'undefined') {
options = [];
}
let out = addressServerRest + "?REST=" + api;
for (let iii=0; iii<options.length; iii++) {
out += "&" + options[iii];
}
return out;
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="499"
height="498"
viewBox="0 0 499 498">
<rect
style="fill:#4c83e5;fill-opacity:1;stroke:none;stroke-width:8.82841587;stroke-opacity:1"
width="500"
height="500"
x="0"
y="-1.9999847" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-opacity:1"
d="m 204.04675,299.92172 64.38231,-8.25011 84.38034,95.33059 -50.65607,144.5704 -137.27461,10.07178 -8.02011,-145.66775 z"/>
<path
d="m 151.70726,153.48377 98.32028,-57.471057 56.94703,21.629237 42.18786,87.1369 -8.8547,99.27952 c 0,0 -50.49799,16.08876 -49.46915,20.02305 1.64608,6.29463 -6.63579,19.542 -19.42333,31.06884 -11.04013,9.95169 -21.88069,22.4832 -25.78302,29.80472 -1.77209,3.32477 -3.61064,6.04503 -4.08568,6.04503 -0.47504,0 -2.26404,-4.6125 -3.97555,-10.25 -7.0054,-23.07485 -5.43752,-20.34841 -16.04346,-27.89857 -14.90382,-10.60973 -22.13256,-19.44659 -23.88228,-29.19518 l -0.74599,-4.15625 -49.90362,-18.10466 z"
style="fill:#fbd0a6"/>
<path
d="m 55.528901,495.75001 c 0.527163,-1.2375 3.024666,-9.9 5.550006,-19.25 8.980498,-33.25004 20.717058,-73.14872 24.415208,-83 7.96468,-21.21664 17.411415,-36.82083 25.634775,-42.3437 3.46578,-2.32765 7.75343,-3.40938 27.99561,-7.063 24.83316,-4.48226 37.7984,-7.72387 44.43556,-11.10989 2.13829,-1.09087 4.2852,-1.98341 4.77091,-1.98341 0.48571,0 0.25824,3.0375 -0.50549,6.75 -1.50052,7.29402 -2.99983,49.3173 -1.91392,53.64393 0.99077,3.94752 2.8969,3.16745 7.07154,-2.89393 3.53084,-5.12662 5.54444,-6.78317 5.54444,-4.56129 0,2.60045 5.3114,31.27728 8.05039,43.46495 5.98108,26.61396 16.76339,62.48393 20.54452,68.34634 l 1.4512,2.25 H 141.57203 54.570422 Z m 210.460079,-0.0508 c 2.17179,-3.31457 8.92419,-24.36077 12.96435,-40.40789 4.43614,-17.61992 8.08383,-37.40934 10.50604,-56.99725 1.05232,-8.50988 2.1619,-15.72111 2.46573,-16.02495 0.64309,-0.64309 2.6928,1.66469 9.7848,11.01675 3.42759,4.51989 5.47957,6.45222 6.14506,5.78673 1.18368,-1.18368 -0.68453,-30.51729 -2.75684,-43.28638 -1.74071,-10.72592 -4.37632,-21.1576 -6.74023,-26.67774 -1.03434,-2.41534 -1.68984,-4.5823 -1.45667,-4.81547 0.23317,-0.23317 3.05697,0.90265 6.27513,2.52404 9.1322,4.60104 20.99201,7.95377 45.19529,12.77659 12.28926,2.44879 23.57308,5.08787 25.07515,5.86462 9.57196,4.94985 22.94665,28.40208 32.96941,57.8111 2.76841,8.12314 10.28609,32.19814 16.70596,53.5 6.41986,21.30186 11.88553,39.29316 12.14592,39.98066 0.37646,0.99395 -17.06674,1.25 -85.1566,1.25 H 264.48143 Z M 292.3029,319.27575 c -3.48342,-3.65128 -4.45897,-6.45791 -5.83264,-16.7804 l -1.14521,-8.60577 5.12567,-8.35825 c 7.3769,-12.02924 13.35778,-24.49549 17.52649,-36.53131 3.20476,-9.25271 4.17092,-10.95875 8.13338,-14.36186 5.35782,-4.60148 8.85325,-11.11418 11.48239,-21.39399 2.20459,-8.6199 2.40904,-13.47419 0.83135,-19.73974 -2.07703,-8.24867 -6.91023,-9.75732 -10.39679,-3.24531 -1.1,2.05452 -2.31639,3.73671 -2.70308,3.7382 -0.3867,0.001 -1.47529,-1.6246 -2.41909,-3.61352 -3.45146,-7.2734 -12.43759,-11.95743 -37.37783,-19.4832 -36.97908,-11.15851 -50.57658,-17.84965 -64.69138,-31.83371 -7.11369,-7.0478 -9.1226,-7.45885 -17.07813,-3.49444 -6.3577,3.16818 -14.21568,11.58946 -17.71356,18.98336 -3.59507,7.59935 -6.48828,19.31308 -7.21077,29.19421 -0.33177,4.5375 -0.80892,8.25 -1.06034,8.25 -0.25141,0 -1.79409,-1.125 -3.42819,-2.5 -3.73675,-3.14427 -4.36211,-3.12484 -6.54282,0.20333 -2.23258,3.40736 -2.43946,17.43846 -0.3656,24.79667 2.41169,8.55685 6.77334,16.1351 11.61665,20.18361 3.60598,3.01423 4.89833,4.96775 6.16195,9.31445 2.92343,10.05624 10.27022,26.25548 16.96068,37.3973 l 6.60969,11.0073 -0.6645,10.04867 c -0.74861,11.32069 -1.9804,16.16987 -4.42377,17.41502 -1.56622,0.79815 -24.35316,-0.0941 -35.85864,-1.40416 -6.56738,-0.74777 -11.84347,-4.46271 -17.76801,-12.51063 -12.10229,-16.43979 -15.71037,-32.44915 -13.58553,-60.28013 4.7534,-62.25964 27.2222,-120.24856 52.91047,-136.55478 2.54749,-1.61707 7.03281,-3.64203 9.96737,-4.49991 3.87995,-1.13423 6.9751,-3.07768 11.34521,-7.123635 12.46712,-11.54236 25.74733,-15.92105 46.31922,-15.27215 11.32895,0.35735 14.13371,0.80718 21.81973,3.49945 16.5524,5.798 31.67451,16.565115 46.03801,32.779585 14.3084,16.15227 22.61268,30.83521 30.69285,54.26859 16.39981,47.56123 14.10848,112.15599 -4.86138,137.04726 -4.08556,5.36086 -8.18764,6.77337 -26.3982,9.08991 -9.18994,1.16905 -17.30716,2.35507 -18.03825,2.63562 -0.7311,0.28055 -2.52093,-0.73899 -3.9774,-2.26565 z"
style="fill:#4e4e4d" />
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
width="1600"
height="1600"
viewBox="0 0 1600 1600"
sodipodi:docname="comments.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1598"
inkscape:window-height="858"
id="namedview4"
showgrid="false"
inkscape:zoom="0.417193"
inkscape:cx="564.95647"
inkscape:cy="689.55475"
inkscape:window-x="0"
inkscape:window-y="20"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:#ffffff;fill-opacity:1"
d="M 1450,1300 H 970.49559 L 800,1470 629.50441,1300 H 150 V 300 H 1450 Z M 1350,400 H 250 v 800 H 670.50581 L 800,1329 929.49419,1200 H 1350 Z M 450,950 h 500 v 100 H 450 Z m 0,-200 h 700 V 850 H 450 Z M 1036,650 H 450 V 550 h 586 z"
id="path4520"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccccccccccccccccccc" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
width="128"
height="128"
viewBox="0 0 128 128"
sodipodi:docname="erase.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1598"
inkscape:window-height="858"
id="namedview4"
showgrid="false"
inkscape:zoom="1.0091185"
inkscape:cx="-283.45157"
inkscape:cy="33.728592"
inkscape:window-x="0"
inkscape:window-y="20"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:9.22393036;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 78.057715,6.7629418 74.781278,10.009583 7.1140977,77.061429 41.377799,111.63957 l 24.704188,0.002 58.479833,-57.94805 z M 50.017286,47.533394 83.536922,81.36064 62.286619,102.4177 45.22373,102.41662 20.158146,77.121007 Z"
id="rect1639"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:6.53187132;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.12387033,120.4439 H 66.02296"
id="path1656"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

Some files were not shown because too many files have changed in this diff Show More