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:
parent
3cd9ef7b1a
commit
eaf678bedd
@ -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();
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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') {
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../typings/index.d.ts"/>
|
||||
|
||||
import {IUserManager} from "./IUserManager";
|
||||
import {IGalleryManager} from "./IGalleryManager";
|
||||
import {ISearchManager} from "./ISearchManager";
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
65
frontend/app/app.module.ts
Normal file
65
frontend/app/app.module.ts
Normal 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 {
|
||||
}
|
32
frontend/app/app.routing.ts
Normal file
32
frontend/app/app.routing.ts
Normal 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);
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}));
|
||||
|
||||
});
|
@ -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>> {
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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>;
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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});
|
||||
|
@ -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);
|
||||
}));
|
||||
|
||||
});
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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";
|
||||
|
@ -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) => {
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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"]);
|
||||
}));
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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);
|
||||
}));
|
||||
|
||||
});
|
5
frontend/browser.d.ts
vendored
5
frontend/browser.d.ts
vendored
@ -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"/>
|
||||
|
||||
|
@ -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>
|
@ -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));
|
||||
|
||||
|
11
frontend/systemjs.config.extras.js
Normal file
11
frontend/systemjs.config.extras.js
Normal 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);
|
41
frontend/systemjs.config.js
Normal file
41
frontend/systemjs.config.js
Normal 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);
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
98
karma-test-shim.js
Normal 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);
|
||||
}
|
154
karma.conf.js
154
karma.conf.js
@ -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
|
||||
})
|
||||
}
|
||||
|
110
package.json
110
package.json
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
17
typings.json
17
typings.json
@ -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"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user