1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-25 02:04:15 +02:00

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

@ -2,12 +2,12 @@ import * as path from "path";
import {Config} from "./config/Config";
class ProjectPathClass {
public Root:string;
public ImageFolder:string;
public ThumbnailFolder:string;
public Root: string;
public ImageFolder: string;
public ThumbnailFolder: string;
isAbsolutePath(pathStr) {
return path.resolve(pathStr) === path.normalize(pathStr).replace(RegExp(pathStr.sep + '$'), '');
isAbsolutePath(pathStr: string) {
return path.resolve(pathStr) === path.normalize(pathStr);
}
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 "./../../backend/config/ConfigLoader";
import {ConfigLoader} from "./ConfigLoader";
import * as path from "path";
import {ConfigClass, DatabaseType} from "../../common/config/Config";
export var Config = new ConfigClass();
export let Config = new ConfigClass();
Config.Server = {
port: 80,

View File

@ -3,16 +3,16 @@ import * as optimist from "optimist";
export class ConfigLoader {
static init(configObject:any, configFilePath?:string, envAlias:Array<Array<string>> = []) {
static init(configObject: any, configFilePath?: string, envAlias: Array<Array<string>> = []) {
this.processConfigFile(configFilePath, configObject);
this.processArguments(configObject);
this.processEnvVariables(configObject, envAlias);
}
private static processEnvVariables(configObject:any, envAlias:Array<Array<string>>) {
private static processEnvVariables(configObject: any, envAlias: Array<Array<string>>) {
let varAliases = {};
envAlias.forEach((alias)=> {
envAlias.forEach((alias) => {
if (process.env[alias[0]]) {
varAliases[alias[1]] = process.env[alias[0]];
}
@ -21,24 +21,25 @@ export class ConfigLoader {
this.loadObject(configObject, process.env);
};
private static processArguments(configObject:any) {
private static processArguments(configObject: any) {
let argv = optimist.argv;
delete(argv._);
delete(argv.$0);
this.processHierarchyVar(configObject, argv);
};
private static processHierarchyVar(configObject:any, vars:any) {
private static processHierarchyVar(configObject: any, vars: any) {
let config = {};
Object.keys(vars).forEach((key)=> {
Object.keys(vars).forEach((key) => {
let keyArray = key.split("-");
let value = vars[key];
//recursive settings
let setObject = (object, keyArray, value) => {
let setObject = (object: any, keyArray: Array<string>, value: any): void => {
let key = keyArray.shift();
object[key] = {};
object[key] = object[key] || {};
if (keyArray.length == 0) {
//convert to boolean
@ -48,6 +49,7 @@ export class ConfigLoader {
if (value.toLowerCase && value.toLowerCase() === "true") {
value = true;
}
object[key] = value;
return;
}
@ -57,10 +59,11 @@ export class ConfigLoader {
setObject(config, keyArray, value);
});
this.loadObject(configObject, config);
}
private static processConfigFile(configFilePath:string, configObject:any) {
private static processConfigFile(configFilePath: string, configObject: any) {
if (typeof configFilePath !== 'undefined') {
if (ConfigLoader.loadConfigFile(configFilePath, configObject) === false) {
ConfigLoader.saveConfigFile(configFilePath, configObject);
@ -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) {
return false;
}
@ -84,7 +87,7 @@ export class ConfigLoader {
}
private static saveConfigFile(configFilePath, configObject) {
private static saveConfigFile(configFilePath: string, configObject: any) {
try {
fs.writeFileSync(configFilePath, JSON.stringify(configObject, null, 4));
} catch (err) {
@ -92,8 +95,8 @@ export class ConfigLoader {
}
}
private static loadObject(targetObject, sourceObject) {
Object.keys(sourceObject).forEach((key)=> {
private static loadObject(targetObject: any, sourceObject: any) {
Object.keys(sourceObject).forEach((key) => {
if (typeof targetObject[key] === "undefined") {
return;
}

View File

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

View File

@ -1,6 +1,4 @@
///<reference path="exif.d.ts"/>
import * as fs from "fs";
import * as path from "path";
import * as mime from "mime";
@ -18,7 +16,7 @@ import {
import {ProjectPath} from "../ProjectPath";
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");
let directoryName = path.basename(relativeDirectoryName);
let directoryParent = path.join(path.dirname(relativeDirectoryName), "/");
@ -26,7 +24,7 @@ export class DiskManager {
let directory = new Directory(1, directoryName, directoryParent, new Date(), [], []);
let promises:Array< Promise<any> > = [];
let promises: Array< Promise<any> > = [];
fs.readdir(absoluteDirectoryName, function (err, list) {
if (err) {
@ -44,7 +42,7 @@ export class DiskManager {
if (DiskManager.isImage(fullFilePath)) {
let promise = DiskManager.loadPhotoMetadata(fullFilePath).then((photoMetadata)=> {
let promise = DiskManager.loadPhotoMetadata(fullFilePath).then((photoMetadata) => {
directory.photos.push(new Photo(1, file, directory, photoMetadata));
});
@ -52,14 +50,14 @@ export class DiskManager {
}
}
Promise.all(promises).then(()=> {
Promise.all(promises).then(() => {
return cb(err, directory);
});
});
}
private static isImage(fullPath) {
private static isImage(fullPath: string) {
let imageMimeTypes = [
'image/bmp',
'image/gif',
@ -72,7 +70,7 @@ export class DiskManager {
'image/x-windows-bmp'
];
var extension = mime.lookup(fullPath);
let extension = mime.lookup(fullPath);
if (imageMimeTypes.indexOf(extension) !== -1) {
return true;
@ -113,8 +111,8 @@ export class DiskManager {
}
};*/
private static loadPhotoMetadata(fullPath):Promise<PhotoMetadata> {
return new Promise<PhotoMetadata>((resolve:(metadata:PhotoMetadata)=>void, reject) => {
private static loadPhotoMetadata(fullPath: string): Promise<PhotoMetadata> {
return new Promise<PhotoMetadata>((resolve: (metadata: PhotoMetadata) => void, reject) => {
fs.readFile(fullPath, function (err, data) {
if (err) {
reject(err);
@ -122,8 +120,8 @@ export class DiskManager {
let exif = exif_parser.create(data).parse();
let iptcData = iptc(data);
let imageSize:ImageSize = {width: exif.imageSize.width, height: exif.imageSize.height};
let cameraData:CameraMetadata = {
let imageSize: ImageSize = {width: exif.imageSize.width, height: exif.imageSize.height};
let cameraData: CameraMetadata = {
ISO: exif.tags.ISO,
model: exif.tags.Modeol,
maker: exif.tags.Make,
@ -132,14 +130,14 @@ export class DiskManager {
focalLength: exif.tags.FocalLength,
lens: exif.tags.LensModel,
};
let GPS:GPSMetadata = {
let GPS: GPSMetadata = {
latitude: exif.tags.GPSLatitude,
longitude: exif.tags.GPSLongitude,
altitude: exif.tags.GPSAltitude
};
let positionData:PositionMetaData = {
let positionData: PositionMetaData = {
GPSData: GPS,
country: iptcData.country_or_primary_location_name,
state: iptcData.province_or_state,
@ -147,24 +145,21 @@ export class DiskManager {
};
//Decode characters to UTF8
let decode = (s)=> {
for (var a, b, i = -1, l = (s = s.split("")).length, o = String.fromCharCode, c = "charCodeAt"; ++i < l;
let decode = (s: any) => {
for (let a, b, i = -1, l = (s = s.split("")).length, o = String.fromCharCode, c = "charCodeAt"; ++i < l;
((a = s[i][c](0)) & 0x80) &&
(s[i] = (a & 0xfc) == 0xc0 && ((b = s[i + 1][c](0)) & 0xc0) == 0x80 ?
o(((a & 0x03) << 6) + (b & 0x3f)) : o(128), s[++i] = "")
);
return s.join("");
};
let keywords:[string] = iptcData.keywords.map(s => decode(s));
let creationDate:Date = iptcData.date_time;
let keywords: [string] = iptcData.keywords.map((s: string) => decode(s));
let creationDate: Date = iptcData.date_time;
console.log(keywords);
let metadata:PhotoMetadata = new PhotoMetadata(keywords, cameraData, positionData, imageSize, creationDate);
let metadata: PhotoMetadata = new PhotoMetadata(keywords, cameraData, positionData, imageSize, creationDate);
resolve(metadata);
}
});

View File

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

View File

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

View File

@ -5,7 +5,7 @@ import {DiskManager} from "../DiskManger";
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);
}

View File

@ -5,15 +5,15 @@ import {SearchResult} from "../../../common/entities/SearchResult";
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");
}
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");
}
instantSearch(text, cb:(error:any, result:SearchResult) => void) {
instantSearch(text: string, cb: (error: any, result: SearchResult) => void) {
throw new Error("not implemented");
}

View File

@ -1,6 +1,4 @@
///<reference path="flat-file-db.ts"/>
import {User, UserRoles} from "../../../common/entities/User";
import {IUserManager} from "../IUserManager";
import {ProjectPath} from "../../ProjectPath";
@ -10,9 +8,9 @@ import * as path from "path";
export class UserManager implements IUserManager {
private db:any = null;
private db: any = null;
generateId():string {
generateId(): string {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
@ -43,8 +41,8 @@ export class UserManager implements IUserManager {
}
public findOne(filter, cb:(error:any, result:User) => void) {
this.find(filter, (error, result:Array<User>)=> {
public findOne(filter: any, cb: (error: any, result: User) => void) {
this.find(filter, (error, result: Array<User>) => {
if (error) {
return cb(error, null);
}
@ -56,14 +54,14 @@ 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);
}
public createUser(user:User, cb:(error:any, result:User) => void = (e, r) => {
public createUser(user: User, cb: (error: any, result: User) => void = (e, r) => {
}) {
user.id = parseInt(this.db.get("idCounter")) + 1;
this.db.put("idCounter", user.id);
@ -74,15 +72,15 @@ export class UserManager implements IUserManager {
return cb(null, user);
}
public deleteUser(id:number, cb:(error:any) => void) {
let users = this.db.get("users").filter((u) => u.id != id);
public deleteUser(id: number, cb: (error: any) => void) {
let users = this.db.get("users").filter((u: User) => u.id != id);
this.db.put("users", users);
return cb(null);
}
public changeRole(id:number, newRole:UserRoles, cb:(error:any, result:string) => void) {
public changeRole(id: number, newRole: UserRoles, cb: (error: any, result: string) => void) {
let users:Array<User> = this.db.get("users");
let users: Array<User> = this.db.get("users");
for (let i = 0; i < users.length; i++) {
if (users[i].id == id) {
@ -93,7 +91,7 @@ export class UserManager implements IUserManager {
this.db.put("users", users);
}
public changePassword(request:any, cb:(error:any, result:string) => void) {
public changePassword(request: any, cb: (error: any, result: string) => void) {
throw new Error("not implemented"); //TODO: implement
}

View File

@ -1,13 +1,13 @@
declare module "flat-file-db" {
export function sync(path:string):DB;
export function sync(path: string): DB;
}
declare interface DB {
sync();
put();
get();
del();
has();
keys();
close();
sync(): any;
put(): any;
get(): any;
del(): any;
has(): any;
keys(): any;
close(): any;
}

View File

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

View File

@ -1,10 +1,10 @@
///<reference path="../../typings/index.d.ts"/>
import {RenderingMWs} from "../middlewares/RenderingMWs";
import {Error, ErrorCodes} from "../../common/entities/Error";
import Request = Express.Request;
import Response = Express.Response;
export class ErrorRouter {
constructor(private app) {
constructor(private app: any) {
this.addApiErrorHandler();
this.addGenericHandler();
@ -17,7 +17,7 @@ export class ErrorRouter {
};
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
console.error(err.stack);

View File

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

View File

@ -1,5 +1,3 @@
///<reference path="../../typings/index.d.ts"/>
import * as _express from "express";
import {NextFunction, Request, Response} from "express";
import * as _path from "path";
@ -24,8 +22,9 @@ export class PublicRouter {
this.app.use(_express.static(_path.resolve(__dirname, './../../frontend')));
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);
};

View File

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

View File

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

View File

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

View File

@ -1,11 +1,11 @@
export class Utils {
static clone<T>(object:T):T {
static clone<T>(object: T): T {
return JSON.parse(JSON.stringify(object));
}
static equalsFilter(object:any, filter:any):boolean {
static equalsFilter(object: any, filter: any): boolean {
let keys = Object.keys(filter);
for (let i = 0; i < keys.length; i++) {
@ -19,7 +19,7 @@ export class Utils {
}
static concatUrls(...args:Array<string>) {
static concatUrls(...args: Array<string>) {
let url = "";
for (let i = 0; i < args.length; i++) {
if (args[i] === "" || typeof args[i] === "undefined") continue;
@ -34,8 +34,8 @@ export class Utils {
return url.substring(0, url.length - 1);
}
public static updateKeys(targetObject, sourceObject) {
Object.keys(sourceObject).forEach((key)=> {
public static updateKeys(targetObject: any, sourceObject: any) {
Object.keys(sourceObject).forEach((key) => {
if (typeof targetObject[key] === "undefined") {
return;
}
@ -47,8 +47,8 @@ export class Utils {
});
}
public static setKeys(targetObject, sourceObject) {
Object.keys(sourceObject).forEach((key)=> {
public static setKeys(targetObject: any, sourceObject: any) {
Object.keys(sourceObject).forEach((key) => {
if (typeof targetObject[key] === "object") {
Utils.setKeys(targetObject[key], sourceObject[key]);
} else {
@ -57,8 +57,8 @@ export class Utils {
});
}
public static setKeysForced(targetObject, sourceObject) {
Object.keys(sourceObject).forEach((key)=> {
public static setKeysForced(targetObject: any, sourceObject: any) {
Object.keys(sourceObject).forEach((key) => {
if (typeof sourceObject[key] === "object") {
if (typeof targetObject[key] === "undefined") {
targetObject[key] = {};
@ -70,8 +70,8 @@ export class Utils {
});
}
public static enumToArray(EnumType):Array<{key:number;value:string;}> {
let arr:Array<{key:number;value:string;}> = [];
public static enumToArray(EnumType: any): Array<{key: number;value: string;}> {
let arr: Array<{key: number;value: string;}> = [];
for (let enumMember in EnumType) {
if (!EnumType.hasOwnProperty(enumMember)) {
continue;
@ -85,12 +85,12 @@ export class Utils {
}
public static findClosest(number:number, arr:Array<number>) {
public static findClosest(number: number, arr: Array<number>) {
let curr = arr[0];
let diff = Math.abs(number - curr);
arr.forEach((value)=> {
arr.forEach((value) => {
let newDiff = Math.abs(number - value);

View File

@ -1,19 +1,19 @@
function isFunction(functionToCheck) {
var getType = {};
function isFunction(functionToCheck: any) {
let getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}
export class Event<T> {
private handlers: { (data?: T): void; }[] = [];
private handlers: {(data?: T): void;}[] = [];
public on(handler: { (data?: T): void }) {
if(!isFunction(handler)){
public on(handler: {(data?: T): void}) {
if (!isFunction(handler)) {
throw new Error("Handler is not a function");
}
this.handlers.push(handler);
}
public off(handler: { (data?: T): void }) {
public off(handler: {(data?: T): void}) {
this.handlers = this.handlers.filter(h => h !== handler);
}

View File

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

View File

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

View File

@ -1,83 +1,29 @@
///<reference path="../browser.d.ts"/>
import {Component, OnInit} from "@angular/core";
import {LoginComponent} from "./login/login.component";
import {AuthenticationService} from "./model/network/authentication.service.ts";
import {GalleryComponent} from "./gallery/gallery.component";
import {AuthenticationService} from "./model/network/authentication.service";
import {User} from "../../common/entities/User";
import {Router, RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from "@angular/router-deprecated";
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";
import {Router} from "@angular/router";
@Component({
selector: 'pi-gallery2-app',
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 {
constructor(private _router:Router, private _authenticationService:AuthenticationService) {
constructor(private _router: Router, private _authenticationService: AuthenticationService) {
}
ngOnInit() {
this._authenticationService.OnUserChanged.on((user:User) => {
this._authenticationService.OnUserChanged.on((user: User) => {
if (user != null) {
if (this._router.isRouteActive(this._router.generate(['Login']))) {
if (this._router.isActive('login', true)) {
console.log("routing");
this._router.navigate(["Gallery", {directory: ""}]);
this._router.navigate(["gallery", ""]);
}
} else {
if (!this._router.isRouteActive(this._router.generate(['Login']))) {
if (this._router.isActive('login', true)) {
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";
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") {
Utils.updateKeys(Config.Client, ServerInject.ConfigInject);

View File

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

View File

@ -1,7 +1,5 @@
///<reference path="../../browser.d.ts"/>
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 {User} from "../../../common/entities/User";
import {Config} from "../config/Config";
@ -9,7 +7,7 @@ import {Config} from "../config/Config";
@Component({
selector: 'app-frame',
templateUrl: 'app/frame/frame.component.html',
directives: [RouterLink],
providers: [RouterLink],
encapsulation: ViewEncapsulation.Emulated
})
export class FrameComponent {

View File

@ -1,5 +1,3 @@
///<reference path="../../browser.d.ts"/>
import {Injectable} from "@angular/core";
import {Photo} from "../../../common/entities/Photo";
import {Directory} from "../../../common/entities/Directory";
@ -10,20 +8,20 @@ import {Config} from "../config/Config";
export class GalleryCacheService {
public getDirectory(directoryName:string):Directory {
public getDirectory(directoryName: string): Directory {
if (Config.Client.enableCache == false) {
return null;
}
let value = localStorage.getItem(directoryName);
if (value != null) {
let directory:Directory = JSON.parse(value);
let directory: Directory = JSON.parse(value);
directory.photos.forEach((photo:Photo) => {
directory.photos.forEach((photo: Photo) => {
photo.metadata.creationDate = new Date(<any>photo.metadata.creationDate);
});
directory.photos.forEach((photo:Photo) => {
directory.photos.forEach((photo: Photo) => {
photo.directory = directory;
});
@ -32,14 +30,14 @@ export class GalleryCacheService {
return null;
}
public setDirectory(directory:Directory):void {
public setDirectory(directory: Directory): void {
if (Config.Client.enableCache == false) {
return;
}
localStorage.setItem(Utils.concatUrls(directory.path, directory.name), JSON.stringify(directory));
directory.directories.forEach((dir:Directory) => {
directory.directories.forEach((dir: Directory) => {
let name = Utils.concatUrls(dir.path, dir.name);
if (localStorage.getItem(name) == null) { //don't override existing
localStorage.setItem(Utils.concatUrls(dir.path, dir.name), JSON.stringify(dir));
@ -52,7 +50,7 @@ export class GalleryCacheService {
* Update photo state at cache too (Eg.: thumbnail rendered)
* @param photo
*/
public photoUpdated(photo:Photo):void {
public photoUpdated(photo: Photo): void {
if (Config.Client.enableCache == false) {
return;
@ -61,7 +59,7 @@ export class GalleryCacheService {
let directoryName = Utils.concatUrls(photo.directory.path, photo.directory.name);
let value = localStorage.getItem(directoryName);
if (value != null) {
let directory:Directory = JSON.parse(value);
let directory: Directory = JSON.parse(value);
directory.photos.forEach((p) => {
if (p.name === photo.name) {
//update data

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;">
{{directory.name}}
</a>

View File

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

View File

@ -1,16 +1,14 @@
///<reference path="../../browser.d.ts"/>
import {Injectable} from "@angular/core";
@Injectable()
export class FullScreenService {
public isFullScreenEnabled():boolean {
public isFullScreenEnabled(): boolean {
return !!(document.fullscreenElement || document['mozFullScreenElement'] || document.webkitFullscreenElement);
}
public showFullScreen(element:any) {
public showFullScreen(element: any) {
if (this.isFullScreenEnabled()) {
return;
}

View File

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

View File

@ -1,72 +1,65 @@
///<reference path="../../browser.d.ts"/>
import {Component, OnInit, ViewChild} from "@angular/core";
import {AuthenticationService} from "../model/network/authentication.service.ts";
import {Router, RouteParams} from "@angular/router-deprecated";
import {AuthenticationService} from "../model/network/authentication.service";
import {Router, ActivatedRoute, Params} from "@angular/router";
import {GalleryService} from "./gallery.service";
import {GalleryDirectoryComponent} from "./directory/directory.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 {Config} from "../config/Config";
import {SearchTypes} from "../../../common/entities/AutoCompleteItem";
import {GalleryNavigatorComponent} from "./navigator/navigator.gallery.component";
@Component({
selector: 'gallery',
templateUrl: 'app/gallery/gallery.component.html',
styleUrls: ['app/gallery/gallery.component.css'],
directives: [GalleryGridComponent,
GalleryDirectoryComponent,
GalleryLightboxComponent,
FrameComponent,
GallerySearchComponent,
GalleryNavigatorComponent]
styleUrls: ['app/gallery/gallery.component.css']
})
export class GalleryComponent implements OnInit {
@ViewChild(GallerySearchComponent) search:GallerySearchComponent;
@ViewChild(GalleryGridComponent) grid:GalleryGridComponent;
@ViewChild(GallerySearchComponent) search: GallerySearchComponent;
@ViewChild(GalleryGridComponent) grid: GalleryGridComponent;
public showSearchBar:boolean = true;
public showSearchBar: boolean = true;
constructor(private _galleryService:GalleryService,
private _params:RouteParams,
private _authService:AuthenticationService,
private _router:Router) {
constructor(private _galleryService: GalleryService,
private _authService: AuthenticationService,
private _router: Router,
private _route: ActivatedRoute) {
this.showSearchBar = Config.Client.Search.searchEnabled;
}
ngOnInit() {
if (!this._authService.isAuthenticated()) {
this._router.navigate(['Login']);
this._router.navigate(['login']);
return;
}
this._route.params
.subscribe((params: Params) => {
let searchText = params['searchText'];
if (searchText && searchText != "") {
console.log("searching");
let typeString = params['type'];
let searchText = this._params.get('searchText');
if (searchText && searchText != "") {
console.log("searching");
let typeString = this._params.get('type');
if (typeString && typeString != "") {
console.log("with type");
let type: SearchTypes = <any>SearchTypes[typeString];
this._galleryService.search(searchText, type);
return;
}
if (typeString && typeString != "") {
console.log("with type");
let type:SearchTypes = SearchTypes[typeString];
this._galleryService.search(searchText, type);
return;
}
this._galleryService.search(searchText);
return;
}
this._galleryService.search(searchText);
return;
}
let directoryName = this._params.get('directory');
directoryName = directoryName ? directoryName : "";
let directoryName = params['directory'];
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 {NetworkService} from "../model/network/network.service.ts";
import {NetworkService} from "../model/network/network.service";
import {Message} from "../../../common/entities/Message";
import {ContentWrapper} from "../../../common/entities/ConentWrapper";
import {Photo} from "../../../common/entities/Photo";
@ -20,7 +18,7 @@ export class GalleryService {
this.content = new ContentWrapper();
}
lastRequest = {
lastRequest: {directory: any} = {
directory: null
};
public getDirectory(directoryName:string):Promise<Message<ContentWrapper>> {

View File

@ -1,5 +1,3 @@
///<reference path="../../../browser.d.ts"/>
import {
Component,
Input,
@ -22,7 +20,6 @@ import {Config} from "../../config/Config";
selector: 'gallery-grid',
templateUrl: 'app/gallery/grid/grid.gallery.component.html',
styleUrls: ['app/gallery/grid/grid.gallery.component.css'],
directives: [GalleryPhotoComponent]
})
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 {IRenderable, Dimension} from "../../../model/IRenderable";
import {GridPhoto} from "../GridPhoto";
import {SearchTypes} from "../../../../../common/entities/AutoCompleteItem";
import {RouterLink} from "@angular/router-deprecated";
import {RouterLink} from "@angular/router";
import {Config} from "../../../config/Config";
import {
ThumbnailLoaderService,
@ -12,19 +10,18 @@ import {
ThumbnailLoadingListener,
ThumbnailLoadingPriority
} from "../thumnailLoader.service";
import {GalleryPhotoLoadingComponent} from "./loading/loading.photo.grid.gallery.component";
@Component({
selector: 'gallery-grid-photo',
templateUrl: 'app/gallery/grid/photo/photo.grid.gallery.component.html',
styleUrls: ['app/gallery/grid/photo/photo.grid.gallery.component.css'],
directives: [RouterLink, GalleryPhotoLoadingComponent],
providers: [RouterLink],
})
export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit, OnDestroy {
@Input() gridPhoto:GridPhoto;
@ViewChild("img") imageRef:ElementRef;
@ViewChild("info") infoDiv:ElementRef;
@ViewChild("photoContainer") container:ElementRef;
@Input() gridPhoto: GridPhoto;
@ViewChild("img") imageRef: ElementRef;
@ViewChild("info") infoDiv: ElementRef;
@ViewChild("photoContainer") container: ElementRef;
image = {
@ -37,19 +34,19 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
show: true
};
thumbnailTask:ThumbnailTaskEntity = null;
thumbnailTask: ThumbnailTaskEntity = null;
infoStyle = {
height: 0,
background: "rgba(0,0,0,0.0)"
};
SearchTypes:any = [];
searchEnabled:boolean = true;
SearchTypes: any = [];
searchEnabled: boolean = true;
wasInView:boolean = null;
wasInView: boolean = null;
constructor(private thumbnailService:ThumbnailLoaderService) {
constructor(private thumbnailService: ThumbnailLoaderService) {
this.SearchTypes = SearchTypes;
this.searchEnabled = Config.Client.Search.searchEnabled;
@ -74,17 +71,17 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
if (!this.gridPhoto.isThumbnailAvailable()) {
setImmediate(() => {
let listener:ThumbnailLoadingListener = {
onStartedLoading: ()=> { //onLoadStarted
let listener: ThumbnailLoadingListener = {
onStartedLoading: () => { //onLoadStarted
this.loading.animate = true;
},
onLoad: ()=> {//onLoaded
onLoad: () => {//onLoaded
this.image.src = this.gridPhoto.getThumbnailPath();
this.image.show = true;
this.loading.show = false;
this.thumbnailTask = null;
},
onError: (error)=> {//onError
onError: (error) => {//onError
this.thumbnailTask = null;
//TODO: handle error
//TODO: not an error if its from cache
@ -111,7 +108,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
}
isInView():boolean {
isInView(): boolean {
return document.body.scrollTop < this.container.nativeElement.offsetTop + this.container.nativeElement.clientHeight
&& document.body.scrollTop + window.innerHeight > this.container.nativeElement.offsetTop;
}
@ -139,7 +136,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
}
}
getPositionText():string {
getPositionText(): string {
if (!this.gridPhoto) {
return ""
}
@ -164,7 +161,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
this.loading.show = false;
}
public getDimension():Dimension {
public getDimension(): Dimension {
return new Dimension(this.imageRef.nativeElement.offsetTop,
this.imageRef.nativeElement.offsetLeft,
this.imageRef.nativeElement.width,

View File

@ -1,5 +1,3 @@
///<reference path="../../../browser.d.ts"/>
import {Injectable} from "@angular/core";
import {GridPhoto} from "./GridPhoto";
import {Config} from "../../config/Config";
@ -12,17 +10,17 @@ export enum ThumbnailLoadingPriority{
@Injectable()
export class ThumbnailLoaderService {
que:Array<ThumbnailTask> = [];
runningRequests:number = 0;
que: Array<ThumbnailTask> = [];
runningRequests: number = 0;
constructor(private galleryChacheService:GalleryCacheService) {
constructor(private galleryChacheService: GalleryCacheService) {
}
removeTasks() {
this.que = [];
}
removeTask(taskEntry:ThumbnailTaskEntity) {
removeTask(taskEntry: ThumbnailTaskEntity) {
for (let i = 0; i < this.que.length; i++) {
let index = this.que[i].taskEntities.indexOf(taskEntry);
@ -38,9 +36,9 @@ export class ThumbnailLoaderService {
}
loadImage(gridPhoto:GridPhoto, priority:ThumbnailLoadingPriority, listener:ThumbnailLoadingListener):ThumbnailTaskEntity {
loadImage(gridPhoto: GridPhoto, priority: ThumbnailLoadingPriority, listener: ThumbnailLoadingListener): ThumbnailTaskEntity {
let tmp:ThumbnailTask = null;
let tmp: ThumbnailTask = null;
//is image already qued?
for (let i = 0; i < this.que.length; i++) {
if (this.que[i].gridPhoto.getThumbnailPath() == gridPhoto.getThumbnailPath()) {
@ -71,7 +69,7 @@ export class ThumbnailLoaderService {
}
private getNextTask():ThumbnailTask {
private getNextTask(): ThumbnailTask {
if (this.que.length === 0) {
return null;
}
@ -95,7 +93,7 @@ export class ThumbnailLoaderService {
return this.que[0];
}
private taskReady(task:ThumbnailTask) {
private taskReady(task: ThumbnailTask) {
let i = this.que.indexOf(task);
if (i == -1) {
if (task.taskEntities.length !== 0) {
@ -118,7 +116,7 @@ export class ThumbnailLoaderService {
}
this.runningRequests++;
task.taskEntities.forEach(te=>te.listener.onStartedLoading());
task.taskEntities.forEach(te => te.listener.onStartedLoading());
task.inProgress = true;
let curImg = new Image();
@ -128,7 +126,7 @@ export class ThumbnailLoaderService {
task.gridPhoto.thumbnailLoaded();
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.runningRequests--;
@ -136,7 +134,7 @@ export class ThumbnailLoaderService {
};
curImg.onerror = (error) => {
task.taskEntities.forEach(te=>te.listener.onError(error));
task.taskEntities.forEach((te: ThumbnailTaskEntity) => te.listener.onError(error));
this.taskReady(task);
this.runningRequests--;
@ -147,21 +145,21 @@ export class ThumbnailLoaderService {
export interface ThumbnailLoadingListener {
onStartedLoading:()=>void;
onLoad:()=>void;
onError:(error)=>void;
onStartedLoading: () => void;
onLoad: () => void;
onError: (error: any) => void;
}
export interface ThumbnailTaskEntity {
priority:ThumbnailLoadingPriority;
listener:ThumbnailLoadingListener;
priority: ThumbnailLoadingPriority;
listener: ThumbnailLoadingListener;
}
interface ThumbnailTask {
gridPhoto:GridPhoto;
inProgress:boolean;
taskEntities:Array<ThumbnailTaskEntity>;
gridPhoto: GridPhoto;
inProgress: boolean;
taskEntities: Array<ThumbnailTaskEntity>;
}

View File

@ -1,36 +1,29 @@
///<reference path="../../../browser.d.ts"/>
import {Component, QueryList, Output, EventEmitter, HostListener, ElementRef, ViewChild} from "@angular/core";
import {Photo} from "../../../../common/entities/Photo";
import {GalleryPhotoComponent} from "../grid/photo/photo.grid.gallery.component.ts";
import {BrowserDomAdapter} from "@angular/platform-browser/src/browser/browser_adapter";
import {GalleryPhotoComponent} from "../grid/photo/photo.grid.gallery.component";
import {Dimension} from "../../model/IRenderable";
import {GalleryLightboxPhotoComponent} from "./photo/photo.lightbox.gallery.component";
import {FullScreenService} from "../fullscreen.service";
@Component({
selector: 'gallery-lightbox',
styleUrls: ['app/gallery/lightbox/lightbox.gallery.component.css'],
templateUrl: 'app/gallery/lightbox/lightbox.gallery.component.html',
directives: [GalleryLightboxPhotoComponent]
})
export class GalleryLightboxComponent {
@Output('onLastElement') onLastElement = new EventEmitter();
public navigation = {hasPrev: true, hasNext: true};
public photoDimension:Dimension = new Dimension(0, 0, 0, 0);
public photoDimension: Dimension = new Dimension(0, 0, 0, 0);
private activePhoto:GalleryPhotoComponent;
public gridPhotoQL:QueryList<GalleryPhotoComponent>;
private activePhoto: GalleryPhotoComponent;
public gridPhotoQL: QueryList<GalleryPhotoComponent>;
private dom:BrowserDomAdapter;
private visible = false;
@ViewChild("root") elementRef:ElementRef;
@ViewChild("root") elementRef: ElementRef;
constructor(private fullScreenService:FullScreenService) {
this.dom = new BrowserDomAdapter();
constructor(private fullScreenService: FullScreenService) {
}
@ -65,9 +58,9 @@ export class GalleryLightboxComponent {
}
private showPhoto(photoComponent:GalleryPhotoComponent) {
private showPhoto(photoComponent: GalleryPhotoComponent) {
this.activePhoto = null;
setImmediate(()=> {
setImmediate(() => {
let pcList = this.gridPhotoQL.toArray();
let index = pcList.indexOf(photoComponent);
@ -82,7 +75,7 @@ export class GalleryLightboxComponent {
});
}
public show(photo:Photo) {
public show(photo: Photo) {
this.visible = true;
let selectedPhoto = this.findPhotoComponent(photo);
if (selectedPhoto === null) {
@ -91,7 +84,7 @@ export class GalleryLightboxComponent {
this.showPhoto(selectedPhoto);
this.dom.setStyle(this.dom.query('body'), 'overflow', 'hidden');
document.getElementsByTagName('body')[0].style.overflow = 'hidden';
}
public hide() {
@ -104,14 +97,14 @@ export class GalleryLightboxComponent {
this.setBodyScrollTop(to.top);
}
this.dom.setStyle(this.dom.query('body'), 'overflow', 'auto');
document.getElementsByTagName('body')[0].style.overflow = 'auto';
this.activePhoto = null;
}
private findPhotoComponent(photo) {
private findPhotoComponent(photo: any) {
let galleryPhotoComponents = this.gridPhotoQL.toArray();
for (let i = 0; i < galleryPhotoComponents.length; i++) {
if (galleryPhotoComponents[i].gridPhoto.photo == photo) {
@ -122,8 +115,8 @@ export class GalleryLightboxComponent {
}
@HostListener('window:keydown', ['$event'])
onKeyPress(e) {
let event = window.event ? window.event : e;
onKeyPress(e: KeyboardEvent) {
let event: KeyboardEvent = window.event ? <any>window.event : e;
switch (event.keyCode) {
case 37:
this.prevImage();
@ -134,11 +127,11 @@ export class GalleryLightboxComponent {
}
}
private getBodyScrollTop():number {
private getBodyScrollTop(): number {
return window.scrollY;
}
private setBodyScrollTop(value:number) {
private setBodyScrollTop(value: number) {
window.scrollTo(window.scrollX, value);
}
@ -151,7 +144,7 @@ export class GalleryLightboxComponent {
}
private calcLightBoxPhotoDimension(photo:Photo):Dimension {
private calcLightBoxPhotoDimension(photo: Photo): Dimension {
let width = 0;
let height = 0;
if (photo.metadata.size.height > photo.metadata.size.width) {

View File

@ -1,6 +1,6 @@
<ol id="directory-path" class="breadcrumb">
<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>
</li>

View File

@ -1,18 +1,16 @@
///<reference path="../../../browser.d.ts"/>
import {Component, Input, OnChanges} from "@angular/core";
import {Directory} from "../../../../common/entities/Directory";
import {RouterLink} from "@angular/router-deprecated";
import {RouterLink} from "@angular/router";
@Component({
selector: 'gallery-navbar',
templateUrl: 'app/gallery/navigator/navigator.gallery.component.html',
directives: [RouterLink],
providers: [RouterLink],
})
export class GalleryNavigatorComponent implements OnChanges {
@Input() directory:Directory;
@Input() directory: Directory;
routes:Array<any> = [];
routes: Array<any> = [];
constructor() {
}
@ -22,7 +20,7 @@ export class GalleryNavigatorComponent implements OnChanges {
this.getPath();
}
getPath() {
getPath(): any {
if (!this.directory) {
return [];
}
@ -41,7 +39,7 @@ export class GalleryNavigatorComponent implements OnChanges {
}
let arr = [];
let arr: any = [];
//create root link
if (dirs.length == 0) {
@ -52,7 +50,7 @@ export class GalleryNavigatorComponent implements OnChanges {
}
//create rest navigation
dirs.forEach((name, index)=> {
dirs.forEach((name, index) => {
let route = dirs.slice(0, dirs.indexOf(name) + 1).join("/");
if (dirs.length - 1 == index) {
arr.push({name: name, route: null});

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">
<div class="input-group">
<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"
name="srch-term" id="srch-term" autocomplete="off">
@ -11,10 +11,10 @@
<div class="autocomplete-item" *ngFor="let item of autoCompleteItems">
<a [routerLink]="['Search',{searchText: item.text, type: SearchTypes[item.type]}]">
<span [ngSwitch]="item.type">
<span *ngSwitchWhen="0" class="glyphicon glyphicon-picture"></span>
<span *ngSwitchWhen="1" class="glyphicon glyphicon-folder-open"></span>
<span *ngSwitchWhen="2" class="glyphicon glyphicon-tag"></span>
<span *ngSwitchWhen="3" class="glyphicon glyphicon-map-marker"></span>
<span *ngSwitchCase="0" class="glyphicon glyphicon-picture"></span>
<span *ngSwitchCase="1" class="glyphicon glyphicon-folder-open"></span>
<span *ngSwitchCase="2" class="glyphicon glyphicon-tag"></span>
<span *ngSwitchCase="3" class="glyphicon glyphicon-map-marker"></span>
</span>
{{item.preText}}<strong>{{item.highLightText}}</strong>{{item.postText}}
</a>

View File

@ -1,38 +1,41 @@
///<reference path="../../../browser.d.ts"/>
import {Component} from "@angular/core";
import {AutoCompleteService} from "./autocomplete.service";
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 {GalleryService} from "../gallery.service";
import {FORM_DIRECTIVES} from "@angular/common";
import {Config} from "../../config/Config";
@Component({
selector: 'gallery-search',
templateUrl: 'app/gallery/search/search.gallery.component.html',
styleUrls: ['app/gallery/search/search.gallery.component.css'],
providers: [AutoCompleteService],
directives: [FORM_DIRECTIVES, RouterLink]
providers: [AutoCompleteService, RouterLink]
})
export class GallerySearchComponent {
autoCompleteItems:Array<AutoCompleteRenderItem> = [];
private searchText:string = "";
autoCompleteItems: Array<AutoCompleteRenderItem> = [];
private searchText: string = "";
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;
let searchText = this._params.get('searchText');
if (searchText && searchText != "") {
this.searchText = searchText;
}
this._route.params
.subscribe((params: Params) => {
let searchText = params['searchText'];
if (searchText && searchText != "") {
this.searchText = searchText;
}
});
}
onSearchChange(event:KeyboardEvent) {
onSearchChange(event: KeyboardEvent) {
let searchText = (<HTMLInputElement>event.target).value;
@ -51,26 +54,26 @@ export class GallerySearchComponent {
}
}
public search(item:AutoCompleteItem) {
public search(item: AutoCompleteItem) {
console.log("clicked");
this.searchText = item.text;
this.onSearch();
}
mouseOverAutoComplete:boolean = false;
mouseOverAutoComplete: boolean = false;
public setMouseOverAutoComplete(value) {
public setMouseOverAutoComplete(value: boolean) {
this.mouseOverAutoComplete = value;
}
public onFocusLost(event) {
public onFocusLost() {
if (this.mouseOverAutoComplete == false) {
this.autoCompleteItems = [];
}
}
public onFocus(event) {
public onFocus() {
this.autocomplete(this.searchText);
}
@ -78,12 +81,12 @@ export class GallerySearchComponent {
this.autoCompleteItems = [];
}
private autocomplete(searchText:string) {
private autocomplete(searchText: string) {
if (!Config.Client.Search.autocompleteEnabled) {
return
}
if (searchText.trim().length > 0) {
this._autoCompleteService.autoComplete(searchText).then((message:Message<Array<AutoCompleteItem>>) => {
this._autoCompleteService.autoComplete(searchText).then((message: Message<Array<AutoCompleteItem>>) => {
if (message.error) {
//TODO: implement
console.error(message.error);
@ -96,27 +99,27 @@ export class GallerySearchComponent {
}
}
private showSuggestions(suggestions:Array<AutoCompleteItem>, searchText:string) {
private showSuggestions(suggestions: Array<AutoCompleteItem>, searchText: string) {
this.emptyAutoComplete();
suggestions.forEach((item:AutoCompleteItem)=> {
suggestions.forEach((item: AutoCompleteItem) => {
let renderItem = new AutoCompleteRenderItem(item.text, searchText, item.type);
this.autoCompleteItems.push(renderItem);
});
}
public setSearchText(searchText:string) {
public setSearchText(searchText: string) {
this.searchText = searchText;
}
}
class AutoCompleteRenderItem {
public preText:string = "";
public highLightText:string = "";
public postText:string = "";
public type:SearchTypes;
public preText: string = "";
public highLightText: string = "";
public postText: string = "";
public type: SearchTypes;
constructor(public text:string, searchText:string, type:SearchTypes) {
constructor(public text: string, searchText: string, type: SearchTypes) {
let preIndex = text.toLowerCase().indexOf(searchText.toLowerCase());
if (preIndex > -1) {
this.preText = text.substring(0, preIndex);

View File

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

View File

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

View File

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

View File

@ -1,26 +1,24 @@
///<reference path="../../../browser.d.ts"/>
import {Injectable} from "@angular/core";
import {User, UserRoles} from "../../../../common/entities/User";
import {Event} from "../../../../common/event/Event";
import {UserService} from "./user.service.ts";
import {UserService} from "./user.service";
import {LoginCredential} from "../../../../common/entities/LoginCredential";
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 {Config} from "../../config/Config";
declare module ServerInject {
export var user;
export let user: User;
}
@Injectable()
export class AuthenticationService {
private _user:User = null;
public OnUserChanged:Event<User>;
private _user: User = null;
public OnUserChanged: Event<User>;
constructor(private _userService:UserService) {
constructor(private _userService: UserService) {
this.OnUserChanged = new Event();
//picking up session..
@ -29,12 +27,14 @@ export class AuthenticationService {
this.setUser(ServerInject.user);
}
this.getSessionUser();
} else {
this.OnUserChanged.trigger(this._user);
}
}
private getSessionUser() {
this._userService.getSessionUser().then((message:Message<User>) => {
this._userService.getSessionUser().then((message: Message<User>) => {
if (message.error) {
console.log(message.error);
} else {
@ -44,15 +44,15 @@ export class AuthenticationService {
});
}
private setUser(user:User) {
private setUser(user: User) {
this._user = user;
this.OnUserChanged.trigger(this._user);
}
public login(credential:LoginCredential) {
return this._userService.login(credential).then((message:Message<User>) => {
public login(credential: LoginCredential) {
return this._userService.login(credential).then((message: Message<User>) => {
if (message.error) {
console.log(ErrorCodes[message.error.code] + ", message: " + message.error.message);
console.log(ErrorCodes[message.error.code] + ", message: ", message.error.message);
} else {
this.setUser(message.result);
}
@ -61,11 +61,11 @@ export class AuthenticationService {
}
public isAuthenticated():boolean {
public isAuthenticated(): boolean {
if (Config.Client.authenticationRequired === false) {
return true;
}
return (this._user && this._user != null) ? true : false;
return !!(this._user && this._user != null);
}
public getUser() {

View File

@ -1,32 +1,35 @@
///<reference path="../../../browser.d.ts"/>
import {it, inject, beforeEachProviders, beforeEach, afterEach} from "@angular/core/testing";
import {inject, TestBed} from "@angular/core/testing";
import {BaseRequestOptions, Http, Response, ResponseOptions} from "@angular/http";
import {MockBackend, MockConnection} from "@angular/http/testing";
import {provide} from "@angular/core";
import "rxjs/Rx";
import {NetworkService} from "./network.service";
import {Message} from "../../../../common/entities/Message";
describe('NetworkService Success tests', () => {
let connection:MockConnection = null;
let connection: MockConnection = null;
let testUrl = "/test/url";
let testData = {data: "testData"};
let testResponse = "testResponse";
let testResponseMessage = new Message(null, testResponse);
beforeEachProviders(() => [
MockBackend,
BaseRequestOptions,
provide(Http, {
useFactory: (backend, options) => {
return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions]
}),
NetworkService
]);
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
MockBackend,
BaseRequestOptions,
{
provide: Http, useFactory: (backend, options) => {
return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions]
},
NetworkService
]
});
});
beforeEach(inject([MockBackend], (backend) => {
@ -48,7 +51,7 @@ describe('NetworkService Success tests', () => {
it('should call GET', inject([NetworkService], (networkService) => {
networkService.getJson(testUrl).then((res:Message<any>) => {
networkService.getJson(testUrl).then((res: Message<any>) => {
expect(res.result).toBe(testResponse);
});
@ -56,13 +59,13 @@ describe('NetworkService Success tests', () => {
it('should call POST', inject([NetworkService, MockBackend], (networkService) => {
networkService.postJson(testUrl, testData).then((res:Message<any>) => {
networkService.postJson(testUrl, testData).then((res: Message<any>) => {
expect(res.result).toBe(testResponse);
});
expect(connection.request.text()).toBe(JSON.stringify(testData));
networkService.postJson(testUrl).then((res:Message<any>) => {
networkService.postJson(testUrl).then((res: Message<any>) => {
expect(res.result).toBe(testResponse);
});
expect(connection.request.text()).toBe(JSON.stringify({}));
@ -70,14 +73,14 @@ describe('NetworkService Success tests', () => {
it('should call PUT', inject([NetworkService, MockBackend], (networkService) => {
networkService.putJson(testUrl, testData).then((res:Message<any>) => {
networkService.putJson(testUrl, testData).then((res: Message<any>) => {
expect(res.result).toBe(testResponse);
});
expect(connection.request.text()).toBe(JSON.stringify(testData));
networkService.putJson(testUrl).then((res:Message<any>) => {
networkService.putJson(testUrl).then((res: Message<any>) => {
expect(res.result).toBe(testResponse);
});
expect(connection.request.text()).toBe(JSON.stringify({}));
@ -86,7 +89,7 @@ describe('NetworkService Success tests', () => {
it('should call DELETE', inject([NetworkService, MockBackend], (networkService) => {
networkService.deleteJson(testUrl).then((res:Message<any>) => {
networkService.deleteJson(testUrl).then((res: Message<any>) => {
expect(res.result).toBe(testResponse);
});
}));
@ -94,22 +97,26 @@ describe('NetworkService Success tests', () => {
describe('NetworkService Fail tests', () => {
let connection:MockConnection = null;
let connection: MockConnection = null;
let testUrl = "/test/url";
let testData = {data: "testData"};
let testError = "testError";
beforeEachProviders(() => [
MockBackend,
BaseRequestOptions,
provide(Http, {
useFactory: (backend, options) => {
return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions]
}),
NetworkService
]);
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
MockBackend,
BaseRequestOptions,
{
provide: Http, useFactory: (backend, options) => {
return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions]
},
NetworkService
]
});
});
beforeEach(inject([MockBackend], (backend) => {
@ -127,7 +134,7 @@ describe('NetworkService Fail tests', () => {
it('should call GET with error', inject([NetworkService], (networkService) => {
networkService.getJson(testUrl).then((res:Message<any>) => {
networkService.getJson(testUrl).then((res: Message<any>) => {
expect(res).toBe(null);
}).catch((err) => {
expect(err).toBe(testError);
@ -137,7 +144,7 @@ describe('NetworkService Fail tests', () => {
it('should call POST with error', inject([NetworkService, MockBackend], (networkService) => {
networkService.postJson(testUrl, testData).then((res:Message<any>) => {
networkService.postJson(testUrl, testData).then((res: Message<any>) => {
expect(res).toBe(null);
}).catch((err) => {
expect(err).toBe(testError);
@ -147,7 +154,7 @@ describe('NetworkService Fail tests', () => {
it('should call PUT with error', inject([NetworkService, MockBackend], (networkService) => {
networkService.putJson(testUrl, testData).then((res:Message<any>) => {
networkService.putJson(testUrl, testData).then((res: Message<any>) => {
expect(res).toBe(null);
}).catch((err) => {
expect(err).toBe(testError);
@ -159,7 +166,7 @@ describe('NetworkService Fail tests', () => {
it('should call DELETE with error', inject([NetworkService, MockBackend], (networkService) => {
networkService.deleteJson(testUrl).then((res:Message<any>) => {
networkService.deleteJson(testUrl).then((res: Message<any>) => {
expect(res).toBe(null);
}).catch((err) => {
expect(err).toBe(testError);

View File

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

View File

@ -1,9 +1,6 @@
///<reference path="../../../browser.d.ts"/>
import {it, inject, beforeEachProviders} from "@angular/core/testing";
import {inject, TestBed} 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 "./network.service";
import {UserService} from "./user.service";
@ -12,34 +9,36 @@ import {LoginCredential} from "../../../../common/entities/LoginCredential";
describe('UserService', () => {
beforeEachProviders(() => [
MockBackend,
BaseRequestOptions,
provide(Http, {
useFactory: (backend, options) => {
return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions]
}),
NetworkService,
UserService
]);
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
MockBackend,
BaseRequestOptions,
{
provide: Http, useFactory: (backend, options) => {
return new Http(backend, options);
}, deps: [MockBackend, BaseRequestOptions]
},
NetworkService,
UserService]
});
it('should call postJson at login', inject([UserService, NetworkService], (userService, networkService) => {
spyOn(networkService, "postJson");
let credential = new LoginCredential("name", "pass");
userService.login(credential);
expect(networkService.postJson).toHaveBeenCalled();
expect(networkService.postJson.calls.argsFor(0)).toEqual(["/user/login", {"loginCredential": credential}]);
}));
it('should call postJson at login', inject([UserService, NetworkService], (userService, networkService) => {
spyOn(networkService, "postJson");
let credential = new LoginCredential("name", "pass");
userService.login(credential);
expect(networkService.postJson).toHaveBeenCalled();
expect(networkService.postJson.calls.argsFor(0)).toEqual(["/user/login", {"loginCredential": credential}]);
}));
it('should call getJson at getSessionUser', inject([UserService, NetworkService], (userService, networkService) => {
spyOn(networkService, "getJson");
userService.getSessionUser();
expect(networkService.getJson).toHaveBeenCalled();
expect(networkService.getJson.calls.argsFor(0)).toEqual(["/user/login"]);
}));
it('should call getJson at getSessionUser', inject([UserService, NetworkService], (userService, networkService) => {
spyOn(networkService, "getJson");
userService.getSessionUser();
expect(networkService.getJson).toHaveBeenCalled();
expect(networkService.getJson.calls.argsFor(0)).toEqual(["/user/login"]);
}));
});
});
});

View File

@ -1,8 +1,6 @@
///<reference path="../../../browser.d.ts"/>
import {Injectable} from "@angular/core";
import {LoginCredential} from "../../../../common/entities/LoginCredential";
import {NetworkService} from "./network.service.ts";
import {NetworkService} from "./network.service";
import {User} from "../../../../common/entities/User";
import {Message} from "../../../../common/entities/Message";
@ -10,19 +8,19 @@ import {Message} from "../../../../common/entities/Message";
export class UserService {
constructor(private _networkService:NetworkService) {
constructor(private _networkService: NetworkService) {
}
public logout():Promise<Message<string>> {
public logout(): Promise<Message<string>> {
console.log("call logout");
return this._networkService.postJson("/user/logout");
}
public login(credential:LoginCredential):Promise<Message<User>> {
public login(credential: LoginCredential): Promise<Message<User>> {
return this._networkService.postJson("/user/login", {"loginCredential": credential});
}
public getSessionUser():Promise<Message<User>> {
public getSessionUser(): Promise<Message<User>> {
return this._networkService.getJson("/user/login");
}

View File

@ -52,10 +52,10 @@
<form (ngSubmit)="onSubmit()" #NewUserForm="ngForm">
<div class="modal-body">
<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"
[(ngModel)]="newUser.password" ngControl="password" #name="ngForm" required>
<select class="form-control" [(ngModel)]="newUser.role" required>
[(ngModel)]="newUser.password" name="password" required>
<select class="form-control" [(ngModel)]="newUser.role" name="role" required>
<option *ngFor="let repository of userRoles" [value]="repository.key">{{repository.value}}
</option>
</select>

View File

@ -1,31 +1,24 @@
///<reference path="../../../browser.d.ts"/>
import {Component, OnInit} from "@angular/core";
import {AuthenticationService} from "../../model/network/authentication.service.ts";
import {Router} from "@angular/router-deprecated";
import {FrameComponent} from "../../frame/frame.component";
import {AuthenticationService} from "../../model/network/authentication.service";
import {Router} from "@angular/router";
import {User, UserRoles} from "../../../../common/entities/User";
import {FORM_DIRECTIVES} from "@angular/common";
import {Utils} from "../../../../common/Utils";
import {Message} from "../../../../common/entities/Message";
import {StringifyRole} from "./../../pipes/StringifyRolePipe";
import {UserManagerSettingsService} from "./usermanager.settings.service";
@Component({
selector: 'settings-usermanager',
templateUrl: 'app/settings/usermanager/usermanager.settings.component.html',
styleUrls: ['app/settings/usermanager/usermanager.settings.component.css'],
directives: [FrameComponent, FORM_DIRECTIVES],
providers: [UserManagerSettingsService],
pipes: [StringifyRole]
})
export class UserMangerSettingsComponent implements OnInit {
private newUser = new User();
private userRoles:Array<any> = [];
private users:Array<User> = [];
private userRoles: Array<any> = [];
private users: Array<User> = [];
constructor(private _authService:AuthenticationService, private _router:Router, private _userSettings:UserManagerSettingsService) {
constructor(private _authService: AuthenticationService, private _router: Router, private _userSettings: UserManagerSettingsService) {
}
ngOnInit() {
@ -38,13 +31,13 @@ export class UserMangerSettingsComponent implements OnInit {
}
private getUsersList() {
this._userSettings.getUsers().then((result:Message<Array<User>>) => {
this._userSettings.getUsers().then((result: Message<Array<User>>) => {
this.users = result.result;
});
}
canModifyUser(user:User):boolean {
canModifyUser(user: User): boolean {
let currentUser = this._authService.getUser();
if (!currentUser) {
return false;
@ -64,13 +57,13 @@ export class UserMangerSettingsComponent implements OnInit {
});
}
updateRole(user:User) {
updateRole(user: User) {
this._userSettings.updateRole(user).then(() => {
this.getUsersList();
});
}
deleteUser(user:User) {
deleteUser(user: User) {
this._userSettings.deleteUser(user).then(() => {
this.getUsersList();
});

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="../node_modules/tslint/lib/tslint.d.ts" />
/// <reference path="../common/common-classes.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/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"/>

View File

@ -9,26 +9,31 @@
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7"
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>
<script>
var ServerInject = {
user: <%- JSON.stringify(user); %>,
ConfigInject: <%- JSON.stringify(clientConfig); %>
}
</script>
<script src="systemjs.config.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>
<script>
var ServerInject = {
user: <%- JSON.stringify(user); %>,
ConfigInject: <%- JSON.stringify(clientConfig); %>
}
</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="dist/app-bundle.js"></script>
</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";
import {AppComponent} from "./app/app.component.ts";
bootstrap(AppComponent)
.catch(err => console.error(err));
platformBrowserDynamic().bootstrapModule(AppModule).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": {
"target": "es5",
"sourceMap": true,
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
"exclude": [
"node_modules",
"typings/main.d.ts",
"typings/main"
]
}
"experimentalDecorators": true,
"lib": [
"es2015",
"dom"
],
"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) {
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({
// 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
basePath: '',
frameworks: ['jasmine'],
// list of files to exclude
exclude: [ ],
// list of files / patterns to load in the browser
// 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'
plugins: [
require('karma-jasmine'),
require('karma-phantomjs-launcher'),
require('karma-jasmine-html-reporter')
],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
client: {
builtPaths: [appBase, commonBase, testingBase], // add more spec base paths as needed
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",
"main": "./backend/server.js",
"scripts": {
"postinstall": "typings install && tsc -p backend && tsc -p test/backend && tsc -p common && webpack --config ./frontend/webpack.config.js -p",
"pretest": "typings install && tsc -p test/backend",
"test": "karma start ./karma.conf.js && mocha --recursive test/backend/unit",
"postinstall": "tsc -p frontend && tsc -p backend && tsc -p test/backend && tsc -p common",
"pretest": "tsc -p frontend && tsc -p backend && tsc -p test/backend",
"test": "karma start karma.conf.js --single-run && mocha --recursive test/backend/unit",
"start": "node ./backend/server"
},
"repository": {
@ -21,70 +21,58 @@
"url": "https://github.com/bpatrik/PiGallery2/issues"
},
"dependencies": {
"@angular/common": "2.0.0-rc.4",
"@angular/compiler": "2.0.0-rc.4",
"@angular/core": "2.0.0-rc.4",
"@angular/forms": "^0.2.0",
"@angular/http": "2.0.0-rc.4",
"@angular/platform-browser": "2.0.0-rc.4",
"@angular/platform-browser-dynamic": "2.0.0-rc.4",
"@angular/platform-server": "2.0.0-rc.4",
"@angular/router": "3.0.0-beta.2",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/common": "~2.4.1",
"@angular/compiler": "~2.4.1",
"@angular/core": "~2.4.1",
"@angular/forms": "~2.4.1",
"@angular/http": "~2.4.1",
"@angular/platform-browser": "~2.4.1",
"@angular/platform-browser-dynamic": "~2.4.1",
"@angular/platform-server": "~2.4.1",
"@angular/router": "~3.4.1",
"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",
"chai": "^3.5.0",
"compression-webpack-plugin": "^0.3.0",
"core-js": "^2.4.0",
"css-loader": "^0.23.1",
"debug": "^2.2.0",
"ejs": "^2.4.2",
"es6-promise-loader": "^1.0.1",
"debug": "^2.5.2",
"ejs": "^2.5.5",
"exif-parser": "^0.1.9",
"exports-loader": "^0.6.3",
"expose-loader": "^0.7.1",
"express": "^4.14.0",
"express-session": "^1.14.0",
"file-loader": "^0.8.5",
"express-session": "^1.14.2",
"flat-file-db": "^1.0.0",
"html-webpack-plugin": "^2.22.0",
"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",
"jimp": "^0.2.27",
"mime": "^1.3.4",
"mocha": "^2.5.3",
"mocha": "^3.2.0",
"morgan": "^1.7.0",
"ng2-cookies": "^0.1.9",
"ng2lint": "0.0.10",
"ng2-cookies": "^1.0.4",
"node-iptc": "^1.0.4",
"optimist": "^0.6.1",
"phantomjs-prebuilt": "^2.1.7",
"protractor": "^3.2.2",
"raw-loader": "0.5.1",
"remap-istanbul": "^0.6.4",
"rimraf": "^2.5.2",
"rxjs": "5.0.0-beta.6",
"source-map-loader": "^0.1.5",
"style-loader": "^0.13.0",
"ts-helpers": "1.1.1",
"ts-loader": "^0.8.2",
"tslint": "^3.13.0",
"tslint-loader": "^2.1.5",
"typedoc": "^0.4.4",
"typescript": "^1.8.10",
"typings": "^1.3.1",
"url-loader": "^0.5.7",
"webpack": "^1.13.1",
"zone.js": "^0.6.12"
"optimist": "^0.6.1"
},
"devDependencies": {
"@types/express": "^4.0.34",
"@types/express-session": "0.0.32",
"@types/jasmine": "^2.5.38",
"@types/node": "^6.0.46",
"@types/optimist": "0.0.29",
"angular-cli": "^1.0.0-beta.24",
"chai": "^3.5.0",
"jasmine-core": "^2.5.2",
"karma": "1.2.0",
"karma-cli": "^1.0.1",
"karma-jasmine": "^1.0.2",
"karma-jasmine-html-reporter": "^0.2.2",
"karma-phantomjs-launcher": "^1.0.2",
"karma-remap-istanbul": "^0.2.1",
"karma-systemjs": "^0.16.0",
"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": {
"target": "es5",
"sourceMap": true,
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
"exclude": [
"node_modules",
"typings/main.d.ts",
"typings/main"
]
}
"experimentalDecorators": true,
"lib": [
"es2015",
"dom"
],
"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"
}
}