mirror of
https://github.com/bpatrik/pigallery2.git
synced 2024-11-24 08:42:24 +02:00
upgrading bootstrap, fixing navigation issue
Router active line broke navigation, replacing it with custom function
This commit is contained in:
parent
669ad818c3
commit
7371fda5a8
17
.browserslistrc
Normal file
17
.browserslistrc
Normal file
@ -0,0 +1,17 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# For the full list of supported browsers by the Angular framework, please see:
|
||||
# https://angular.io/guide/browser-support
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major versions
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
@ -8,6 +8,9 @@ indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.ts]
|
||||
quote_type = single
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
|
21
angular.json
21
angular.json
@ -7,6 +7,8 @@
|
||||
"root": "",
|
||||
"sourceRoot": "src/frontend",
|
||||
"projectType": "application",
|
||||
"schematics": {},
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
@ -21,10 +23,10 @@
|
||||
"src/frontend/assets"
|
||||
],
|
||||
"styles": [
|
||||
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
|
||||
"./node_modules/ngx-bootstrap/datepicker/bs-datepicker.css",
|
||||
"./node_modules/open-iconic/font/css/open-iconic-bootstrap.css",
|
||||
"./node_modules/ngx-toastr/toastr.css",
|
||||
"bootstrap/dist/css/bootstrap.min.css",
|
||||
"ngx-bootstrap/datepicker/bs-datepicker.css",
|
||||
"open-iconic/font/css/open-iconic-bootstrap.css",
|
||||
"ngx-toastr/toastr.css",
|
||||
"src/frontend/styles.css"
|
||||
],
|
||||
"scripts": []
|
||||
@ -34,7 +36,6 @@
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
@ -75,11 +76,11 @@
|
||||
"tsConfig": "src/frontend/tsconfig.spec.json",
|
||||
"scripts": [],
|
||||
"styles": [
|
||||
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
|
||||
"node_modules/ngx-toastr/toastr.css",
|
||||
"node_modules/bootstrap/dist/css/bootstrap.css",
|
||||
"node_modules/open-iconic/font/css/open-iconic-bootstrap.css",
|
||||
"node_modules/ngx-bootstrap/datepicker/bs-datepicker.css",
|
||||
"bootstrap/dist/css/bootstrap.min.css",
|
||||
"ngx-toastr/toastr.css",
|
||||
"bootstrap/dist/css/bootstrap.css",
|
||||
"open-iconic/font/css/open-iconic-bootstrap.css",
|
||||
"ngx-bootstrap/datepicker/bs-datepicker.css",
|
||||
"src/frontend/styles.css"
|
||||
],
|
||||
"assets": [
|
||||
|
@ -263,7 +263,7 @@ gulp.task('extract-locale', async (cb) => {
|
||||
console.log('creating source translation file: locale.source.xlf');
|
||||
try {
|
||||
{
|
||||
const {stdout, stderr} = await execPr('ng xi18n --out-file=./../../locale.source.xlf --i18n-format=xlf --i18n-locale=en',
|
||||
const {stdout, stderr} = await execPr('ng extract-i18n --out-file=./../../locale.source.xlf --i18n-format=xlf --i18n-locale=en',
|
||||
{maxBuffer: 1024 * 1024});
|
||||
console.log(stdout);
|
||||
console.error(stderr);
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -14530,9 +14530,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"ngx-bootstrap": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-5.2.0.tgz",
|
||||
"integrity": "sha512-fh+OmaEdxCZnVLQFLqexdw4Xv0Lp2Ueq7un52gF26lTENhTAypGWgf2c92HXzbp4W/B0tnwIZ9mzQPwdDMH91w==",
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-6.2.0.tgz",
|
||||
"integrity": "sha512-5WKHo6/ltkenw4UyXZwED8rODCgp2RGbWurzYzZsF/gH1JO5SN7TJ+AL6kXYk6XM42sDA2WhN9Db+ZPNjiyHnA==",
|
||||
"dev": true
|
||||
},
|
||||
"ngx-clipboard": {
|
||||
|
@ -9,6 +9,7 @@
|
||||
"bin": "./src/backend/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc && gulp build-prod",
|
||||
"build-en": "tsc && gulp build-prod --languages=en",
|
||||
"create-release": "gulp create-release",
|
||||
"build-backend": "tsc",
|
||||
"pretest": "tsc",
|
||||
@ -120,7 +121,7 @@
|
||||
"mocha": "8.3.2",
|
||||
"natural-orderby": "2.0.3",
|
||||
"ng2-cookies": "1.0.12",
|
||||
"ngx-bootstrap": "5.2.0",
|
||||
"ngx-bootstrap": "6.2.0",
|
||||
"ngx-clipboard": "14.0.1",
|
||||
"ngx-toastr": "13.2.1",
|
||||
"nyc": "15.1.0",
|
||||
|
@ -17,17 +17,17 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
|
||||
private subscription: Subscription = null;
|
||||
|
||||
constructor(private _router: Router,
|
||||
private _authenticationService: AuthenticationService,
|
||||
private _shareService: ShareService,
|
||||
private _title: Title) {
|
||||
constructor(private router: Router,
|
||||
private authenticationService: AuthenticationService,
|
||||
private shareService: ShareService,
|
||||
private title: Title) {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this._title.setTitle(Config.Client.applicationTitle);
|
||||
await this._shareService.wait();
|
||||
this.subscription = this._authenticationService.user.subscribe(() => {
|
||||
if (this._authenticationService.isAuthenticated()) {
|
||||
async ngOnInit(): Promise<void> {
|
||||
this.title.setTitle(Config.Client.applicationTitle);
|
||||
await this.shareService.wait();
|
||||
this.subscription = this.authenticationService.user.subscribe(() => {
|
||||
if (this.authenticationService.isAuthenticated()) {
|
||||
if (this.isLoginPage()) {
|
||||
return this.toGallery();
|
||||
}
|
||||
@ -41,31 +41,35 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
ngOnDestroy(): void {
|
||||
if (this.subscription != null) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
private isLoginPage() {
|
||||
return this._router.isActive('login', true) || this._router.isActive('shareLogin', false);
|
||||
private isLoginPage(): boolean {
|
||||
return this.router.isActive('login', true) || this.router.isActive('shareLogin', false);
|
||||
}
|
||||
|
||||
private toLogin() {
|
||||
if (this._shareService.isSharing()) {
|
||||
private async toLogin(): Promise<void> {
|
||||
if (this.shareService.isSharing()) {
|
||||
const q: any = {};
|
||||
q[QueryParams.gallery.sharingKey_query] = this._shareService.getSharingKey();
|
||||
return this._router.navigate(['shareLogin'], {queryParams: q});
|
||||
q[QueryParams.gallery.sharingKey_query] = this.shareService.getSharingKey();
|
||||
await this.router.navigate(['shareLogin'], {queryParams: q});
|
||||
return;
|
||||
} else {
|
||||
return this._router.navigate(['login']);
|
||||
await this.router.navigate(['login']);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private toGallery() {
|
||||
if (this._shareService.isSharing()) {
|
||||
return this._router.navigate(['share', this._shareService.getSharingKey()]);
|
||||
private async toGallery(): Promise<void> {
|
||||
if (this.shareService.isSharing()) {
|
||||
await this.router.navigate(['share', this.shareService.getSharingKey()]);
|
||||
return;
|
||||
} else {
|
||||
return this._router.navigate(['gallery', '']);
|
||||
await this.router.navigate(['gallery', '']);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import {Injectable, LOCALE_ID, NgModule, TRANSLATIONS, TRANSLATIONS_FORMAT} from
|
||||
import {BrowserModule, HAMMER_GESTURE_CONFIG, HammerGestureConfig} from '@angular/platform-browser';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {AppComponent} from './app.component';
|
||||
import {appRoutes} from './app.routing';
|
||||
import {UserService} from './model/network/user.service';
|
||||
import {GalleryService} from './ui/gallery/gallery.service';
|
||||
import {NetworkService} from './model/network/network.service';
|
||||
@ -12,7 +11,7 @@ import {AuthenticationService} from './model/network/authentication.service';
|
||||
import {UserMangerSettingsComponent} from './ui/settings/usermanager/usermanager.settings.component';
|
||||
import {FrameComponent} from './ui/frame/frame.component';
|
||||
import {YagaModule} from '@yaga/leaflet-ng2';
|
||||
import { LoadingBarModule } from '@ngx-loading-bar/core';
|
||||
import {LoadingBarModule} from '@ngx-loading-bar/core';
|
||||
import {GalleryLightboxMediaComponent} from './ui/gallery/lightbox/media/media.lightbox.gallery.component';
|
||||
import {GalleryPhotoLoadingComponent} from './ui/gallery/grid/photo/loading/loading.photo.grid.gallery.component';
|
||||
import {GalleryNavigatorComponent} from './ui/gallery/navigator/navigator.gallery.component';
|
||||
@ -98,6 +97,7 @@ import {StringifySearchQuery} from './pipes/StringifySearchQuery';
|
||||
import {AutoCompleteService} from './ui/gallery/search/autocomplete.service';
|
||||
import {SearchQueryParserService} from './ui/gallery/search/search-query-parser.service';
|
||||
import {GallerySearchFieldComponent} from './ui/gallery/search/search-field/search-field.gallery.component';
|
||||
import {AppRoutingModule} from './app.routing';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@ -112,31 +112,31 @@ export class MyHammerConfig extends HammerGestureConfig {
|
||||
|
||||
|
||||
export class CustomUrlSerializer implements UrlSerializer {
|
||||
private _defaultUrlSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();
|
||||
private defaultUrlSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();
|
||||
|
||||
parse(url: string): UrlTree {
|
||||
// Encode parentheses
|
||||
url = url.replace(/\(/g, '%28').replace(/\)/g, '%29');
|
||||
// Use the default serializer.
|
||||
return this._defaultUrlSerializer.parse(url);
|
||||
return this.defaultUrlSerializer.parse(url);
|
||||
}
|
||||
|
||||
serialize(tree: UrlTree): string {
|
||||
return this._defaultUrlSerializer.serialize(tree).replace(/%28/g, '(').replace(/%29/g, ')');
|
||||
return this.defaultUrlSerializer.serialize(tree).replace(/%28/g, '(').replace(/%29/g, ')');
|
||||
}
|
||||
}
|
||||
|
||||
// use the require method provided by webpack
|
||||
declare const require: (path: string) => string;
|
||||
|
||||
export function translationsFactory(locale: string) {
|
||||
export function translationsFactory(locale: string): string {
|
||||
locale = locale || 'en'; // default to english if no locale
|
||||
|
||||
// default locale, nothing to translate
|
||||
if (locale === 'en') {
|
||||
return '';
|
||||
}
|
||||
return (<any>require(`raw-loader!../translate/messages.${locale}.xlf`)).default;
|
||||
return (require(`raw-loader!../translate/messages.${locale}.xlf`) as any).default;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
@ -145,7 +145,7 @@ export function translationsFactory(locale: string) {
|
||||
FormsModule,
|
||||
HttpClientModule,
|
||||
BrowserAnimationsModule,
|
||||
appRoutes,
|
||||
AppRoutingModule,
|
||||
ClipboardModule,
|
||||
JwBootstrapSwitchNg2Module,
|
||||
TooltipModule.forRoot(),
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {ModuleWithProviders} from '@angular/core';
|
||||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule, Routes, UrlMatchResult, UrlSegment} from '@angular/router';
|
||||
import {LoginComponent} from './ui/login/login.component';
|
||||
import {GalleryComponent} from './ui/gallery/gallery.component';
|
||||
@ -40,7 +40,7 @@ export function galleryMatcherFunction(
|
||||
return null;
|
||||
}
|
||||
|
||||
const ROUTES: Routes = [
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'login',
|
||||
component: LoginComponent
|
||||
@ -73,7 +73,10 @@ const ROUTES: Routes = [
|
||||
{path: '**', redirectTo: '/login', pathMatch: 'full'}
|
||||
];
|
||||
|
||||
export const appRoutes: ModuleWithProviders<RouterModule> = RouterModule.forRoot(ROUTES, {
|
||||
anchorScrolling: 'enabled'
|
||||
});
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import {ErrorCodes, ErrorDTO} from '../../../../common/entities/Error';
|
||||
import {CookieNames} from '../../../../common/CookieNames';
|
||||
import {ShareService} from '../../ui/gallery/share.service';
|
||||
|
||||
/* Injected config / user from server side */
|
||||
// tslint:disable-next-line:no-internal-module no-namespace
|
||||
declare module ServerInject {
|
||||
export let user: UserDTO;
|
||||
}
|
||||
@ -19,8 +21,8 @@ export class AuthenticationService {
|
||||
|
||||
public readonly user: BehaviorSubject<UserDTO>;
|
||||
|
||||
constructor(private _userService: UserService,
|
||||
private _networkService: NetworkService,
|
||||
constructor(private userService: UserService,
|
||||
private networkService: NetworkService,
|
||||
private shareService: ShareService) {
|
||||
this.user = new BehaviorSubject(null);
|
||||
|
||||
@ -29,20 +31,23 @@ export class AuthenticationService {
|
||||
if (typeof ServerInject !== 'undefined' && typeof ServerInject.user !== 'undefined') {
|
||||
this.user.next(ServerInject.user);
|
||||
}
|
||||
this.getSessionUser();
|
||||
this.getSessionUser().catch(console.error);
|
||||
} else {
|
||||
if (Config.Client.authenticationRequired === false) {
|
||||
this.user.next(<UserDTO>{name: UserRoles[Config.Client.unAuthenticatedUserRole], role: Config.Client.unAuthenticatedUserRole});
|
||||
this.user.next({
|
||||
name: UserRoles[Config.Client.unAuthenticatedUserRole],
|
||||
role: Config.Client.unAuthenticatedUserRole
|
||||
} as UserDTO);
|
||||
}
|
||||
}
|
||||
|
||||
_networkService.addGlobalErrorHandler((error: ErrorDTO) => {
|
||||
networkService.addGlobalErrorHandler((error: ErrorDTO) => {
|
||||
if (error.code === ErrorCodes.NOT_AUTHENTICATED) {
|
||||
this.user.next(null);
|
||||
return true;
|
||||
}
|
||||
if (error.code === ErrorCodes.NOT_AUTHORISED) {
|
||||
this.logout();
|
||||
this.logout().catch(console.error);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -51,19 +56,19 @@ export class AuthenticationService {
|
||||
// TODO: refactor architecture remove shareService dependency
|
||||
window.setTimeout(() => {
|
||||
this.user.subscribe((u) => {
|
||||
this.shareService.onNewUser(u);
|
||||
this.shareService.onNewUser(u).catch(console.error);
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public async login(credential: LoginCredential): Promise<UserDTO> {
|
||||
const user = await this._userService.login(credential);
|
||||
const user = await this.userService.login(credential);
|
||||
this.user.next(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
public async shareLogin(password: string): Promise<UserDTO> {
|
||||
const user = await this._userService.shareLogin(password);
|
||||
const user = await this.userService.shareLogin(password);
|
||||
this.user.next(user);
|
||||
return user;
|
||||
}
|
||||
@ -75,18 +80,18 @@ export class AuthenticationService {
|
||||
return !!this.user.value;
|
||||
}
|
||||
|
||||
public isAuthorized(role: UserRoles) {
|
||||
public isAuthorized(role: UserRoles): boolean {
|
||||
return this.user.value && this.user.value.role >= role;
|
||||
}
|
||||
|
||||
public async logout() {
|
||||
await this._userService.logout();
|
||||
public async logout(): Promise<void> {
|
||||
await this.userService.logout();
|
||||
this.user.next(null);
|
||||
}
|
||||
|
||||
private async getSessionUser(): Promise<void> {
|
||||
try {
|
||||
this.user.next(await this._userService.getSessionUser());
|
||||
this.user.next(await this.userService.getSessionUser());
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ export class AuthGuard implements CanActivate {
|
||||
private navigationService: NavigationService) {
|
||||
}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||
if (this.authenticationService.isAuthenticated() === true) {
|
||||
return true;
|
||||
}
|
||||
|
@ -11,15 +11,15 @@ import {VersionService} from '../version.service';
|
||||
@Injectable()
|
||||
export class NetworkService {
|
||||
|
||||
readonly _apiBaseUrl = Utils.concatUrls(Config.Client.urlBase, '/api');
|
||||
readonly apiBaseUrl = Utils.concatUrls(Config.Client.urlBase, '/api');
|
||||
private globalErrorHandlers: Array<(error: ErrorDTO) => boolean> = [];
|
||||
|
||||
constructor(private _http: HttpClient,
|
||||
constructor(private http: HttpClient,
|
||||
private loadingBarService: LoadingBarService,
|
||||
private versionService: VersionService) {
|
||||
}
|
||||
|
||||
public static buildUrl(url: string, data?: { [key: string]: any }) {
|
||||
public static buildUrl(url: string, data?: { [key: string]: any }): string {
|
||||
if (data) {
|
||||
const keys = Object.getOwnPropertyNames(data);
|
||||
if (keys.length > 0) {
|
||||
@ -51,7 +51,7 @@ export class NetworkService {
|
||||
return this.handleError(error);
|
||||
};
|
||||
|
||||
return this._http.get(this._apiBaseUrl + url, {responseType: 'text'})
|
||||
return this.http.get(this.apiBaseUrl + url, {responseType: 'text'})
|
||||
.toPromise()
|
||||
.then(process)
|
||||
.catch(err);
|
||||
@ -73,7 +73,7 @@ export class NetworkService {
|
||||
return this.callJson('delete', url);
|
||||
}
|
||||
|
||||
addGlobalErrorHandler(fn: (error: ErrorDTO) => boolean) {
|
||||
addGlobalErrorHandler(fn: (error: ErrorDTO) => boolean): void {
|
||||
this.globalErrorHandlers.push(fn);
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ export class NetworkService {
|
||||
}
|
||||
if (!!msg.error) {
|
||||
if (msg.error.code) {
|
||||
(<any>msg.error)['title'] = ErrorCodes[msg.error.code];
|
||||
(msg.error as any).title = ErrorCodes[msg.error.code];
|
||||
}
|
||||
throw msg.error;
|
||||
}
|
||||
@ -104,22 +104,22 @@ export class NetworkService {
|
||||
|
||||
switch (method) {
|
||||
case 'get':
|
||||
return this._http.get<Message<T>>(this._apiBaseUrl + url, {observe: 'response'})
|
||||
return this.http.get<Message<T>>(this.apiBaseUrl + url, {observe: 'response'})
|
||||
.toPromise()
|
||||
.then(process)
|
||||
.catch(err);
|
||||
case 'delete':
|
||||
return this._http.delete<Message<T>>(this._apiBaseUrl + url, {observe: 'response'})
|
||||
return this.http.delete<Message<T>>(this.apiBaseUrl + url, {observe: 'response'})
|
||||
.toPromise()
|
||||
.then(process)
|
||||
.catch(err);
|
||||
case 'post':
|
||||
return this._http.post<Message<T>>(this._apiBaseUrl + url, body, {observe: 'response'})
|
||||
return this.http.post<Message<T>>(this.apiBaseUrl + url, body, {observe: 'response'})
|
||||
.toPromise()
|
||||
.then(process)
|
||||
.catch(err);
|
||||
case 'put':
|
||||
return this._http.put<Message<T>>(this._apiBaseUrl + url, body, {observe: 'response'})
|
||||
return this.http.put<Message<T>>(this.apiBaseUrl + url, body, {observe: 'response'})
|
||||
.toPromise()
|
||||
.then(process)
|
||||
.catch(err);
|
||||
@ -129,10 +129,10 @@ export class NetworkService {
|
||||
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
private handleError(error: any): Promise<any> {
|
||||
if (typeof error.code !== 'undefined') {
|
||||
for (let i = 0; i < this.globalErrorHandlers.length; i++) {
|
||||
if (this.globalErrorHandlers[i](error) === true) {
|
||||
for (const item of this.globalErrorHandlers) {
|
||||
if (item(error) === true) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {ShareService} from '../ui/gallery/share.service';
|
||||
import {MediaBaseDTO, MediaDTO} from '../../../common/entities/MediaDTO';
|
||||
import {MediaBaseDTO} from '../../../common/entities/MediaDTO';
|
||||
import {QueryParams} from '../../../common/QueryParams';
|
||||
import {Utils} from '../../../common/Utils';
|
||||
import {GalleryService} from '../ui/gallery/gallery.service';
|
||||
@ -36,7 +36,7 @@ export class QueryService {
|
||||
return query;
|
||||
}
|
||||
|
||||
getParamsForDirs(directory: DirectoryDTO) {
|
||||
getParamsForDirs(directory: DirectoryDTO): { [key: string]: any } {
|
||||
const params: { [key: string]: any } = {};
|
||||
if (Config.Client.Sharing.enabled === true) {
|
||||
if (this.shareService.isSharing()) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {Component, Input, OnDestroy, OnInit} from '@angular/core';
|
||||
import {RouterLink} from '@angular/router';
|
||||
import {PersonDTO} from '../../../../../common/entities/PersonDTO';
|
||||
import {DomSanitizer} from '@angular/platform-browser';
|
||||
import {DomSanitizer, SafeStyle} from '@angular/platform-browser';
|
||||
import {PersonThumbnail, ThumbnailManagerService} from '../../gallery/thumbnailManager.service';
|
||||
import {FacesService} from '../faces.service';
|
||||
import {AuthenticationService} from '../../../model/network/authentication.service';
|
||||
@ -22,7 +22,7 @@ export class FaceComponent implements OnInit, OnDestroy {
|
||||
public searchQueryDTOstr: string;
|
||||
|
||||
constructor(private thumbnailService: ThumbnailManagerService,
|
||||
private _sanitizer: DomSanitizer,
|
||||
private sanitizer: DomSanitizer,
|
||||
private faceService: FacesService,
|
||||
public authenticationService: AuthenticationService) {
|
||||
|
||||
@ -32,31 +32,31 @@ export class FaceComponent implements OnInit, OnDestroy {
|
||||
return this.authenticationService.user.getValue().role >= Config.Client.Faces.writeAccessMinRole;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit(): void {
|
||||
this.thumbnail = this.thumbnailService.getPersonThumbnail(this.person);
|
||||
this.searchQueryDTOstr = JSON.stringify(<TextSearch>{
|
||||
this.searchQueryDTOstr = JSON.stringify({
|
||||
type: SearchQueryTypes.person,
|
||||
text: this.person.name,
|
||||
matchType: TextSearchQueryMatchTypes.exact_match
|
||||
});
|
||||
} as TextSearch);
|
||||
|
||||
}
|
||||
|
||||
getSanitizedThUrl() {
|
||||
return this._sanitizer.bypassSecurityTrustStyle('url(' +
|
||||
getSanitizedThUrl(): SafeStyle {
|
||||
return this.sanitizer.bypassSecurityTrustStyle('url(' +
|
||||
encodeURI(this.thumbnail.Src)
|
||||
.replace(/\(/g, '%28')
|
||||
.replace(/'/g, '%27')
|
||||
.replace(/\)/g, '%29') + ')');
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
ngOnDestroy(): void {
|
||||
if (this.thumbnail != null) {
|
||||
this.thumbnail.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
async toggleFavourite($event: MouseEvent) {
|
||||
async toggleFavourite($event: MouseEvent): Promise<void> {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
await this.faceService.setFavourite(this.person, !this.person.isFavourite).catch(console.error);
|
||||
|
@ -34,11 +34,11 @@ export class FacesComponent implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit(): void {
|
||||
this.updateSize();
|
||||
}
|
||||
|
||||
private updateSize() {
|
||||
private updateSize(): void {
|
||||
const size = 220 + 5;
|
||||
// body - container margin
|
||||
const containerWidth = this.container.nativeElement.clientWidth - 30;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<ngx-loading-bar [includeSpinner]="false" color="#337ab7" height="3px"></ngx-loading-bar>
|
||||
<nav class="navbar navbar-dark bg-dark navbar-expand-md">
|
||||
<a class="navbar-brand" [routerLink]="['/gallery','/']"
|
||||
<a class="navbar-brand" [routerLink]="['/gallery']"
|
||||
[queryParams]="queryService.getParams()">
|
||||
<img src="assets/icon_inv.png" width="30" height="30" class="d-inline-block align-top" alt="">
|
||||
<strong>{{title}}</strong>
|
||||
@ -12,13 +12,13 @@
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarNav" [collapse]="collapsed">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item" [routerLinkActive]="['active']">
|
||||
<li class="nav-item" >
|
||||
<a class="nav-link"
|
||||
[routerLink]="['/gallery']"
|
||||
[queryParams]="queryService.getParams()" i18n>Gallery</a>
|
||||
[queryParams]="queryService.getParams()" [class.active]="isLinkActive('/gallery')" i18n>Gallery</a>
|
||||
</li>
|
||||
<li class="nav-item" [routerLinkActive]="['active']" *ngIf="isFacesAvailable()">
|
||||
<a class="nav-link" [routerLink]="['/faces']" i18n>Faces</a>
|
||||
<li class="nav-item" *ngIf="isFacesAvailable()">
|
||||
<a class="nav-link" [routerLink]="['/faces']" [class.active]="isLinkActive('/faces')" i18n>Faces</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav navbar-right ml-auto">
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
import {RouterLink} from '@angular/router';
|
||||
import {Router, RouterLink} from '@angular/router';
|
||||
import {AuthenticationService} from '../../model/network/authentication.service';
|
||||
import {UserDTO, UserRoles} from '../../../../common/entities/UserDTO';
|
||||
import {Config} from '../../../../common/config/public/Config';
|
||||
@ -16,29 +16,34 @@ import {QueryService} from '../../model/query.service';
|
||||
})
|
||||
export class FrameComponent {
|
||||
|
||||
user: BehaviorSubject<UserDTO>;
|
||||
public readonly user: BehaviorSubject<UserDTO>;
|
||||
public readonly authenticationRequired = Config.Client.authenticationRequired;
|
||||
public readonly title = Config.Client.applicationTitle;
|
||||
collapsed = true;
|
||||
public collapsed = true;
|
||||
|
||||
constructor(private _authService: AuthenticationService,
|
||||
constructor(private authService: AuthenticationService,
|
||||
public notificationService: NotificationService,
|
||||
public queryService: QueryService) {
|
||||
this.user = this._authService.user;
|
||||
public queryService: QueryService,
|
||||
private router: Router) {
|
||||
this.user = this.authService.user;
|
||||
}
|
||||
|
||||
|
||||
isAdmin() {
|
||||
isAdmin(): boolean {
|
||||
return this.user.value && this.user.value.role >= UserRoles.Admin;
|
||||
}
|
||||
|
||||
isFacesAvailable() {
|
||||
isFacesAvailable(): boolean {
|
||||
return Config.Client.Faces.enabled && this.user.value && this.user.value.role >= Config.Client.Faces.readAccessMinRole;
|
||||
}
|
||||
|
||||
|
||||
logout() {
|
||||
this._authService.logout();
|
||||
isLinkActive(url: string): boolean {
|
||||
return this.router.url.startsWith(url);
|
||||
}
|
||||
|
||||
logout(): void {
|
||||
this.authService.logout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -76,27 +76,27 @@ export class ShareService {
|
||||
return this.ReadyPR;
|
||||
}
|
||||
|
||||
public createSharing(dir: string, includeSubfolders: boolean, valid: number): Promise<SharingDTO> {
|
||||
public createSharing(dir: string, includeSubFolders: boolean, valid: number): Promise<SharingDTO> {
|
||||
return this.networkService.postJson('/share/' + dir, {
|
||||
createSharing: <CreateSharingDTO>{
|
||||
includeSubfolders: includeSubfolders,
|
||||
valid: valid
|
||||
}
|
||||
createSharing: {
|
||||
includeSubfolders: includeSubFolders,
|
||||
valid
|
||||
} as CreateSharingDTO
|
||||
});
|
||||
}
|
||||
|
||||
public updateSharing(dir: string, sharingId: number, includeSubfolders: boolean, password: string, valid: number): Promise<SharingDTO> {
|
||||
public updateSharing(dir: string, sharingId: number, includeSubFolders: boolean, password: string, valid: number): Promise<SharingDTO> {
|
||||
return this.networkService.putJson('/share/' + dir, {
|
||||
updateSharing: <CreateSharingDTO>{
|
||||
updateSharing: {
|
||||
id: sharingId,
|
||||
includeSubfolders: includeSubfolders,
|
||||
valid: valid,
|
||||
password: password
|
||||
}
|
||||
includeSubfolders: includeSubFolders,
|
||||
valid,
|
||||
password
|
||||
} as CreateSharingDTO
|
||||
});
|
||||
}
|
||||
|
||||
public getSharingKey() {
|
||||
public getSharingKey(): string {
|
||||
return this.sharingKey;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {Component, Input, OnChanges, OnDestroy, TemplateRef} from '@angular/core';
|
||||
import {JobProgressDTO, JobProgressStates} from '../../../../../../common/entities/job/JobProgressDTO';
|
||||
import {Subscription, timer} from 'rxjs';
|
||||
import {BsModalRef, BsModalService} from 'ngx-bootstrap';
|
||||
import {BsModalRef, BsModalService} from 'ngx-bootstrap/modal';
|
||||
import {I18n} from '@ngx-translate/i18n-polyfill';
|
||||
import {BackendtextService} from '../../../../model/backendtext.service';
|
||||
|
||||
|
@ -1,8 +1,16 @@
|
||||
// The file contents for the current environment will overwrite these during build.
|
||||
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
|
||||
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
|
||||
// The list of which env maps to which file can be found in `.angular-cli.json`.
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment = {
|
||||
production: false
|
||||
};
|
||||
|
||||
/*
|
||||
* For easier debugging in development mode, you can import the following file
|
||||
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||||
*
|
||||
* This import should be commented out in production mode because it will have a negative impact
|
||||
* on performance if an error is thrown.
|
||||
*/
|
||||
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
||||
|
@ -1,16 +1,21 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/app",
|
||||
"module": "es2015",
|
||||
"baseUrl": "tsconfig.app",
|
||||
"types": []
|
||||
"types": [],
|
||||
"target": "es2015",
|
||||
"module": "es2020",
|
||||
"lib": [
|
||||
"es2018",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"test.ts",
|
||||
"**/*.spec.ts"
|
||||
"files": [
|
||||
"./main.ts",
|
||||
"./polyfills.ts"
|
||||
],
|
||||
"include": [
|
||||
"./**/*"
|
||||
"./**/*.d.ts"
|
||||
]
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/spec",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"baseUrl": "tsconfig.spec",
|
||||
"target": "es2015",
|
||||
"module": "es2020",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"node"
|
||||
"jasmine"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
|
@ -2,19 +2,20 @@
|
||||
"compileOnSave": true,
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"module": "commonjs",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"moduleResolution": "node",
|
||||
"downlevelIteration": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "es6",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
],
|
||||
"target": "es2015",
|
||||
"module": "commonjs",
|
||||
"lib": [
|
||||
"es2017",
|
||||
"es2018",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false
|
||||
}
|
||||
}
|
||||
|
163
tslint.json
163
tslint.json
@ -1,37 +1,37 @@
|
||||
{
|
||||
"extends": "tslint:recommended",
|
||||
"rulesDirectory": [
|
||||
"node_modules/codelyzer"
|
||||
"codelyzer"
|
||||
],
|
||||
"rules": {
|
||||
"align": {
|
||||
"options": [
|
||||
"parameters",
|
||||
"statements"
|
||||
]
|
||||
},
|
||||
"array-type": false,
|
||||
"arrow-return-shorthand": true,
|
||||
"callable-types": true,
|
||||
"class-name": true,
|
||||
"comment-format": [
|
||||
true,
|
||||
"check-space"
|
||||
],
|
||||
"curly": true,
|
||||
"deprecation": {
|
||||
"severity": "warn"
|
||||
"severity": "warning"
|
||||
},
|
||||
"eofline": true,
|
||||
"forin": true,
|
||||
"import-blacklist": [
|
||||
true,
|
||||
"rxjs/Rx"
|
||||
],
|
||||
"import-spacing": true,
|
||||
"indent": [
|
||||
true,
|
||||
"spaces"
|
||||
],
|
||||
"interface-over-type-literal": true,
|
||||
"label-position": true,
|
||||
"indent": {
|
||||
"options": [
|
||||
"spaces"
|
||||
]
|
||||
},
|
||||
"max-classes-per-file": false,
|
||||
"max-line-length": [
|
||||
true,
|
||||
140
|
||||
],
|
||||
"member-access": false,
|
||||
"member-ordering": [
|
||||
true,
|
||||
{
|
||||
@ -43,8 +43,6 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-arg": true,
|
||||
"no-bitwise": true,
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
@ -53,70 +51,91 @@
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-construct": true,
|
||||
"no-debugger": true,
|
||||
"no-duplicate-super": true,
|
||||
"no-empty": false,
|
||||
"no-empty-interface": true,
|
||||
"no-eval": true,
|
||||
"no-inferrable-types": [
|
||||
true,
|
||||
"ignore-params"
|
||||
],
|
||||
"no-misused-new": true,
|
||||
"no-non-null-assertion": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-string-literal": false,
|
||||
"no-string-throw": true,
|
||||
"no-redundant-jsdoc": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-unnecessary-initializer": true,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": true,
|
||||
"object-literal-sort-keys": false,
|
||||
"one-line": [
|
||||
"no-var-requires": false,
|
||||
"object-literal-key-quotes": [
|
||||
true,
|
||||
"check-open-brace",
|
||||
"check-catch",
|
||||
"check-else",
|
||||
"check-whitespace"
|
||||
"as-needed"
|
||||
],
|
||||
"prefer-const": true,
|
||||
"quotemark": [
|
||||
true,
|
||||
"single"
|
||||
],
|
||||
"radix": true,
|
||||
"semicolon": [
|
||||
true,
|
||||
"always",
|
||||
"ignore-bound-class-methods"
|
||||
],
|
||||
"triple-equals": [
|
||||
true,
|
||||
"allow-null-check"
|
||||
],
|
||||
"typedef-whitespace": [
|
||||
true,
|
||||
{
|
||||
"call-signature": "nospace",
|
||||
"index-signature": "nospace",
|
||||
"parameter": "nospace",
|
||||
"property-declaration": "nospace",
|
||||
"variable-declaration": "nospace"
|
||||
"semicolon": {
|
||||
"options": [
|
||||
"always"
|
||||
]
|
||||
},
|
||||
"space-before-function-paren": {
|
||||
"options": {
|
||||
"anonymous": "never",
|
||||
"asyncArrow": "always",
|
||||
"constructor": "never",
|
||||
"method": "never",
|
||||
"named": "never"
|
||||
}
|
||||
],
|
||||
"unified-signatures": true,
|
||||
"variable-name": false,
|
||||
"whitespace": [
|
||||
},
|
||||
"typedef": [
|
||||
true,
|
||||
"check-branch",
|
||||
"check-decl",
|
||||
"check-operator",
|
||||
"check-separator",
|
||||
"check-type"
|
||||
"call-signature"
|
||||
],
|
||||
"typedef-whitespace": {
|
||||
"options": [
|
||||
{
|
||||
"call-signature": "nospace",
|
||||
"index-signature": "nospace",
|
||||
"parameter": "nospace",
|
||||
"property-declaration": "nospace",
|
||||
"variable-declaration": "nospace"
|
||||
},
|
||||
{
|
||||
"call-signature": "onespace",
|
||||
"index-signature": "onespace",
|
||||
"parameter": "onespace",
|
||||
"property-declaration": "onespace",
|
||||
"variable-declaration": "onespace"
|
||||
}
|
||||
]
|
||||
},
|
||||
"variable-name": {
|
||||
"options": [
|
||||
"ban-keywords",
|
||||
"check-format",
|
||||
"allow-pascal-case"
|
||||
]
|
||||
},
|
||||
"whitespace": {
|
||||
"options": [
|
||||
"check-branch",
|
||||
"check-decl",
|
||||
"check-operator",
|
||||
"check-separator",
|
||||
"check-type",
|
||||
"check-typecast"
|
||||
]
|
||||
},
|
||||
"component-class-suffix": true,
|
||||
"contextual-lifecycle": true,
|
||||
"directive-class-suffix": true,
|
||||
"no-conflicting-lifecycle": true,
|
||||
"no-host-metadata-property": true,
|
||||
"no-input-rename": true,
|
||||
"no-inputs-metadata-property": true,
|
||||
"no-output-native": true,
|
||||
"no-output-on-prefix": true,
|
||||
"no-output-rename": true,
|
||||
"no-outputs-metadata-property": true,
|
||||
"template-banana-in-box": true,
|
||||
"template-no-negated-async": true,
|
||||
"use-lifecycle-interface": true,
|
||||
"use-pipe-transform-interface": true,
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
@ -128,16 +147,6 @@
|
||||
"element",
|
||||
"app",
|
||||
"kebab-case"
|
||||
],
|
||||
"no-output-on-prefix": true,
|
||||
"use-input-property-decorator": true,
|
||||
"use-output-property-decorator": true,
|
||||
"use-host-property-decorator": true,
|
||||
"no-input-rename": true,
|
||||
"no-output-rename": true,
|
||||
"use-life-cycle-interface": true,
|
||||
"use-pipe-transform-interface": true,
|
||||
"component-class-suffix": true,
|
||||
"directive-class-suffix": true
|
||||
]
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user