You've already forked pigallery2
							
							
				mirror of
				https://github.com/bpatrik/pigallery2.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	upgrading bootstrap, fixing navigation issue
Router active line broke navigation, replacing it with custom function
This commit is contained in:
		
							
								
								
									
										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 | ||||
|     ] | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user