updating packages and refactoring code

This commit is contained in:
Braun Patrik 2016-12-26 23:36:38 +01:00
parent 3cd9ef7b1a
commit eaf678bedd
72 changed files with 868 additions and 955 deletions

View File

@ -6,8 +6,8 @@ class ProjectPathClass {
public ImageFolder: string; public ImageFolder: string;
public ThumbnailFolder: string; public ThumbnailFolder: string;
isAbsolutePath(pathStr) { isAbsolutePath(pathStr: string) {
return path.resolve(pathStr) === path.normalize(pathStr).replace(RegExp(pathStr.sep + '$'), ''); return path.resolve(pathStr) === path.normalize(pathStr);
} }
constructor() { constructor() {
@ -17,4 +17,4 @@ class ProjectPathClass {
} }
} }
export var ProjectPath = new ProjectPathClass(); export let ProjectPath = new ProjectPathClass();

View File

@ -1,10 +1,8 @@
///<reference path="../../typings/index.d.ts"/> import {ConfigLoader} from "./ConfigLoader";
import {ConfigLoader} from "./../../backend/config/ConfigLoader";
import * as path from "path"; import * as path from "path";
import {ConfigClass, DatabaseType} from "../../common/config/Config"; import {ConfigClass, DatabaseType} from "../../common/config/Config";
export var Config = new ConfigClass(); export let Config = new ConfigClass();
Config.Server = { Config.Server = {
port: 80, port: 80,

View File

@ -28,6 +28,7 @@ export class ConfigLoader {
this.processHierarchyVar(configObject, argv); this.processHierarchyVar(configObject, argv);
}; };
private static processHierarchyVar(configObject: any, vars: any) { private static processHierarchyVar(configObject: any, vars: any) {
let config = {}; let config = {};
@ -36,9 +37,9 @@ export class ConfigLoader {
let value = vars[key]; let value = vars[key];
//recursive settings //recursive settings
let setObject = (object, keyArray, value) => { let setObject = (object: any, keyArray: Array<string>, value: any): void => {
let key = keyArray.shift(); let key = keyArray.shift();
object[key] = {}; object[key] = object[key] || {};
if (keyArray.length == 0) { if (keyArray.length == 0) {
//convert to boolean //convert to boolean
@ -48,6 +49,7 @@ export class ConfigLoader {
if (value.toLowerCase && value.toLowerCase() === "true") { if (value.toLowerCase && value.toLowerCase() === "true") {
value = true; value = true;
} }
object[key] = value; object[key] = value;
return; return;
} }
@ -57,6 +59,7 @@ export class ConfigLoader {
setObject(config, keyArray, value); setObject(config, keyArray, value);
}); });
this.loadObject(configObject, config); this.loadObject(configObject, config);
} }
@ -68,7 +71,7 @@ export class ConfigLoader {
} }
}; };
private static loadConfigFile(configFilePath, configObject):boolean { private static loadConfigFile(configFilePath: string, configObject: any): boolean {
if (fs.existsSync(configFilePath) === false) { if (fs.existsSync(configFilePath) === false) {
return false; return false;
} }
@ -84,7 +87,7 @@ export class ConfigLoader {
} }
private static saveConfigFile(configFilePath, configObject) { private static saveConfigFile(configFilePath: string, configObject: any) {
try { try {
fs.writeFileSync(configFilePath, JSON.stringify(configObject, null, 4)); fs.writeFileSync(configFilePath, JSON.stringify(configObject, null, 4));
} catch (err) { } catch (err) {
@ -92,7 +95,7 @@ export class ConfigLoader {
} }
} }
private static loadObject(targetObject, sourceObject) { private static loadObject(targetObject: any, sourceObject: any) {
Object.keys(sourceObject).forEach((key) => { Object.keys(sourceObject).forEach((key) => {
if (typeof targetObject[key] === "undefined") { if (typeof targetObject[key] === "undefined") {
return; return;

View File

@ -1,6 +1,4 @@
///<reference path="../customtypings/ExtendedRequest.d.ts"/> ///<reference path="../customtypings/ExtendedRequest.d.ts"/>
///<reference path="../../../typings/index.d.ts"/>
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from "express";
import {Error, ErrorCodes} from "../../../common/entities/Error"; import {Error, ErrorCodes} from "../../../common/entities/Error";
import {UserRoles, User} from "../../../common/entities/User"; import {UserRoles, User} from "../../../common/entities/User";
@ -12,6 +10,7 @@ export class AuthenticationMWs {
public static authenticate(req:Request, res:Response, next:NextFunction) { public static authenticate(req:Request, res:Response, next:NextFunction) {
if (Config.Client.authenticationRequired === false) { if (Config.Client.authenticationRequired === false) {
req.session.user = new User("", "", UserRoles.Admin); req.session.user = new User("", "", UserRoles.Admin);
return next(); return next();
} }
if (typeof req.session.user === 'undefined') { if (typeof req.session.user === 'undefined') {

View File

@ -1,6 +1,4 @@
///<reference path="exif.d.ts"/> ///<reference path="exif.d.ts"/>
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import * as mime from "mime"; import * as mime from "mime";
@ -18,7 +16,7 @@ import {
import {ProjectPath} from "../ProjectPath"; import {ProjectPath} from "../ProjectPath";
export class DiskManager { export class DiskManager {
public static scanDirectory(relativeDirectoryName, cb:(error:any, result:Directory) => void) { public static scanDirectory(relativeDirectoryName: string, cb: (error: any, result: Directory) => void) {
console.log("DiskManager: scanDirectory"); console.log("DiskManager: scanDirectory");
let directoryName = path.basename(relativeDirectoryName); let directoryName = path.basename(relativeDirectoryName);
let directoryParent = path.join(path.dirname(relativeDirectoryName), "/"); let directoryParent = path.join(path.dirname(relativeDirectoryName), "/");
@ -59,7 +57,7 @@ export class DiskManager {
}); });
} }
private static isImage(fullPath) { private static isImage(fullPath: string) {
let imageMimeTypes = [ let imageMimeTypes = [
'image/bmp', 'image/bmp',
'image/gif', 'image/gif',
@ -72,7 +70,7 @@ export class DiskManager {
'image/x-windows-bmp' 'image/x-windows-bmp'
]; ];
var extension = mime.lookup(fullPath); let extension = mime.lookup(fullPath);
if (imageMimeTypes.indexOf(extension) !== -1) { if (imageMimeTypes.indexOf(extension) !== -1) {
return true; return true;
@ -113,7 +111,7 @@ export class DiskManager {
} }
};*/ };*/
private static loadPhotoMetadata(fullPath):Promise<PhotoMetadata> { private static loadPhotoMetadata(fullPath: string): Promise<PhotoMetadata> {
return new Promise<PhotoMetadata>((resolve: (metadata: PhotoMetadata) => void, reject) => { return new Promise<PhotoMetadata>((resolve: (metadata: PhotoMetadata) => void, reject) => {
fs.readFile(fullPath, function (err, data) { fs.readFile(fullPath, function (err, data) {
if (err) { if (err) {
@ -147,19 +145,16 @@ export class DiskManager {
}; };
//Decode characters to UTF8 //Decode characters to UTF8
let decode = (s)=> { let decode = (s: any) => {
for (var a, b, i = -1, l = (s = s.split("")).length, o = String.fromCharCode, c = "charCodeAt"; ++i < l; for (let a, b, i = -1, l = (s = s.split("")).length, o = String.fromCharCode, c = "charCodeAt"; ++i < l;
((a = s[i][c](0)) & 0x80) && ((a = s[i][c](0)) & 0x80) &&
(s[i] = (a & 0xfc) == 0xc0 && ((b = s[i + 1][c](0)) & 0xc0) == 0x80 ? (s[i] = (a & 0xfc) == 0xc0 && ((b = s[i + 1][c](0)) & 0xc0) == 0x80 ?
o(((a & 0x03) << 6) + (b & 0x3f)) : o(128), s[++i] = "") o(((a & 0x03) << 6) + (b & 0x3f)) : o(128), s[++i] = "")
); );
return s.join(""); return s.join("");
}; };
let keywords:[string] = iptcData.keywords.map(s => decode(s)); let keywords: [string] = iptcData.keywords.map((s: string) => decode(s));
let creationDate: Date = iptcData.date_time; let creationDate: Date = iptcData.date_time;
console.log(keywords); console.log(keywords);

View File

@ -1,4 +1,4 @@
import {Directory} from "../../common/entities/Directory"; import {Directory} from "../../common/entities/Directory";
export interface IGalleryManager { export interface IGalleryManager {
listDirectory(relativeDirectoryName, cb:(error:any, result:Directory) => void); listDirectory(relativeDirectoryName: string, cb: (error: any, result: Directory) => void): void;
} }

View File

@ -1,7 +1,7 @@
import {AutoCompleteItem, SearchTypes} from "../../common/entities/AutoCompleteItem"; import {AutoCompleteItem, SearchTypes} from "../../common/entities/AutoCompleteItem";
import {SearchResult} from "../../common/entities/SearchResult"; import {SearchResult} from "../../common/entities/SearchResult";
export interface ISearchManager { export interface ISearchManager {
autocomplete(text:string, cb:(error:any, result:Array<AutoCompleteItem>) => void); autocomplete(text: string, cb: (error: any, result: Array<AutoCompleteItem>) => void): void;
search(text:string, searchType:SearchTypes, cb:(error:any, result:SearchResult) => void); search(text: string, searchType: SearchTypes, cb: (error: any, result: SearchResult) => void): void;
instantSearch(text:string, cb:(error:any, result:SearchResult) => void); instantSearch(text: string, cb: (error: any, result: SearchResult) => void): void;
} }

View File

@ -1,9 +1,9 @@
import {User, UserRoles} from "../../common/entities/User"; import {User, UserRoles} from "../../common/entities/User";
export interface IUserManager { export interface IUserManager {
findOne(filter, cb:(error:any, result:User) => void); findOne(filter: any, cb: (error: any, result: User) => void): void;
find(filter, cb:(error:any, result:Array<User>) => void); find(filter: any, cb: (error: any, result: Array<User>) => void): void;
createUser(user, cb:(error:any, result:User) => void); createUser(user: User, cb: (error: any, result: User) => void): void;
deleteUser(id:number, cb:(error:any, result:string) => void); deleteUser(id: number, cb: (error: any, result: string) => void): void;
changeRole(id:number, newRole:UserRoles, cb:(error:any) => void); changeRole(id: number, newRole: UserRoles, cb: (error: any) => void): void;
changePassword(request:any, cb:(error:any, result:string) => void); changePassword(request: any, cb: (error: any, result: string) => void): void;
} }

View File

@ -1,5 +1,3 @@
///<reference path="../../typings/index.d.ts"/>
import {IUserManager} from "./IUserManager"; import {IUserManager} from "./IUserManager";
import {IGalleryManager} from "./IGalleryManager"; import {IGalleryManager} from "./IGalleryManager";
import {ISearchManager} from "./ISearchManager"; import {ISearchManager} from "./ISearchManager";

View File

@ -5,7 +5,7 @@ import {DiskManager} from "../DiskManger";
export class GalleryManager implements IGalleryManager { export class GalleryManager implements IGalleryManager {
public listDirectory(relativeDirectoryName, cb:(error:any, result:Directory) => void) { public listDirectory(relativeDirectoryName: string, cb: (error: any, result: Directory) => void) {
return DiskManager.scanDirectory(relativeDirectoryName, cb); return DiskManager.scanDirectory(relativeDirectoryName, cb);
} }

View File

@ -5,15 +5,15 @@ import {SearchResult} from "../../../common/entities/SearchResult";
export class SearchManager implements ISearchManager { export class SearchManager implements ISearchManager {
autocomplete(text, cb:(error:any, result:Array<AutoCompleteItem>) => void) { autocomplete(text: string, cb: (error: any, result: Array<AutoCompleteItem>) => void) {
throw new Error("not implemented"); throw new Error("not implemented");
} }
search(text, searchType:SearchTypes, cb:(error:any, result:SearchResult) => void) { search(text: string, searchType: SearchTypes, cb: (error: any, result: SearchResult) => void) {
throw new Error("not implemented"); throw new Error("not implemented");
} }
instantSearch(text, cb:(error:any, result:SearchResult) => void) { instantSearch(text: string, cb: (error: any, result: SearchResult) => void) {
throw new Error("not implemented"); throw new Error("not implemented");
} }

View File

@ -1,6 +1,4 @@
///<reference path="flat-file-db.ts"/> ///<reference path="flat-file-db.ts"/>
import {User, UserRoles} from "../../../common/entities/User"; import {User, UserRoles} from "../../../common/entities/User";
import {IUserManager} from "../IUserManager"; import {IUserManager} from "../IUserManager";
import {ProjectPath} from "../../ProjectPath"; import {ProjectPath} from "../../ProjectPath";
@ -43,7 +41,7 @@ export class UserManager implements IUserManager {
} }
public findOne(filter, cb:(error:any, result:User) => void) { public findOne(filter: any, cb: (error: any, result: User) => void) {
this.find(filter, (error, result: Array<User>) => { this.find(filter, (error, result: Array<User>) => {
if (error) { if (error) {
return cb(error, null); return cb(error, null);
@ -56,9 +54,9 @@ export class UserManager implements IUserManager {
}); });
} }
public find(filter, cb:(error:any, result:Array<User>) => void) { public find(filter: any, cb: (error: any, result: Array<User>) => void) {
let users = this.db.get("users").filter((u) => Utils.equalsFilter(u, filter)); let users = this.db.get("users").filter((u: User) => Utils.equalsFilter(u, filter));
return cb(null, users); return cb(null, users);
} }
@ -75,7 +73,7 @@ export class UserManager implements IUserManager {
} }
public deleteUser(id: number, cb: (error: any) => void) { public deleteUser(id: number, cb: (error: any) => void) {
let users = this.db.get("users").filter((u) => u.id != id); let users = this.db.get("users").filter((u: User) => u.id != id);
this.db.put("users", users); this.db.put("users", users);
return cb(null); return cb(null);
} }

View File

@ -3,11 +3,11 @@ declare module "flat-file-db" {
} }
declare interface DB { declare interface DB {
sync(); sync(): any;
put(); put(): any;
get(); get(): any;
del(); del(): any;
has(); has(): any;
keys(); keys(): any;
close(); close(): any;
} }

View File

@ -1,10 +1,8 @@
///<reference path="../../typings/index.d.ts"/>
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs";
import {UserRoles} from "../../common/entities/User"; import {UserRoles} from "../../common/entities/User";
export class AdminRouter { export class AdminRouter {
constructor(private app) { constructor(private app: any) {
this.addResetDB(); this.addResetDB();
this.addIndexGallery(); this.addIndexGallery();

View File

@ -1,10 +1,10 @@
///<reference path="../../typings/index.d.ts"/>
import {RenderingMWs} from "../middlewares/RenderingMWs"; import {RenderingMWs} from "../middlewares/RenderingMWs";
import {Error, ErrorCodes} from "../../common/entities/Error"; import {Error, ErrorCodes} from "../../common/entities/Error";
import Request = Express.Request;
import Response = Express.Response;
export class ErrorRouter { export class ErrorRouter {
constructor(private app) { constructor(private app: any) {
this.addApiErrorHandler(); this.addApiErrorHandler();
this.addGenericHandler(); this.addGenericHandler();
@ -17,7 +17,7 @@ export class ErrorRouter {
}; };
private addGenericHandler() { private addGenericHandler() {
this.app.use((err, req, res, next) => { this.app.use((err: any, req: Request, res: Response, next: Function) => {
//Flush out the stack to the console //Flush out the stack to the console
console.error(err.stack); console.error(err.stack);

View File

@ -1,12 +1,10 @@
///<reference path="../../typings/index.d.ts"/>
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs";
import {GalleryMWs} from "../middlewares/GalleryMWs"; import {GalleryMWs} from "../middlewares/GalleryMWs";
import {RenderingMWs} from "../middlewares/RenderingMWs"; import {RenderingMWs} from "../middlewares/RenderingMWs";
import {ThumbnailGeneratorMWs} from "../middlewares/ThumbnailGeneratorMWs"; import {ThumbnailGeneratorMWs} from "../middlewares/ThumbnailGeneratorMWs";
export class GalleryRouter { export class GalleryRouter {
constructor(private app) { constructor(private app: any) {
this.addGetImageThumbnail(); this.addGetImageThumbnail();
this.addGetImage(); this.addGetImage();

View File

@ -1,5 +1,3 @@
///<reference path="../../typings/index.d.ts"/>
import * as _express from "express"; import * as _express from "express";
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from "express";
import * as _path from "path"; import * as _path from "path";
@ -24,8 +22,9 @@ export class PublicRouter {
this.app.use(_express.static(_path.resolve(__dirname, './../../frontend'))); this.app.use(_express.static(_path.resolve(__dirname, './../../frontend')));
this.app.use('/node_modules', _express.static(_path.resolve(__dirname, './../../node_modules'))); this.app.use('/node_modules', _express.static(_path.resolve(__dirname, './../../node_modules')));
this.app.use('/common', _express.static(_path.resolve(__dirname, './../../common')));
var renderIndex = (req:Request, res:Response) => { const renderIndex = (req: Request, res: Response) => {
res.render(_path.resolve(__dirname, './../../frontend/index.ejs'), res.tpl); res.render(_path.resolve(__dirname, './../../frontend/index.ejs'), res.tpl);
}; };

View File

@ -1,10 +1,8 @@
///<reference path="../../typings/index.d.ts"/>
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs";
import {UserRoles} from "../../common/entities/User"; import {UserRoles} from "../../common/entities/User";
export class SharingRouter { export class SharingRouter {
constructor(private app) { constructor(private app: any) {
this.addGetSharing(); this.addGetSharing();
this.addUpdateSharing(); this.addUpdateSharing();

View File

@ -1,5 +1,3 @@
///<reference path="../../typings/index.d.ts"/>
import {UserMWs} from "../middlewares/user/UserMWs"; import {UserMWs} from "../middlewares/user/UserMWs";
import {UserRoles} from "../../common/entities/User"; import {UserRoles} from "../../common/entities/User";
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs";

View File

@ -1,5 +1,3 @@
///<reference path="../typings/index.d.ts"/>
import * as _express from "express"; import * as _express from "express";
import * as _session from "express-session"; import * as _session from "express-session";
import * as _bodyParser from "body-parser"; import * as _bodyParser from "body-parser";
@ -11,7 +9,7 @@ import {GalleryRouter} from "./routes/GalleryRouter";
import {AdminRouter} from "./routes/AdminRouter"; import {AdminRouter} from "./routes/AdminRouter";
import {ErrorRouter} from "./routes/ErrorRouter"; import {ErrorRouter} from "./routes/ErrorRouter";
import {SharingRouter} from "./routes/SharingRouter"; import {SharingRouter} from "./routes/SharingRouter";
import {DatabaseType} from "./../common/config/Config"; import {DatabaseType} from "../common/config/Config";
import {ObjectManagerRepository} from "./model/ObjectManagerRepository"; import {ObjectManagerRepository} from "./model/ObjectManagerRepository";
import {Config} from "./config/Config"; import {Config} from "./config/Config";
@ -30,7 +28,7 @@ export class Server {
this.app.set('view engine', 'ejs'); this.app.set('view engine', 'ejs');
if (process.env.DEBUG) { if (process.env.DEBUG) {
var _morgan = require('morgan'); let _morgan = require('morgan');
this.app.use(_morgan('dev')); this.app.use(_morgan('dev'));
} }
@ -90,7 +88,7 @@ export class Server {
/** /**
* Event listener for HTTP server "error" event. * Event listener for HTTP server "error" event.
*/ */
private onError = (error) => { private onError = (error: any) => {
if (error.syscall !== 'listen') { if (error.syscall !== 'listen') {
throw error; throw error;
} }

View File

@ -1,15 +1,15 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"sourceMap": false,
"module": "commonjs", "module": "commonjs",
"moduleResolution": "node", "moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"removeComments": false "lib": [
}, "es2015",
"exclude": [ "dom"
"node_modules", ],
"typings" "suppressImplicitAnyIndexErrors": true
] }
} }

View File

@ -34,7 +34,7 @@ export class Utils {
return url.substring(0, url.length - 1); return url.substring(0, url.length - 1);
} }
public static updateKeys(targetObject, sourceObject) { public static updateKeys(targetObject: any, sourceObject: any) {
Object.keys(sourceObject).forEach((key) => { Object.keys(sourceObject).forEach((key) => {
if (typeof targetObject[key] === "undefined") { if (typeof targetObject[key] === "undefined") {
return; return;
@ -47,7 +47,7 @@ export class Utils {
}); });
} }
public static setKeys(targetObject, sourceObject) { public static setKeys(targetObject: any, sourceObject: any) {
Object.keys(sourceObject).forEach((key) => { Object.keys(sourceObject).forEach((key) => {
if (typeof targetObject[key] === "object") { if (typeof targetObject[key] === "object") {
Utils.setKeys(targetObject[key], sourceObject[key]); Utils.setKeys(targetObject[key], sourceObject[key]);
@ -57,7 +57,7 @@ export class Utils {
}); });
} }
public static setKeysForced(targetObject, sourceObject) { public static setKeysForced(targetObject: any, sourceObject: any) {
Object.keys(sourceObject).forEach((key) => { Object.keys(sourceObject).forEach((key) => {
if (typeof sourceObject[key] === "object") { if (typeof sourceObject[key] === "object") {
if (typeof targetObject[key] === "undefined") { if (typeof targetObject[key] === "undefined") {
@ -70,7 +70,7 @@ export class Utils {
}); });
} }
public static enumToArray(EnumType):Array<{key:number;value:string;}> { public static enumToArray(EnumType: any): Array<{key: number;value: string;}> {
let arr: Array<{key: number;value: string;}> = []; let arr: Array<{key: number;value: string;}> = [];
for (let enumMember in EnumType) { for (let enumMember in EnumType) {
if (!EnumType.hasOwnProperty(enumMember)) { if (!EnumType.hasOwnProperty(enumMember)) {

View File

@ -1,5 +1,5 @@
function isFunction(functionToCheck) { function isFunction(functionToCheck: any) {
var getType = {}; let getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
} }

View File

@ -1,13 +1,15 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"sourceMap": true,
"module": "commonjs", "module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true "experimentalDecorators": true,
}, "lib": [
"exclude": [ "es2015",
"./../node_modules", "dom"
"./../typings" ],
] "suppressImplicitAnyIndexErrors": true
}
} }

View File

@ -1,21 +1,12 @@
///<reference path="../../browser.d.ts"/>
import {Component, OnInit} from "@angular/core"; import {Component, OnInit} from "@angular/core";
import {AuthenticationService} from "../model/network/authentication.service.ts"; import {AuthenticationService} from "../model/network/authentication.service";
import {Router} from "@angular/router-deprecated"; import {Router} from "@angular/router";
import {FrameComponent} from "../frame/frame.component";
import {UserRoles} from "../../../common/entities/User"; import {UserRoles} from "../../../common/entities/User";
import {FORM_DIRECTIVES} from "@angular/common";
import {StringifyRole} from "./../pipes/StringifyRolePipe";
import {Config} from "../config/Config"; import {Config} from "../config/Config";
import {UserMangerSettingsComponent} from "../settings/usermanager/usermanager.settings.component";
@Component({ @Component({
selector: 'admin', selector: 'admin',
templateUrl: 'app/admin/admin.component.html', templateUrl: 'app/admin/admin.component.html',
styleUrls: ['app/admin/admin.component.css'], styleUrls: ['app/admin/admin.component.css']
directives: [FrameComponent, FORM_DIRECTIVES, UserMangerSettingsComponent],
pipes: [StringifyRole]
}) })
export class AdminComponent implements OnInit { export class AdminComponent implements OnInit {
userManagementEnable: boolean = false; userManagementEnable: boolean = false;

View File

@ -1,67 +1,13 @@
///<reference path="../browser.d.ts"/>
import {Component, OnInit} from "@angular/core"; import {Component, OnInit} from "@angular/core";
import {LoginComponent} from "./login/login.component"; import {AuthenticationService} from "./model/network/authentication.service";
import {AuthenticationService} from "./model/network/authentication.service.ts";
import {GalleryComponent} from "./gallery/gallery.component";
import {User} from "../../common/entities/User"; import {User} from "../../common/entities/User";
import {Router, RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from "@angular/router-deprecated"; import {Router} from "@angular/router";
import {HTTP_PROVIDERS} from "@angular/http";
import {UserService} from "./model/network/user.service.ts";
import {GalleryService} from "./gallery/gallery.service";
import {AdminComponent} from "./admin/admin.component";
import {NetworkService} from "./model/network/network.service";
import {ThumbnailLoaderService} from "./gallery/grid/thumnailLoader.service";
import {GalleryCacheService} from "./gallery/cache.gallery.service";
import {FullScreenService} from "./gallery/fullscreen.service";
@Component({ @Component({
selector: 'pi-gallery2-app', selector: 'pi-gallery2-app',
template: `<router-outlet></router-outlet>`, template: `<router-outlet></router-outlet>`,
directives: [ROUTER_DIRECTIVES],
providers: [
HTTP_PROVIDERS,
ROUTER_PROVIDERS,
NetworkService,
UserService,
GalleryCacheService,
GalleryService,
AuthenticationService,
ThumbnailLoaderService,
FullScreenService]
}) })
@RouteConfig([
{
path: '/',
redirectTo: ["Login"]
},
{
path: '/login',
name: 'Login',
component: LoginComponent,
useAsDefault: true
},
{
path: '/admin',
name: 'Admin',
component: AdminComponent
},
{
path: '/gallery',
redirectTo: ["Gallery", {directory: ""}]
},
{
path: '/gallery/:directory',
name: 'Gallery',
component: GalleryComponent
},
{
path: '/search/:searchText',
name: 'Search',
component: GalleryComponent
},
])
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
constructor(private _router: Router, private _authenticationService: AuthenticationService) { constructor(private _router: Router, private _authenticationService: AuthenticationService) {
@ -70,14 +16,14 @@ export class AppComponent implements OnInit {
ngOnInit() { ngOnInit() {
this._authenticationService.OnUserChanged.on((user: User) => { this._authenticationService.OnUserChanged.on((user: User) => {
if (user != null) { if (user != null) {
if (this._router.isRouteActive(this._router.generate(['Login']))) { if (this._router.isActive('login', true)) {
console.log("routing"); console.log("routing");
this._router.navigate(["Gallery", {directory: ""}]); this._router.navigate(["gallery", ""]);
} }
} else { } else {
if (!this._router.isRouteActive(this._router.generate(['Login']))) { if (this._router.isActive('login', true)) {
console.log("routing"); console.log("routing");
this._router.navigate(["Login"]); this._router.navigate(["login"]);
} }
} }

View File

@ -0,0 +1,65 @@
import {NgModule} from "@angular/core";
import {BrowserModule} from "@angular/platform-browser";
import {FormsModule} from "@angular/forms";
import {HttpModule} from "@angular/http";
import {AppComponent} from "./app.component";
import {appRoutes} from "./app.routing";
import {UserService} from "./model/network/user.service";
import {GalleryService} from "./gallery/gallery.service";
import {NetworkService} from "./model/network/network.service";
import {ThumbnailLoaderService} from "./gallery/grid/thumnailLoader.service";
import {GalleryCacheService} from "./gallery/cache.gallery.service";
import {FullScreenService} from "./gallery/fullscreen.service";
import {AuthenticationService} from "./model/network/authentication.service";
import {UserMangerSettingsComponent} from "./settings/usermanager/usermanager.settings.component";
import {FrameComponent} from "./frame/frame.component";
import {GalleryLightboxPhotoComponent} from "./gallery/lightbox/photo/photo.lightbox.gallery.component";
import {GalleryPhotoLoadingComponent} from "./gallery/grid/photo/loading/loading.photo.grid.gallery.component";
import {GalleryNavigatorComponent} from "./gallery/navigator/navigator.gallery.component";
import {GallerySearchComponent} from "./gallery/search/search.gallery.component";
import {GalleryLightboxComponent} from "./gallery/lightbox/lightbox.gallery.component";
import {GalleryDirectoryComponent} from "./gallery/directory/directory.gallery.component";
import {GalleryGridComponent} from "./gallery/grid/grid.gallery.component";
import {GalleryPhotoComponent} from "./gallery/grid/photo/photo.grid.gallery.component";
import {LoginComponent} from "./login/login.component";
import {AdminComponent} from "./admin/admin.component";
import {GalleryComponent} from "./gallery/gallery.component";
import {StringifyRole} from "./pipes/StringifyRolePipe";
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
appRoutes
],
declarations: [AppComponent,
LoginComponent,
AdminComponent,
GalleryComponent,
FrameComponent,
UserMangerSettingsComponent,
GalleryLightboxPhotoComponent,
GalleryPhotoLoadingComponent,
GalleryGridComponent,
GalleryDirectoryComponent,
GalleryLightboxComponent,
FrameComponent,
GallerySearchComponent,
GalleryNavigatorComponent,
GalleryPhotoComponent,
FrameComponent,
StringifyRole],
providers: [
NetworkService,
UserService,
GalleryCacheService,
GalleryService,
AuthenticationService,
ThumbnailLoaderService,
FullScreenService],
bootstrap: [AppComponent]
})
export class AppModule {
}

View File

@ -0,0 +1,32 @@
import {ModuleWithProviders} from "@angular/core";
import {Routes, RouterModule} from "@angular/router";
import {LoginComponent} from "./login/login.component";
import {GalleryComponent} from "./gallery/gallery.component";
import {AdminComponent} from "./admin/admin.component";
const ROUTES: Routes = [
{
path: 'login',
component: LoginComponent
},
{
path: 'admin',
component: AdminComponent
},
{
path: 'gallery/:directory',
component: GalleryComponent
},
{
path: 'gallery',
component: GalleryComponent
},
{
path: 'search/:searchText',
component: GalleryComponent
},
{path: '', redirectTo: '/login', pathMatch: 'full'}
];
export const appRoutes: ModuleWithProviders = RouterModule.forRoot(ROUTES);

View File

@ -2,10 +2,10 @@ import {ConfigClass} from "../../../common/config/Config";
import {Utils} from "../../../common/Utils"; import {Utils} from "../../../common/Utils";
declare module ServerInject { declare module ServerInject {
export var ConfigInject; export let ConfigInject: ConfigClass;
} }
export var Config = new ConfigClass(); export let Config = new ConfigClass();
if (typeof ServerInject !== "undefined" && typeof ServerInject.ConfigInject !== "undefined") { if (typeof ServerInject !== "undefined" && typeof ServerInject.ConfigInject !== "undefined") {
Utils.updateKeys(Config.Client, ServerInject.ConfigInject); Utils.updateKeys(Config.Client, ServerInject.ConfigInject);

View File

@ -12,8 +12,8 @@
</div> </div>
<div id="navbar" class="collapse navbar-collapse"> <div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="active"><a [routerLink]="['Gallery',{directory: '/'}]">Gallery</a></li> <li class="active"><a [routerLink]="['/gallery','/']">Gallery</a></li>
<li><a [routerLink]="['Admin']">Admin</a></li> <li><a [routerLink]="['/admin']">Admin</a></li>
</ul> </ul>
<ul class="nav navbar-nav navbar-right" *ngIf="authenticationRequired"> <ul class="nav navbar-nav navbar-right" *ngIf="authenticationRequired">
<li> <li>

View File

@ -1,7 +1,5 @@
///<reference path="../../browser.d.ts"/>
import {Component, ViewEncapsulation} from "@angular/core"; import {Component, ViewEncapsulation} from "@angular/core";
import {RouterLink} from "@angular/router-deprecated"; import {RouterLink} from "@angular/router";
import {AuthenticationService} from "../model/network/authentication.service"; import {AuthenticationService} from "../model/network/authentication.service";
import {User} from "../../../common/entities/User"; import {User} from "../../../common/entities/User";
import {Config} from "../config/Config"; import {Config} from "../config/Config";
@ -9,7 +7,7 @@ import {Config} from "../config/Config";
@Component({ @Component({
selector: 'app-frame', selector: 'app-frame',
templateUrl: 'app/frame/frame.component.html', templateUrl: 'app/frame/frame.component.html',
directives: [RouterLink], providers: [RouterLink],
encapsulation: ViewEncapsulation.Emulated encapsulation: ViewEncapsulation.Emulated
}) })
export class FrameComponent { export class FrameComponent {

View File

@ -1,5 +1,3 @@
///<reference path="../../browser.d.ts"/>
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {Photo} from "../../../common/entities/Photo"; import {Photo} from "../../../common/entities/Photo";
import {Directory} from "../../../common/entities/Directory"; import {Directory} from "../../../common/entities/Directory";

View File

@ -1,4 +1,4 @@
<a class="button btn btn-default" [routerLink]="['Gallery',{directory: getDirectoryPath()}]" <a class="button btn btn-default" [routerLink]="['/gallery', getDirectoryPath()]"
style="display: inline-block;"> style="display: inline-block;">
{{directory.name}} {{directory.name}}
</a> </a>

View File

@ -1,14 +1,12 @@
///<reference path="../../../browser.d.ts"/>
import {Component, Input} from "@angular/core"; import {Component, Input} from "@angular/core";
import {Directory} from "../../../../common/entities/Directory"; import {Directory} from "../../../../common/entities/Directory";
import {RouterLink} from "@angular/router-deprecated"; import {RouterLink} from "@angular/router";
import {Utils} from "../../../../common/Utils"; import {Utils} from "../../../../common/Utils";
@Component({ @Component({
selector: 'gallery-directory', selector: 'gallery-directory',
templateUrl: 'app/gallery/directory/directory.gallery.component.html', templateUrl: 'app/gallery/directory/directory.gallery.component.html',
directives: [RouterLink], providers: [RouterLink],
}) })
export class GalleryDirectoryComponent { export class GalleryDirectoryComponent {
@Input() directory:Directory; @Input() directory:Directory;

View File

@ -1,5 +1,3 @@
///<reference path="../../browser.d.ts"/>
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
@Injectable() @Injectable()

View File

@ -17,10 +17,10 @@
<li class="active"> <li class="active">
Searching for: Searching for:
<span [ngSwitch]="_galleryService.content.searchResult.searchType"> <span [ngSwitch]="_galleryService.content.searchResult.searchType">
<span *ngSwitchWhen="0" class="glyphicon glyphicon-picture"></span> <span *ngSwitchCase="0" class="glyphicon glyphicon-picture"></span>
<span *ngSwitchWhen="1" class="glyphicon glyphicon-folder-open"></span> <span *ngSwitchCase="1" class="glyphicon glyphicon-folder-open"></span>
<span *ngSwitchWhen="2" class="glyphicon glyphicon-tag"></span> <span *ngSwitchCase="2" class="glyphicon glyphicon-tag"></span>
<span *ngSwitchWhen="3" class="glyphicon glyphicon-map-marker"></span> <span *ngSwitchCase="3" class="glyphicon glyphicon-map-marker"></span>
</span> </span>
<strong>{{_galleryService.content.searchResult.searchText}}</strong> <strong>{{_galleryService.content.searchResult.searchText}}</strong>
</li> </li>

View File

@ -1,28 +1,16 @@
///<reference path="../../browser.d.ts"/>
import {Component, OnInit, ViewChild} from "@angular/core"; import {Component, OnInit, ViewChild} from "@angular/core";
import {AuthenticationService} from "../model/network/authentication.service.ts"; import {AuthenticationService} from "../model/network/authentication.service";
import {Router, RouteParams} from "@angular/router-deprecated"; import {Router, ActivatedRoute, Params} from "@angular/router";
import {GalleryService} from "./gallery.service"; import {GalleryService} from "./gallery.service";
import {GalleryDirectoryComponent} from "./directory/directory.gallery.component";
import {GalleryGridComponent} from "./grid/grid.gallery.component"; import {GalleryGridComponent} from "./grid/grid.gallery.component";
import {FrameComponent} from "../frame/frame.component";
import {GalleryLightboxComponent} from "./lightbox/lightbox.gallery.component";
import {GallerySearchComponent} from "./search/search.gallery.component"; import {GallerySearchComponent} from "./search/search.gallery.component";
import {Config} from "../config/Config"; import {Config} from "../config/Config";
import {SearchTypes} from "../../../common/entities/AutoCompleteItem"; import {SearchTypes} from "../../../common/entities/AutoCompleteItem";
import {GalleryNavigatorComponent} from "./navigator/navigator.gallery.component";
@Component({ @Component({
selector: 'gallery', selector: 'gallery',
templateUrl: 'app/gallery/gallery.component.html', templateUrl: 'app/gallery/gallery.component.html',
styleUrls: ['app/gallery/gallery.component.css'], styleUrls: ['app/gallery/gallery.component.css']
directives: [GalleryGridComponent,
GalleryDirectoryComponent,
GalleryLightboxComponent,
FrameComponent,
GallerySearchComponent,
GalleryNavigatorComponent]
}) })
export class GalleryComponent implements OnInit { export class GalleryComponent implements OnInit {
@ -32,28 +20,29 @@ export class GalleryComponent implements OnInit {
public showSearchBar: boolean = true; public showSearchBar: boolean = true;
constructor(private _galleryService: GalleryService, constructor(private _galleryService: GalleryService,
private _params:RouteParams,
private _authService: AuthenticationService, private _authService: AuthenticationService,
private _router:Router) { private _router: Router,
private _route: ActivatedRoute) {
this.showSearchBar = Config.Client.Search.searchEnabled; this.showSearchBar = Config.Client.Search.searchEnabled;
} }
ngOnInit() { ngOnInit() {
if (!this._authService.isAuthenticated()) { if (!this._authService.isAuthenticated()) {
this._router.navigate(['Login']); this._router.navigate(['login']);
return; return;
} }
this._route.params
let searchText = this._params.get('searchText'); .subscribe((params: Params) => {
let searchText = params['searchText'];
if (searchText && searchText != "") { if (searchText && searchText != "") {
console.log("searching"); console.log("searching");
let typeString = this._params.get('type'); let typeString = params['type'];
if (typeString && typeString != "") { if (typeString && typeString != "") {
console.log("with type"); console.log("with type");
let type:SearchTypes = SearchTypes[typeString]; let type: SearchTypes = <any>SearchTypes[typeString];
this._galleryService.search(searchText, type); this._galleryService.search(searchText, type);
return; return;
} }
@ -63,11 +52,15 @@ export class GalleryComponent implements OnInit {
} }
let directoryName = this._params.get('directory'); let directoryName = params['directory'];
directoryName = directoryName ? directoryName : ""; directoryName = directoryName ? directoryName : "";
this._galleryService.getDirectory(directoryName); this._galleryService.getDirectory(directoryName);
});
} }

View File

@ -1,32 +0,0 @@
import {it, inject, addProviders} from "@angular/core/testing";
import {BaseRequestOptions, Http} from "@angular/http";
import {MockBackend} from "@angular/http/testing";
import {provide} from "@angular/core";
import "rxjs/Rx";
import {NetworkService} from "../model/network/network.service";
import {GalleryService} from "./gallery.service";
describe('GalleryService', () => {
beforeEach(() => {
addProviders([
MockBackend,
BaseRequestOptions,
provide(Http, {
useFactory: (backend, options) => {
return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions]
}),
NetworkService,
GalleryService
]);
});
it('placeholder test', inject([], () => {
expect(true).toBe(true);
}));
});

View File

@ -1,7 +1,5 @@
///<reference path="../../browser.d.ts"/>
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {NetworkService} from "../model/network/network.service.ts"; import {NetworkService} from "../model/network/network.service";
import {Message} from "../../../common/entities/Message"; import {Message} from "../../../common/entities/Message";
import {ContentWrapper} from "../../../common/entities/ConentWrapper"; import {ContentWrapper} from "../../../common/entities/ConentWrapper";
import {Photo} from "../../../common/entities/Photo"; import {Photo} from "../../../common/entities/Photo";
@ -20,7 +18,7 @@ export class GalleryService {
this.content = new ContentWrapper(); this.content = new ContentWrapper();
} }
lastRequest = { lastRequest: {directory: any} = {
directory: null directory: null
}; };
public getDirectory(directoryName:string):Promise<Message<ContentWrapper>> { public getDirectory(directoryName:string):Promise<Message<ContentWrapper>> {

View File

@ -1,5 +1,3 @@
///<reference path="../../../browser.d.ts"/>
import { import {
Component, Component,
Input, Input,
@ -22,7 +20,6 @@ import {Config} from "../../config/Config";
selector: 'gallery-grid', selector: 'gallery-grid',
templateUrl: 'app/gallery/grid/grid.gallery.component.html', templateUrl: 'app/gallery/grid/grid.gallery.component.html',
styleUrls: ['app/gallery/grid/grid.gallery.component.css'], styleUrls: ['app/gallery/grid/grid.gallery.component.css'],
directives: [GalleryPhotoComponent]
}) })
export class GalleryGridComponent implements OnChanges,AfterViewInit { export class GalleryGridComponent implements OnChanges,AfterViewInit {

View File

@ -1,10 +1,8 @@
///<reference path="../../../../browser.d.ts"/>
import {Component, Input, ElementRef, ViewChild, OnInit, AfterViewInit, OnDestroy} from "@angular/core"; import {Component, Input, ElementRef, ViewChild, OnInit, AfterViewInit, OnDestroy} from "@angular/core";
import {IRenderable, Dimension} from "../../../model/IRenderable"; import {IRenderable, Dimension} from "../../../model/IRenderable";
import {GridPhoto} from "../GridPhoto"; import {GridPhoto} from "../GridPhoto";
import {SearchTypes} from "../../../../../common/entities/AutoCompleteItem"; import {SearchTypes} from "../../../../../common/entities/AutoCompleteItem";
import {RouterLink} from "@angular/router-deprecated"; import {RouterLink} from "@angular/router";
import {Config} from "../../../config/Config"; import {Config} from "../../../config/Config";
import { import {
ThumbnailLoaderService, ThumbnailLoaderService,
@ -12,13 +10,12 @@ import {
ThumbnailLoadingListener, ThumbnailLoadingListener,
ThumbnailLoadingPriority ThumbnailLoadingPriority
} from "../thumnailLoader.service"; } from "../thumnailLoader.service";
import {GalleryPhotoLoadingComponent} from "./loading/loading.photo.grid.gallery.component";
@Component({ @Component({
selector: 'gallery-grid-photo', selector: 'gallery-grid-photo',
templateUrl: 'app/gallery/grid/photo/photo.grid.gallery.component.html', templateUrl: 'app/gallery/grid/photo/photo.grid.gallery.component.html',
styleUrls: ['app/gallery/grid/photo/photo.grid.gallery.component.css'], styleUrls: ['app/gallery/grid/photo/photo.grid.gallery.component.css'],
directives: [RouterLink, GalleryPhotoLoadingComponent], providers: [RouterLink],
}) })
export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit, OnDestroy { export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit, OnDestroy {
@Input() gridPhoto: GridPhoto; @Input() gridPhoto: GridPhoto;

View File

@ -1,5 +1,3 @@
///<reference path="../../../browser.d.ts"/>
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {GridPhoto} from "./GridPhoto"; import {GridPhoto} from "./GridPhoto";
import {Config} from "../../config/Config"; import {Config} from "../../config/Config";
@ -128,7 +126,7 @@ export class ThumbnailLoaderService {
task.gridPhoto.thumbnailLoaded(); task.gridPhoto.thumbnailLoaded();
this.galleryChacheService.photoUpdated(task.gridPhoto.photo); this.galleryChacheService.photoUpdated(task.gridPhoto.photo);
task.taskEntities.forEach(te=>te.listener.onLoad()); task.taskEntities.forEach((te: ThumbnailTaskEntity) => te.listener.onLoad());
this.taskReady(task); this.taskReady(task);
this.runningRequests--; this.runningRequests--;
@ -136,7 +134,7 @@ export class ThumbnailLoaderService {
}; };
curImg.onerror = (error) => { curImg.onerror = (error) => {
task.taskEntities.forEach(te=>te.listener.onError(error)); task.taskEntities.forEach((te: ThumbnailTaskEntity) => te.listener.onError(error));
this.taskReady(task); this.taskReady(task);
this.runningRequests--; this.runningRequests--;
@ -149,7 +147,7 @@ export class ThumbnailLoaderService {
export interface ThumbnailLoadingListener { export interface ThumbnailLoadingListener {
onStartedLoading: () => void; onStartedLoading: () => void;
onLoad: () => void; onLoad: () => void;
onError:(error)=>void; onError: (error: any) => void;
} }

View File

@ -1,18 +1,13 @@
///<reference path="../../../browser.d.ts"/>
import {Component, QueryList, Output, EventEmitter, HostListener, ElementRef, ViewChild} from "@angular/core"; import {Component, QueryList, Output, EventEmitter, HostListener, ElementRef, ViewChild} from "@angular/core";
import {Photo} from "../../../../common/entities/Photo"; import {Photo} from "../../../../common/entities/Photo";
import {GalleryPhotoComponent} from "../grid/photo/photo.grid.gallery.component.ts"; import {GalleryPhotoComponent} from "../grid/photo/photo.grid.gallery.component";
import {BrowserDomAdapter} from "@angular/platform-browser/src/browser/browser_adapter";
import {Dimension} from "../../model/IRenderable"; import {Dimension} from "../../model/IRenderable";
import {GalleryLightboxPhotoComponent} from "./photo/photo.lightbox.gallery.component";
import {FullScreenService} from "../fullscreen.service"; import {FullScreenService} from "../fullscreen.service";
@Component({ @Component({
selector: 'gallery-lightbox', selector: 'gallery-lightbox',
styleUrls: ['app/gallery/lightbox/lightbox.gallery.component.css'], styleUrls: ['app/gallery/lightbox/lightbox.gallery.component.css'],
templateUrl: 'app/gallery/lightbox/lightbox.gallery.component.html', templateUrl: 'app/gallery/lightbox/lightbox.gallery.component.html',
directives: [GalleryLightboxPhotoComponent]
}) })
export class GalleryLightboxComponent { export class GalleryLightboxComponent {
@Output('onLastElement') onLastElement = new EventEmitter(); @Output('onLastElement') onLastElement = new EventEmitter();
@ -23,14 +18,12 @@ export class GalleryLightboxComponent {
private activePhoto: GalleryPhotoComponent; private activePhoto: GalleryPhotoComponent;
public gridPhotoQL: QueryList<GalleryPhotoComponent>; public gridPhotoQL: QueryList<GalleryPhotoComponent>;
private dom:BrowserDomAdapter;
private visible = false; private visible = false;
@ViewChild("root") elementRef: ElementRef; @ViewChild("root") elementRef: ElementRef;
constructor(private fullScreenService: FullScreenService) { constructor(private fullScreenService: FullScreenService) {
this.dom = new BrowserDomAdapter();
} }
@ -91,7 +84,7 @@ export class GalleryLightboxComponent {
this.showPhoto(selectedPhoto); this.showPhoto(selectedPhoto);
this.dom.setStyle(this.dom.query('body'), 'overflow', 'hidden'); document.getElementsByTagName('body')[0].style.overflow = 'hidden';
} }
public hide() { public hide() {
@ -104,14 +97,14 @@ export class GalleryLightboxComponent {
this.setBodyScrollTop(to.top); this.setBodyScrollTop(to.top);
} }
this.dom.setStyle(this.dom.query('body'), 'overflow', 'auto'); document.getElementsByTagName('body')[0].style.overflow = 'auto';
this.activePhoto = null; this.activePhoto = null;
} }
private findPhotoComponent(photo) { private findPhotoComponent(photo: any) {
let galleryPhotoComponents = this.gridPhotoQL.toArray(); let galleryPhotoComponents = this.gridPhotoQL.toArray();
for (let i = 0; i < galleryPhotoComponents.length; i++) { for (let i = 0; i < galleryPhotoComponents.length; i++) {
if (galleryPhotoComponents[i].gridPhoto.photo == photo) { if (galleryPhotoComponents[i].gridPhoto.photo == photo) {
@ -122,8 +115,8 @@ export class GalleryLightboxComponent {
} }
@HostListener('window:keydown', ['$event']) @HostListener('window:keydown', ['$event'])
onKeyPress(e) { onKeyPress(e: KeyboardEvent) {
let event = window.event ? window.event : e; let event: KeyboardEvent = window.event ? <any>window.event : e;
switch (event.keyCode) { switch (event.keyCode) {
case 37: case 37:
this.prevImage(); this.prevImage();

View File

@ -1,6 +1,6 @@
<ol id="directory-path" class="breadcrumb"> <ol id="directory-path" class="breadcrumb">
<li *ngFor="let path of routes"> <li *ngFor="let path of routes">
<a *ngIf="path.route" [routerLink]="['Gallery',{directory: path.route}]">{{path.name}}</a> <a *ngIf="path.route" [routerLink]="['/gallery',path.route]">{{path.name}}</a>
<span *ngIf="!path.route">{{path.name}}</span> <span *ngIf="!path.route">{{path.name}}</span>
</li> </li>

View File

@ -1,13 +1,11 @@
///<reference path="../../../browser.d.ts"/>
import {Component, Input, OnChanges} from "@angular/core"; import {Component, Input, OnChanges} from "@angular/core";
import {Directory} from "../../../../common/entities/Directory"; import {Directory} from "../../../../common/entities/Directory";
import {RouterLink} from "@angular/router-deprecated"; import {RouterLink} from "@angular/router";
@Component({ @Component({
selector: 'gallery-navbar', selector: 'gallery-navbar',
templateUrl: 'app/gallery/navigator/navigator.gallery.component.html', templateUrl: 'app/gallery/navigator/navigator.gallery.component.html',
directives: [RouterLink], providers: [RouterLink],
}) })
export class GalleryNavigatorComponent implements OnChanges { export class GalleryNavigatorComponent implements OnChanges {
@Input() directory: Directory; @Input() directory: Directory;
@ -22,7 +20,7 @@ export class GalleryNavigatorComponent implements OnChanges {
this.getPath(); this.getPath();
} }
getPath() { getPath(): any {
if (!this.directory) { if (!this.directory) {
return []; return [];
} }
@ -41,7 +39,7 @@ export class GalleryNavigatorComponent implements OnChanges {
} }
let arr = []; let arr: any = [];
//create root link //create root link
if (dirs.length == 0) { if (dirs.length == 0) {

View File

@ -1,30 +0,0 @@
import {it, inject, beforeEachProviders} from "@angular/core/testing";
import {BaseRequestOptions, Http} from "@angular/http";
import {MockBackend} from "@angular/http/testing";
import {provide} from "@angular/core";
import "rxjs/Rx";
import {AutoCompleteService} from "./autocomplete.service";
import {NetworkService} from "../../model/network/network.service";
describe('AutoCompleteService', () => {
beforeEachProviders(() => [
MockBackend,
BaseRequestOptions,
provide(Http, {
useFactory: (backend, options) => {
return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions]
}),
NetworkService,
AutoCompleteService
]);
it('placeholder test', inject([], () => {
expect(true).toBe(true);
}));
});

View File

@ -2,7 +2,7 @@
<form class="navbar-form" role="search" #SearchForm="ngForm"> <form class="navbar-form" role="search" #SearchForm="ngForm">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" placeholder="Search" (keyup)="onSearchChange($event)" <input type="text" class="form-control" placeholder="Search" (keyup)="onSearchChange($event)"
(blur)="onFocusLost($event)" (focus)="onFocus($evnet)" [(ngModel)]="searchText" #name="ngForm" (blur)="onFocusLost($event)" (focus)="onFocus($evnet)" [(ngModel)]="searchText" #name="ngModel"
ngControl="search" ngControl="search"
name="srch-term" id="srch-term" autocomplete="off"> name="srch-term" id="srch-term" autocomplete="off">
@ -11,10 +11,10 @@
<div class="autocomplete-item" *ngFor="let item of autoCompleteItems"> <div class="autocomplete-item" *ngFor="let item of autoCompleteItems">
<a [routerLink]="['Search',{searchText: item.text, type: SearchTypes[item.type]}]"> <a [routerLink]="['Search',{searchText: item.text, type: SearchTypes[item.type]}]">
<span [ngSwitch]="item.type"> <span [ngSwitch]="item.type">
<span *ngSwitchWhen="0" class="glyphicon glyphicon-picture"></span> <span *ngSwitchCase="0" class="glyphicon glyphicon-picture"></span>
<span *ngSwitchWhen="1" class="glyphicon glyphicon-folder-open"></span> <span *ngSwitchCase="1" class="glyphicon glyphicon-folder-open"></span>
<span *ngSwitchWhen="2" class="glyphicon glyphicon-tag"></span> <span *ngSwitchCase="2" class="glyphicon glyphicon-tag"></span>
<span *ngSwitchWhen="3" class="glyphicon glyphicon-map-marker"></span> <span *ngSwitchCase="3" class="glyphicon glyphicon-map-marker"></span>
</span> </span>
{{item.preText}}<strong>{{item.highLightText}}</strong>{{item.postText}} {{item.preText}}<strong>{{item.highLightText}}</strong>{{item.postText}}
</a> </a>

View File

@ -1,20 +1,16 @@
///<reference path="../../../browser.d.ts"/>
import {Component} from "@angular/core"; import {Component} from "@angular/core";
import {AutoCompleteService} from "./autocomplete.service"; import {AutoCompleteService} from "./autocomplete.service";
import {AutoCompleteItem, SearchTypes} from "../../../../common/entities/AutoCompleteItem"; import {AutoCompleteItem, SearchTypes} from "../../../../common/entities/AutoCompleteItem";
import {RouteParams, RouterLink} from "@angular/router-deprecated"; import {RouterLink, ActivatedRoute, Params} from "@angular/router";
import {Message} from "../../../../common/entities/Message"; import {Message} from "../../../../common/entities/Message";
import {GalleryService} from "../gallery.service"; import {GalleryService} from "../gallery.service";
import {FORM_DIRECTIVES} from "@angular/common";
import {Config} from "../../config/Config"; import {Config} from "../../config/Config";
@Component({ @Component({
selector: 'gallery-search', selector: 'gallery-search',
templateUrl: 'app/gallery/search/search.gallery.component.html', templateUrl: 'app/gallery/search/search.gallery.component.html',
styleUrls: ['app/gallery/search/search.gallery.component.css'], styleUrls: ['app/gallery/search/search.gallery.component.css'],
providers: [AutoCompleteService], providers: [AutoCompleteService, RouterLink]
directives: [FORM_DIRECTIVES, RouterLink]
}) })
export class GallerySearchComponent { export class GallerySearchComponent {
@ -23,13 +19,20 @@ export class GallerySearchComponent {
SearchTypes: any = []; SearchTypes: any = [];
constructor(private _autoCompleteService:AutoCompleteService, private _galleryService:GalleryService, private _params:RouteParams) { constructor(private _autoCompleteService: AutoCompleteService,
private _galleryService: GalleryService,
private _route: ActivatedRoute) {
this.SearchTypes = SearchTypes; this.SearchTypes = SearchTypes;
let searchText = this._params.get('searchText');
this._route.params
.subscribe((params: Params) => {
let searchText = params['searchText'];
if (searchText && searchText != "") { if (searchText && searchText != "") {
this.searchText = searchText; this.searchText = searchText;
} }
});
} }
onSearchChange(event: KeyboardEvent) { onSearchChange(event: KeyboardEvent) {
@ -60,17 +63,17 @@ export class GallerySearchComponent {
mouseOverAutoComplete: boolean = false; mouseOverAutoComplete: boolean = false;
public setMouseOverAutoComplete(value) { public setMouseOverAutoComplete(value: boolean) {
this.mouseOverAutoComplete = value; this.mouseOverAutoComplete = value;
} }
public onFocusLost(event) { public onFocusLost() {
if (this.mouseOverAutoComplete == false) { if (this.mouseOverAutoComplete == false) {
this.autoCompleteItems = []; this.autoCompleteItems = [];
} }
} }
public onFocus(event) { public onFocus() {
this.autocomplete(this.searchText); this.autocomplete(this.searchText);
} }

View File

@ -6,9 +6,9 @@
{{loginError}} {{loginError}}
</div> </div>
<input type="text" class="form-control" placeholder="Username" autofocus <input type="text" class="form-control" placeholder="Username" autofocus
[(ngModel)]="loginCredential.username" ngControl="name" #name="ngForm" required> [(ngModel)]="loginCredential.username" name="name" required>
<input type="password" class="form-control" placeholder="Password" <input type="password" class="form-control" placeholder="Password"
[(ngModel)]="loginCredential.password" ngControl="password" #name="ngForm" required> [(ngModel)]="loginCredential.password" name="password" required>
<br/> <br/>
<button class="btn btn-lg btn-primary btn-block" [disabled]="!LoginForm.form.valid" (click)="onLogin()">Sign in</button> <button class="btn btn-lg btn-primary btn-block" [disabled]="!LoginForm.form.valid" (click)="onLogin()">Sign in</button>
</form> </form>

View File

@ -1,10 +1,7 @@
///<reference path="../../browser.d.ts"/>
import {Component, OnInit} from "@angular/core"; import {Component, OnInit} from "@angular/core";
import {LoginCredential} from "../../../common/entities/LoginCredential"; import {LoginCredential} from "../../../common/entities/LoginCredential";
import {AuthenticationService} from "../model/network/authentication.service.ts"; import {AuthenticationService} from "../model/network/authentication.service";
import {Router} from "@angular/router-deprecated"; import {Router} from "@angular/router";
import {FORM_DIRECTIVES} from "@angular/common";
import {Message} from "../../../common/entities/Message"; import {Message} from "../../../common/entities/Message";
import {User} from "../../../common/entities/User"; import {User} from "../../../common/entities/User";
import {ErrorCodes} from "../../../common/entities/Error"; import {ErrorCodes} from "../../../common/entities/Error";
@ -13,11 +10,10 @@ import {ErrorCodes} from "../../../common/entities/Error";
selector: 'login', selector: 'login',
templateUrl: 'app/login/login.component.html', templateUrl: 'app/login/login.component.html',
styleUrls: ['app/login/login.component.css'], styleUrls: ['app/login/login.component.css'],
directives: [FORM_DIRECTIVES]
}) })
export class LoginComponent implements OnInit { export class LoginComponent implements OnInit {
loginCredential: LoginCredential; loginCredential: LoginCredential;
loginError = null; loginError: any = null;
constructor(private _authService: AuthenticationService, private _router: Router) { constructor(private _authService: AuthenticationService, private _router: Router) {
this.loginCredential = new LoginCredential(); this.loginCredential = new LoginCredential();
@ -25,7 +21,7 @@ export class LoginComponent implements OnInit {
ngOnInit() { ngOnInit() {
if (this._authService.isAuthenticated()) { if (this._authService.isAuthenticated()) {
this._router.navigate(['Gallery', {directory: "/"}]); this._router.navigate(['gallery', "/"]);
} }
} }

View File

@ -1,8 +1,5 @@
///<reference path="../../../browser.d.ts"/> import {inject, TestBed} from "@angular/core/testing";
import {UserService} from "./user.service";
import {it, inject, beforeEachProviders} from "@angular/core/testing";
import {provide} from "@angular/core";
import {UserService} from "./user.service.ts";
import {User} from "../../../../common/entities/User"; import {User} from "../../../../common/entities/User";
import {Message} from "../../../../common/entities/Message"; import {Message} from "../../../../common/entities/Message";
import "rxjs/Rx"; import "rxjs/Rx";
@ -16,10 +13,13 @@ class MockUserService {
} }
describe('AuthenticationService', () => { describe('AuthenticationService', () => {
beforeEachProviders(() => [ beforeEach(() => {
provide(UserService, {useClass: MockUserService}), TestBed.configureTestingModule({
AuthenticationService providers: [
]); {provide: UserService, useClass: MockUserService},
AuthenticationService]
});
});
it('should call User service login', inject([AuthenticationService, UserService], (authService, userService) => { it('should call User service login', inject([AuthenticationService, UserService], (authService, userService) => {

View File

@ -1,17 +1,15 @@
///<reference path="../../../browser.d.ts"/>
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {User, UserRoles} from "../../../../common/entities/User"; import {User, UserRoles} from "../../../../common/entities/User";
import {Event} from "../../../../common/event/Event"; import {Event} from "../../../../common/event/Event";
import {UserService} from "./user.service.ts"; import {UserService} from "./user.service";
import {LoginCredential} from "../../../../common/entities/LoginCredential"; import {LoginCredential} from "../../../../common/entities/LoginCredential";
import {Message} from "../../../../common/entities/Message"; import {Message} from "../../../../common/entities/Message";
import {Cookie} from "ng2-cookies/ng2-cookies"; import {Cookie} from "ng2-cookies";
import {ErrorCodes} from "../../../../common/entities/Error"; import {ErrorCodes} from "../../../../common/entities/Error";
import {Config} from "../../config/Config"; import {Config} from "../../config/Config";
declare module ServerInject { declare module ServerInject {
export var user; export let user: User;
} }
@Injectable() @Injectable()
@ -29,6 +27,8 @@ export class AuthenticationService {
this.setUser(ServerInject.user); this.setUser(ServerInject.user);
} }
this.getSessionUser(); this.getSessionUser();
} else {
this.OnUserChanged.trigger(this._user);
} }
} }
@ -52,7 +52,7 @@ export class AuthenticationService {
public login(credential: LoginCredential) { public login(credential: LoginCredential) {
return this._userService.login(credential).then((message: Message<User>) => { return this._userService.login(credential).then((message: Message<User>) => {
if (message.error) { if (message.error) {
console.log(ErrorCodes[message.error.code] + ", message: " + message.error.message); console.log(ErrorCodes[message.error.code] + ", message: ", message.error.message);
} else { } else {
this.setUser(message.result); this.setUser(message.result);
} }
@ -65,7 +65,7 @@ export class AuthenticationService {
if (Config.Client.authenticationRequired === false) { if (Config.Client.authenticationRequired === false) {
return true; return true;
} }
return (this._user && this._user != null) ? true : false; return !!(this._user && this._user != null);
} }
public getUser() { public getUser() {

View File

@ -1,9 +1,6 @@
///<reference path="../../../browser.d.ts"/> import {inject, TestBed} from "@angular/core/testing";
import {it, inject, beforeEachProviders, beforeEach, afterEach} from "@angular/core/testing";
import {BaseRequestOptions, Http, Response, ResponseOptions} from "@angular/http"; import {BaseRequestOptions, Http, Response, ResponseOptions} from "@angular/http";
import {MockBackend, MockConnection} from "@angular/http/testing"; import {MockBackend, MockConnection} from "@angular/http/testing";
import {provide} from "@angular/core";
import "rxjs/Rx"; import "rxjs/Rx";
import {NetworkService} from "./network.service"; import {NetworkService} from "./network.service";
import {Message} from "../../../../common/entities/Message"; import {Message} from "../../../../common/entities/Message";
@ -17,16 +14,22 @@ describe('NetworkService Success tests', () => {
let testResponse = "testResponse"; let testResponse = "testResponse";
let testResponseMessage = new Message(null, testResponse); let testResponseMessage = new Message(null, testResponse);
beforeEachProviders(() => [
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
MockBackend, MockBackend,
BaseRequestOptions, BaseRequestOptions,
provide(Http, { {
useFactory: (backend, options) => { provide: Http, useFactory: (backend, options) => {
return new Http(backend, options); return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions] }, deps: [MockBackend, BaseRequestOptions]
}), },
NetworkService NetworkService
]); ]
});
});
beforeEach(inject([MockBackend], (backend) => { beforeEach(inject([MockBackend], (backend) => {
@ -100,16 +103,20 @@ describe('NetworkService Fail tests', () => {
let testData = {data: "testData"}; let testData = {data: "testData"};
let testError = "testError"; let testError = "testError";
beforeEachProviders(() => [ beforeEach(() => {
TestBed.configureTestingModule({
providers: [
MockBackend, MockBackend,
BaseRequestOptions, BaseRequestOptions,
provide(Http, { {
useFactory: (backend, options) => { provide: Http, useFactory: (backend, options) => {
return new Http(backend, options); return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions] }, deps: [MockBackend, BaseRequestOptions]
}), },
NetworkService NetworkService
]); ]
});
});
beforeEach(inject([MockBackend], (backend) => { beforeEach(inject([MockBackend], (backend) => {

View File

@ -1,5 +1,3 @@
///<reference path="../../../browser.d.ts"/>
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {Http, Headers, RequestOptions} from "@angular/http"; import {Http, Headers, RequestOptions} from "@angular/http";
import {Message} from "../../../../common/entities/Message"; import {Message} from "../../../../common/entities/Message";
@ -19,7 +17,7 @@ export class NetworkService {
let options = new RequestOptions({headers: headers}); let options = new RequestOptions({headers: headers});
if (method == "get" || method == "delete") { if (method == "get" || method == "delete") {
return this._http[method](this._baseUrl + url, options) return <any>this._http[method](this._baseUrl + url, options)
.toPromise() .toPromise()
.then(res => <Message<any>> res.json()) .then(res => <Message<any>> res.json())
.catch(NetworkService.handleError); .catch(NetworkService.handleError);
@ -27,7 +25,7 @@ export class NetworkService {
return this._http[method](this._baseUrl + url, body, options) return this._http[method](this._baseUrl + url, body, options)
.toPromise() .toPromise()
.then(res => <Message<any>> res.json()) .then((res: any) => <Message<any>> res.json())
.catch(NetworkService.handleError); .catch(NetworkService.handleError);
} }

View File

@ -1,9 +1,6 @@
///<reference path="../../../browser.d.ts"/> import {inject, TestBed} from "@angular/core/testing";
import {it, inject, beforeEachProviders} from "@angular/core/testing";
import {BaseRequestOptions, Http} from "@angular/http"; import {BaseRequestOptions, Http} from "@angular/http";
import {MockBackend} from "@angular/http/testing"; import {MockBackend} from "@angular/http/testing";
import {provide} from "@angular/core";
import "rxjs/Rx"; import "rxjs/Rx";
import {NetworkService} from "./network.service"; import {NetworkService} from "./network.service";
import {UserService} from "./user.service"; import {UserService} from "./user.service";
@ -12,18 +9,19 @@ import {LoginCredential} from "../../../../common/entities/LoginCredential";
describe('UserService', () => { describe('UserService', () => {
beforeEach(() => {
beforeEachProviders(() => [ TestBed.configureTestingModule({
providers: [
MockBackend, MockBackend,
BaseRequestOptions, BaseRequestOptions,
provide(Http, { {
useFactory: (backend, options) => { provide: Http, useFactory: (backend, options) => {
return new Http(backend, options); return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions] }, deps: [MockBackend, BaseRequestOptions]
}), },
NetworkService, NetworkService,
UserService UserService]
]); });
it('should call postJson at login', inject([UserService, NetworkService], (userService, networkService) => { it('should call postJson at login', inject([UserService, NetworkService], (userService, networkService) => {
@ -43,3 +41,4 @@ describe('UserService', () => {
}); });
});

View File

@ -1,8 +1,6 @@
///<reference path="../../../browser.d.ts"/>
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {LoginCredential} from "../../../../common/entities/LoginCredential"; import {LoginCredential} from "../../../../common/entities/LoginCredential";
import {NetworkService} from "./network.service.ts"; import {NetworkService} from "./network.service";
import {User} from "../../../../common/entities/User"; import {User} from "../../../../common/entities/User";
import {Message} from "../../../../common/entities/Message"; import {Message} from "../../../../common/entities/Message";

View File

@ -52,10 +52,10 @@
<form (ngSubmit)="onSubmit()" #NewUserForm="ngForm"> <form (ngSubmit)="onSubmit()" #NewUserForm="ngForm">
<div class="modal-body"> <div class="modal-body">
<input type="text" class="form-control" placeholder="Username" autofocus <input type="text" class="form-control" placeholder="Username" autofocus
[(ngModel)]="newUser.name" ngControl="name" #name="ngForm" required> [(ngModel)]="newUser.name" name="name" required>
<input type="password" class="form-control" placeholder="Password" <input type="password" class="form-control" placeholder="Password"
[(ngModel)]="newUser.password" ngControl="password" #name="ngForm" required> [(ngModel)]="newUser.password" name="password" required>
<select class="form-control" [(ngModel)]="newUser.role" required> <select class="form-control" [(ngModel)]="newUser.role" name="role" required>
<option *ngFor="let repository of userRoles" [value]="repository.key">{{repository.value}} <option *ngFor="let repository of userRoles" [value]="repository.key">{{repository.value}}
</option> </option>
</select> </select>

View File

@ -1,23 +1,16 @@
///<reference path="../../../browser.d.ts"/>
import {Component, OnInit} from "@angular/core"; import {Component, OnInit} from "@angular/core";
import {AuthenticationService} from "../../model/network/authentication.service.ts"; import {AuthenticationService} from "../../model/network/authentication.service";
import {Router} from "@angular/router-deprecated"; import {Router} from "@angular/router";
import {FrameComponent} from "../../frame/frame.component";
import {User, UserRoles} from "../../../../common/entities/User"; import {User, UserRoles} from "../../../../common/entities/User";
import {FORM_DIRECTIVES} from "@angular/common";
import {Utils} from "../../../../common/Utils"; import {Utils} from "../../../../common/Utils";
import {Message} from "../../../../common/entities/Message"; import {Message} from "../../../../common/entities/Message";
import {StringifyRole} from "./../../pipes/StringifyRolePipe";
import {UserManagerSettingsService} from "./usermanager.settings.service"; import {UserManagerSettingsService} from "./usermanager.settings.service";
@Component({ @Component({
selector: 'settings-usermanager', selector: 'settings-usermanager',
templateUrl: 'app/settings/usermanager/usermanager.settings.component.html', templateUrl: 'app/settings/usermanager/usermanager.settings.component.html',
styleUrls: ['app/settings/usermanager/usermanager.settings.component.css'], styleUrls: ['app/settings/usermanager/usermanager.settings.component.css'],
directives: [FrameComponent, FORM_DIRECTIVES],
providers: [UserManagerSettingsService], providers: [UserManagerSettingsService],
pipes: [StringifyRole]
}) })
export class UserMangerSettingsComponent implements OnInit { export class UserMangerSettingsComponent implements OnInit {

View File

@ -1,30 +0,0 @@
import {it, inject, beforeEachProviders} from "@angular/core/testing";
import {BaseRequestOptions, Http} from "@angular/http";
import {MockBackend} from "@angular/http/testing";
import {provide} from "@angular/core";
import "rxjs/Rx";
import {NetworkService} from "../../model/network/network.service";
import {UserManagerSettingsService} from "./usermanager.settings.service";
describe('AdminService', () => {
beforeEachProviders(() => [
MockBackend,
BaseRequestOptions,
provide(Http, {
useFactory: (backend, options) => {
return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions]
}),
NetworkService,
UserManagerSettingsService
]);
it('placeholder test', inject([], () => {
expect(true).toBe(true);
}));
});

View File

@ -1,9 +1,6 @@
/// <reference path="../typings/index.d.ts"/>
/// <reference path="../common/common-classes.d.ts" /> /// <reference path="../common/common-classes.d.ts" />
/// <reference path="../node_modules/tslint/lib/tslint.d.ts" />
/// <reference path="../node_modules/@angular/core/index.d.ts" /> /// <reference path="../node_modules/@angular/core/index.d.ts" />
/// <reference path="../node_modules/@angular/common/index.d.ts" /> /// <reference path="../node_modules/@angular/common/index.d.ts" />
/// <reference path="../node_modules/@angular/router/index.d.ts" /> /// <reference path="../node_modules/@angular/router/index.d.ts" />
/// <reference path="../node_modules/@angular/router-deprecated/index.d.ts" />
/// <reference path="../node_modules/zone.js/dist/zone.js.d.ts"/> /// <reference path="../node_modules/zone.js/dist/zone.js.d.ts"/>

View File

@ -9,11 +9,14 @@
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7"
crossorigin="anonymous"> crossorigin="anonymous">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<body style="overflow-y: scroll">
<pi-gallery2-app>Loading...</pi-gallery2-app>
</body>
<script> <script>
var ServerInject = { var ServerInject = {
user: <%- JSON.stringify(user); %>, user: <%- JSON.stringify(user); %>,
@ -21,14 +24,16 @@
} }
</script> </script>
<script
src="https://code.jquery.com/jquery-2.2.3.min.js"
integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
crossorigin="anonymous"></script>
<script src="https://code.angularjs.org/2.0.0-beta.17/angular2-polyfills.js"></script> <script src="systemjs.config.js"></script>
<script src="dist/app-bundle.js"></script> <script>
System.import('').catch(function (err) {
console.error(err);
});
</script>
</head>
<body style="overflow-y: scroll">
<pi-gallery2-app>Loading...</pi-gallery2-app>
</body>
</html> </html>

View File

@ -1,8 +1,5 @@
///<reference path="./browser.d.ts"/> import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
import {AppModule} from "./app/app.module";
import {bootstrap} from "@angular/platform-browser-dynamic"; platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err));
import {AppComponent} from "./app/app.component.ts";
bootstrap(AppComponent)
.catch(err => console.error(err));

View File

@ -0,0 +1,11 @@
/**
* Add barrels and stuff
* Adjust as necessary for your application needs.
*/
// (function (global) {
// System.config({
// packages: {
// // add packages here
// }
// });
// })(this);

View File

@ -0,0 +1,41 @@
/**
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: '',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'ng2-cookies': 'npm:ng2-cookies/ng2-cookies'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
}
}
});
})(this);

View File

@ -1,14 +1,15 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"sourceMap": true,
"module": "commonjs", "module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true "experimentalDecorators": true,
}, "lib": [
"exclude": [ "es2015",
"node_modules", "dom"
"typings/main.d.ts", ],
"typings/main" "suppressImplicitAnyIndexErrors": true
] }
} }

View File

@ -1,44 +0,0 @@
var webpack = require('webpack');
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
var path = require("path");
module.exports = {
entry: {
'app': path.join(__dirname,'/main.ts')
},
output: {
filename: path.join(__dirname,'/dist/[name]-bundle.js'),
library: ['peer']
},
// Turn on sourcemaps
devtool: 'source-map',
resolve: {
extensions: ['', '.webpack.js', '.web.js', '.ts', '.js'],
modulesDirectories: [
'node_modules',
'lib'
]
},
// Add minification
plugins: [
],
module: {
loaders: [
// Support for .ts files.
{ test: /\.ts$/, loader: 'ts-loader', exclude: [ /\.(spec|e2e)\.ts$/ ] },
// Support for *.json files.
{ test: /\.json$/, loader: 'json-loader' },
// Support for CSS as raw text
{ test: /\.css$/, loader: 'raw-loader' },
// support for .html as raw text
{ test: /\.html$/, loader: 'raw-loader', exclude: [ 'index.html' ] }
]
}
};

98
karma-test-shim.js Normal file
View File

@ -0,0 +1,98 @@
// /*global jasmine, __karma__, window*/
Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing.
// Uncomment to get full stacktrace output. Sometimes helpful, usually not.
// Error.stackTraceLimit = Infinity; //
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
// builtPaths: root paths for output ("built") files
// get from karma.config.js, then prefix with '/base/' (default is 'app/')
var builtPaths = (__karma__.config.builtPaths || ['app/'])
.map(function (p) {
return '/base/' + p;
});
__karma__.loaded = function () {
};
function isJsFile(path) {
return path.slice(-3) == '.js';
}
function isSpecFile(path) {
return /\.spec\.(.*\.)?js$/.test(path);
}
// Is a "built" file if is JavaScript file in one of the "built" folders
function isBuiltFile(path) {
return isJsFile(path) &&
builtPaths.reduce(function (keep, bp) {
return keep || (path.substr(0, bp.length) === bp);
}, false);
}
var allSpecFiles = Object.keys(window.__karma__.files)
.filter(isSpecFile)
.filter(isBuiltFile);
System.config({
baseURL: 'base',
// Extend usual application package list with test folder
packages: {'testing': {main: 'index.js', defaultExtension: 'js'}},
// Assume npm: is set in `paths` in systemjs.config
// Map the angular testing umd bundles
map: {
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
'@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
},
});
System.import('frontend/systemjs.config.js')
.then(importSystemJsExtras)
.then(initTestBed)
.then(initTesting);
/** Optional SystemJS configuration extras. Keep going w/o it */
function importSystemJsExtras() {
return System.import('frontend/systemjs.config.extras.js')
.catch(function (reason) {
console.log(
'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.'
);
console.log(reason);
});
}
function initTestBed() {
return Promise.all([
System.import('@angular/core/testing'),
System.import('@angular/platform-browser-dynamic/testing')
])
.then(function (providers) {
var coreTesting = providers[0];
var browserTesting = providers[1];
coreTesting.TestBed.initTestEnvironment(
browserTesting.BrowserDynamicTestingModule,
browserTesting.platformBrowserDynamicTesting());
})
}
// Import all spec files and start karma
function initTesting() {
return Promise.all(
allSpecFiles.map(function (moduleName) {
return System.import(moduleName);
})
)
.then(__karma__.start, __karma__.error);
}

View File

@ -1,66 +1,104 @@
var testWebpackConfig = require('./test/webpack.test.config.js');
module.exports = function(config) { module.exports = function(config) {
var appBase = 'frontend/'; // transpiled app JS and map files
var appSrcBase = 'frontend/'; // app source TS files
var commonBase = 'common/'; // transpiled app JS and map files
var commonSrcBase = 'common/'; // app source TS files
var appAssets = 'base/'; // component assets fetched by Angular's compiler
// Testing helpers (optional) are conventionally in a folder called `testing`
var testingBase = 'testing/'; // transpiled test JS and map files
var testingSrcBase = 'testing/'; // test source TS files
config.set({ config.set({
basePath: '',
// base path that will be used to resolve all patterns (e.g. files, exclude)
basePath: './test',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'], frameworks: ['jasmine'],
// list of files to exclude plugins: [
exclude: [ ], require('karma-jasmine'),
require('karma-phantomjs-launcher'),
// list of files / patterns to load in the browser require('karma-jasmine-html-reporter')
// we are building the test environment in ./spec-bundle.js
files: [ { pattern: 'spec-bundle.js', watched: false } ],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {'spec-bundle.js': ['coverage', 'webpack', 'sourcemap']},
// Webpack Config at ./webpack.test.config.js
webpack: testWebpackConfig,
coverageReporter: {
type: 'lcov', // lcov or lcovonly are required for generating lcov.info files
dir: 'coverage/'
},
// Webpack please don't spam the console when running in karma!
webpackServer: { noInfo: true },
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: [ 'mocha', 'coverage', 'coveralls' ],
// web server PORT
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: [
// 'Chrome',
'PhantomJS'
], ],
// Continuous Integration mode client: {
// if true, Karma captures browsers, runs the tests and exits builtPaths: [appBase, commonBase, testingBase], // add more spec base paths as needed
singleRun: true clearContext: false // leave Jasmine Spec Runner output visible in browser
}); },
};
files: [
// System.js for module loading
'node_modules/systemjs/dist/system-polyfills.js',
'node_modules/systemjs/dist/system.src.js',
// Polyfills
'node_modules/core-js/client/shim.js',
'node_modules/reflect-metadata/Reflect.js',
// zone.js
'node_modules/zone.js/dist/zone.js',
'node_modules/zone.js/dist/long-stack-trace-zone.js',
'node_modules/zone.js/dist/proxy.js',
'node_modules/zone.js/dist/sync-test.js',
'node_modules/zone.js/dist/jasmine-patch.js',
'node_modules/zone.js/dist/async-test.js',
'node_modules/zone.js/dist/fake-async-test.js',
// RxJs
{pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false},
{pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false},
//Other libs
{pattern: 'node_modules/ng2-cookies/**/*.js', included: false, watched: false},
// Paths loaded via module imports:
// Angular itself
{pattern: 'node_modules/@angular/**/*.js', included: false, watched: false},
{pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false},
{pattern: 'systemjs.config.js', included: false, watched: false},
{pattern: 'systemjs.config.extras.js', included: false, watched: false},
'karma-test-shim.js', // optionally extend SystemJS mapping e.g., with barrels
// transpiled application & spec code paths loaded via module imports
{pattern: appBase + '**/*.js', included: false, watched: true},
{pattern: commonBase + '**/*.js', included: false, watched: true},
{pattern: testingBase + '**/*.js', included: false, watched: true},
// Asset (HTML & CSS) paths loaded via Angular's component compiler
// (these paths need to be rewritten, see proxies section)
{pattern: appBase + '**/*.html', included: false, watched: true},
{pattern: appBase + '**/*.css', included: false, watched: true},
{pattern: commonBase + '**/*.html', included: false, watched: true},
{pattern: commonBase + '**/*.css', included: false, watched: true},
// Paths for debugging with source maps in dev tools
{pattern: appSrcBase + '**/*.ts', included: false, watched: false},
{pattern: commonSrcBase + '**/*.ts', included: false, watched: false},
{pattern: appBase + '**/*.js.map', included: false, watched: false},
{pattern: commonBase + '**/*.js.map', included: false, watched: false},
{pattern: testingSrcBase + '**/*.ts', included: false, watched: false},
{pattern: testingBase + '**/*.js.map', included: false, watched: false}
],
// Proxied base paths for loading assets
proxies: {
// required for component assets fetched by Angular's compiler
"/app/": appAssets
},
exclude: [],
preprocessors: {},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['PhantomJS'],
singleRun: false
})
}

View File

@ -8,9 +8,9 @@
"license": "MIT", "license": "MIT",
"main": "./backend/server.js", "main": "./backend/server.js",
"scripts": { "scripts": {
"postinstall": "typings install && tsc -p backend && tsc -p test/backend && tsc -p common && webpack --config ./frontend/webpack.config.js -p", "postinstall": "tsc -p frontend && tsc -p backend && tsc -p test/backend && tsc -p common",
"pretest": "typings install && tsc -p test/backend", "pretest": "tsc -p frontend && tsc -p backend && tsc -p test/backend",
"test": "karma start ./karma.conf.js && mocha --recursive test/backend/unit", "test": "karma start karma.conf.js --single-run && mocha --recursive test/backend/unit",
"start": "node ./backend/server" "start": "node ./backend/server"
}, },
"repository": { "repository": {
@ -21,70 +21,58 @@
"url": "https://github.com/bpatrik/PiGallery2/issues" "url": "https://github.com/bpatrik/PiGallery2/issues"
}, },
"dependencies": { "dependencies": {
"@angular/common": "2.0.0-rc.4", "@angular/common": "~2.4.1",
"@angular/compiler": "2.0.0-rc.4", "@angular/compiler": "~2.4.1",
"@angular/core": "2.0.0-rc.4", "@angular/core": "~2.4.1",
"@angular/forms": "^0.2.0", "@angular/forms": "~2.4.1",
"@angular/http": "2.0.0-rc.4", "@angular/http": "~2.4.1",
"@angular/platform-browser": "2.0.0-rc.4", "@angular/platform-browser": "~2.4.1",
"@angular/platform-browser-dynamic": "2.0.0-rc.4", "@angular/platform-browser-dynamic": "~2.4.1",
"@angular/platform-server": "2.0.0-rc.4", "@angular/platform-server": "~2.4.1",
"@angular/router": "3.0.0-beta.2", "@angular/router": "~3.4.1",
"@angular/router-deprecated": "2.0.0-rc.2", "systemjs": "0.19.41",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.9",
"rxjs": "^5.0.2",
"zone.js": "^0.7.4",
"body-parser": "^1.15.2", "body-parser": "^1.15.2",
"chai": "^3.5.0", "debug": "^2.5.2",
"compression-webpack-plugin": "^0.3.0", "ejs": "^2.5.5",
"core-js": "^2.4.0",
"css-loader": "^0.23.1",
"debug": "^2.2.0",
"ejs": "^2.4.2",
"es6-promise-loader": "^1.0.1",
"exif-parser": "^0.1.9", "exif-parser": "^0.1.9",
"exports-loader": "^0.6.3",
"expose-loader": "^0.7.1",
"express": "^4.14.0", "express": "^4.14.0",
"express-session": "^1.14.0", "express-session": "^1.14.2",
"file-loader": "^0.8.5",
"flat-file-db": "^1.0.0", "flat-file-db": "^1.0.0",
"html-webpack-plugin": "^2.22.0", "jimp": "^0.2.27",
"ie-shim": "^0.1.0",
"imports-loader": "^0.6.5",
"istanbul-instrumenter-loader": "^0.2.0",
"jasmine-core": "^2.4.1",
"jimp": "^0.2.24",
"json-loader": "^0.5.4",
"karma": "^0.13.21",
"karma-coverage": "^1.0.0",
"karma-coveralls": "^1.1.2",
"karma-jasmine": "^1.0.2",
"karma-mocha-reporter": "^2.0.4",
"karma-phantomjs-launcher": "^1.0.1",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "1.7.0",
"mime": "^1.3.4", "mime": "^1.3.4",
"mocha": "^2.5.3", "mocha": "^3.2.0",
"morgan": "^1.7.0", "morgan": "^1.7.0",
"ng2-cookies": "^0.1.9", "ng2-cookies": "^1.0.4",
"ng2lint": "0.0.10",
"node-iptc": "^1.0.4", "node-iptc": "^1.0.4",
"optimist": "^0.6.1", "optimist": "^0.6.1"
"phantomjs-prebuilt": "^2.1.7", },
"protractor": "^3.2.2", "devDependencies": {
"raw-loader": "0.5.1", "@types/express": "^4.0.34",
"remap-istanbul": "^0.6.4", "@types/express-session": "0.0.32",
"rimraf": "^2.5.2", "@types/jasmine": "^2.5.38",
"rxjs": "5.0.0-beta.6", "@types/node": "^6.0.46",
"source-map-loader": "^0.1.5", "@types/optimist": "0.0.29",
"style-loader": "^0.13.0", "angular-cli": "^1.0.0-beta.24",
"ts-helpers": "1.1.1", "chai": "^3.5.0",
"ts-loader": "^0.8.2", "jasmine-core": "^2.5.2",
"tslint": "^3.13.0", "karma": "1.2.0",
"tslint-loader": "^2.1.5", "karma-cli": "^1.0.1",
"typedoc": "^0.4.4", "karma-jasmine": "^1.0.2",
"typescript": "^1.8.10", "karma-jasmine-html-reporter": "^0.2.2",
"typings": "^1.3.1", "karma-phantomjs-launcher": "^1.0.2",
"url-loader": "^0.5.7", "karma-remap-istanbul": "^0.2.1",
"webpack": "^1.13.1", "karma-systemjs": "^0.16.0",
"zone.js": "^0.6.12" "mocha": "^3.2.0",
"phantomjs-prebuilt": "^2.1.14",
"protractor": "^4.0.14",
"remap-istanbul": "^0.8.4",
"rimraf": "^2.5.4",
"ts-helpers": "^1.1.2",
"tslint": "^4.2.0",
"typescript": "^2.1.4"
} }
} }

View File

@ -1,87 +0,0 @@
var path = require('path');
// Webpack Plugins
var ProvidePlugin = require('webpack/lib/ProvidePlugin');
var DefinePlugin = require('webpack/lib/DefinePlugin');
var ENV = process.env.ENV = process.env.NODE_ENV = 'test';
/*
* Config
*/
module.exports = {
devtool: 'inline-source-map',
resolve: {
extensions: ['', '.ts', '.js']
},
module: {
preLoaders: [
{
test: /\.ts$/,
loader: 'tslint-loader',
exclude: [
root('node_modules')
]
},
{
test: /\.js$/,
loader: "source-map-loader",
exclude: [
root('node_modules/rxjs')
]
}
],
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader',
query: {
"compilerOptions": {
"removeComments": true
}
},
exclude: [ /\.e2e\.ts$/ ]
},
{ test: /\.json$/, loader: 'json-loader', exclude: [ root('frontend/index.ejs') ] },
{ test: /\.html$/, loader: 'raw-loader', exclude: [ root('frontend/index.ejs') ] },
{ test: /\.css$/, loader: 'raw-loader', exclude: [ root('frontend/index.ejs') ] }
],
postLoaders: [
// instrument only testing sources with Istanbul
{
test: /\.(js|ts)$/,
include: root('frontend'),
loader: 'istanbul-instrumenter-loader',
exclude: [
/\.(e2e|spec)\.ts$/,
/node_modules/
]
}
]
},
plugins: [
// Environment helpers
new DefinePlugin({
'ENV': JSON.stringify(ENV),
'HMR': false
})
],
node: {
global: 'window',
progress: false,
crypto: 'empty',
module: false,
clearImmediate: false,
setImmediate: false
},
tslint: {
emitErrors: false,
failOnHint: false,
resourcePath: 'src'
}
};
function root(args) {
args = Array.prototype.slice.call(arguments, 0);
return path.join.apply(path, [__dirname+"/../"].concat(args));
}

View File

@ -1,14 +1,15 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"sourceMap": true,
"module": "commonjs", "module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true "experimentalDecorators": true,
}, "lib": [
"exclude": [ "es2015",
"node_modules", "dom"
"typings/main.d.ts", ],
"typings/main" "suppressImplicitAnyIndexErrors": true
] }
} }

View File

@ -1,17 +0,0 @@
{
"name": "PiGallery2",
"version": false,
"globalDependencies": {
"body-parser": "registry:dt/body-parser#0.0.0+20160619023215",
"chai": "registry:dt/chai#3.4.0+20160601211834",
"core-js": "registry:dt/core-js#0.0.0+20160602141332",
"debug": "github:DefinitelyTyped/DefinitelyTyped/debug/debug.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"express": "github:DefinitelyTyped/DefinitelyTyped/express/express.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"express-session": "registry:dt/express-session#0.0.0+20160331200931",
"jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#d22516f9f089de107d7e7d5938566377370631f6",
"mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"optimist": "registry:dt/optimist#0.0.0+20160316171810",
"serve-static": "github:DefinitelyTyped/DefinitelyTyped/serve-static/serve-static.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e"
}
}