mirror of
https://github.com/xuthus83/pigallery2.git
synced 2025-01-14 14:43:17 +08:00
implementing search
This commit is contained in:
parent
225d2b6a8c
commit
c93c1aba2d
@ -7,6 +7,8 @@ import {Config} from "../config/Config";
|
|||||||
import {ObjectManagerRepository} from "../model/ObjectManagerRepository";
|
import {ObjectManagerRepository} from "../model/ObjectManagerRepository";
|
||||||
import {AutoCompleteItem} from "../../common/entities/AutoCompleteItem";
|
import {AutoCompleteItem} from "../../common/entities/AutoCompleteItem";
|
||||||
import {ContentWrapper} from "../../common/entities/ConentWrapper";
|
import {ContentWrapper} from "../../common/entities/ConentWrapper";
|
||||||
|
import {SearchResult} from "../../common/entities/SearchResult";
|
||||||
|
import {Photo} from "../../common/entities/Photo";
|
||||||
|
|
||||||
export class GalleryMWs {
|
export class GalleryMWs {
|
||||||
|
|
||||||
@ -27,12 +29,19 @@ export class GalleryMWs {
|
|||||||
if (err || !directory) {
|
if (err || !directory) {
|
||||||
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//remove cyclic reference
|
||||||
|
directory.photos.forEach((photo:Photo) => {
|
||||||
|
photo.directory = null;
|
||||||
|
});
|
||||||
|
|
||||||
req.resultPipe = new ContentWrapper(directory, null);
|
req.resultPipe = new ContentWrapper(directory, null);
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static loadImage(req:Request, res:Response, next:NextFunction) {
|
public static loadImage(req:Request, res:Response, next:NextFunction) {
|
||||||
if (!(req.params.imagePath)) {
|
if (!(req.params.imagePath)) {
|
||||||
return next();
|
return next();
|
||||||
@ -49,14 +58,29 @@ export class GalleryMWs {
|
|||||||
|
|
||||||
|
|
||||||
public static search(req:Request, res:Response, next:NextFunction) {
|
public static search(req:Request, res:Response, next:NextFunction) {
|
||||||
//TODO: implement
|
|
||||||
return next(new Error(ErrorCodes.GENERAL_ERROR));
|
ObjectManagerRepository.getInstance().getSearchManager().search(req.params.text, (err, result:SearchResult) => {
|
||||||
|
if (err || !result) {
|
||||||
|
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
||||||
|
}
|
||||||
|
req.resultPipe = new ContentWrapper(null, result);
|
||||||
|
return next();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static instantSearch(req:Request, res:Response, next:NextFunction) {
|
public static instantSearch(req:Request, res:Response, next:NextFunction) {
|
||||||
//TODO: implement
|
if (!(req.params.text)) {
|
||||||
return next(new Error(ErrorCodes.GENERAL_ERROR));
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectManagerRepository.getInstance().getSearchManager().instantSearch(req.params.text, (err, result:SearchResult) => {
|
||||||
|
if (err || !result) {
|
||||||
|
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
||||||
|
}
|
||||||
|
req.resultPipe = new ContentWrapper(null, result);
|
||||||
|
return next();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static autocomplete(req:Request, res:Response, next:NextFunction) {
|
public static autocomplete(req:Request, res:Response, next:NextFunction) {
|
||||||
|
@ -30,7 +30,7 @@ export class DiskManager {
|
|||||||
|
|
||||||
if (DiskManager.isImage(fullFilePath)) {
|
if (DiskManager.isImage(fullFilePath)) {
|
||||||
let dimensions = sizeOf(fullFilePath);
|
let dimensions = sizeOf(fullFilePath);
|
||||||
directory.photos.push(new Photo(1, file, dimensions.width, dimensions.height));
|
directory.photos.push(new Photo(1, file, directory, dimensions.width, dimensions.height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import {AutoCompleteItem} from "../../common/entities/AutoCompleteItem";
|
import {AutoCompleteItem} from "../../common/entities/AutoCompleteItem";
|
||||||
|
import {SearchResult} from "../../common/entities/SearchResult";
|
||||||
export interface ISearchManager {
|
export interface ISearchManager {
|
||||||
autocomplete(text, cb:(error:any, result:Array<AutoCompleteItem>) => void);
|
autocomplete(text, cb:(error:any, result:Array<AutoCompleteItem>) => void);
|
||||||
|
search(text, cb:(error:any, result:SearchResult) => void);
|
||||||
|
instantSearch(text, cb:(error:any, result:SearchResult) => void);
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import {AutoCompleteItem} from "../../../common/entities/AutoCompleteItem";
|
import {AutoCompleteItem} from "../../../common/entities/AutoCompleteItem";
|
||||||
import {ISearchManager} from "../ISearchManager";
|
import {ISearchManager} from "../ISearchManager";
|
||||||
|
import {SearchResult} from "../../../common/entities/SearchResult";
|
||||||
|
|
||||||
export class SearchManager implements ISearchManager {
|
export class SearchManager implements ISearchManager {
|
||||||
|
|
||||||
@ -8,5 +9,13 @@ export class SearchManager implements ISearchManager {
|
|||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
search(text, cb:(error:any, result:SearchResult) => void) {
|
||||||
|
throw new Error("not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
instantSearch(text, cb:(error:any, result:SearchResult) => void) {
|
||||||
|
throw new Error("not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -5,6 +5,7 @@ import {DiskManager} from "../DiskManger";
|
|||||||
import {Utils} from "../../../common/Utils";
|
import {Utils} from "../../../common/Utils";
|
||||||
import {DirectoryModel} from "./entities/DirectoryModel";
|
import {DirectoryModel} from "./entities/DirectoryModel";
|
||||||
import {PhotoModel} from "./entities/PhotoModel";
|
import {PhotoModel} from "./entities/PhotoModel";
|
||||||
|
import {Photo} from "../../../common/entities/Photo";
|
||||||
|
|
||||||
export class MongoGalleryManager implements IGalleryManager {
|
export class MongoGalleryManager implements IGalleryManager {
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ export class MongoGalleryManager implements IGalleryManager {
|
|||||||
if (err || !res) {
|
if (err || !res) {
|
||||||
return this.indexDirectory(relativeDirectoryName, cb);
|
return this.indexDirectory(relativeDirectoryName, cb);
|
||||||
}
|
}
|
||||||
return cb(err, res);
|
return cb(err, this.modelToEntity(res));
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -46,12 +47,38 @@ export class MongoGalleryManager implements IGalleryManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
scannedDirectory.photos = arr;
|
scannedDirectory.photos = arr;
|
||||||
DirectoryModel.create(scannedDirectory, (err)=> {
|
DirectoryModel.create(scannedDirectory, (err, savedDir)=> {
|
||||||
return cb(err, scannedDirectory);
|
scannedDirectory.photos.forEach((value:any) => {
|
||||||
|
value['directory'] = savedDir;
|
||||||
|
value.save();
|
||||||
|
});
|
||||||
|
return cb(err, this.modelToEntity(scannedDirectory));
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private modelToEntity(directroy:any):Directory {
|
||||||
|
console.log("modelToEntity");
|
||||||
|
// console.log(directroy);
|
||||||
|
let directoryEntity = new Directory(directroy._id);
|
||||||
|
Utils.updateKeys(directoryEntity, directroy);
|
||||||
|
directroy.photos.forEach((photo) => {
|
||||||
|
let photoEntity = new Photo(null, null, null, null, null);
|
||||||
|
Utils.updateKeys(photoEntity, photo);
|
||||||
|
console.log(photoEntity);
|
||||||
|
directoryEntity.photos.push(photoEntity);
|
||||||
|
});
|
||||||
|
directroy.directories.forEach((dir) => {
|
||||||
|
let dirEntity = new Directory(null, null, null, null, null, null);
|
||||||
|
Utils.updateKeys(dirEntity, dir);
|
||||||
|
console.log(dir);
|
||||||
|
console.log(dirEntity);
|
||||||
|
directoryEntity.directories.push(dirEntity);
|
||||||
|
});
|
||||||
|
|
||||||
|
return directoryEntity;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ import {AutoCompleteItem, AutoCompeleteTypes} from "../../../common/entities/Aut
|
|||||||
import {ISearchManager} from "../ISearchManager";
|
import {ISearchManager} from "../ISearchManager";
|
||||||
import {DirectoryModel} from "./entities/DirectoryModel";
|
import {DirectoryModel} from "./entities/DirectoryModel";
|
||||||
import {PhotoModel} from "./entities/PhotoModel";
|
import {PhotoModel} from "./entities/PhotoModel";
|
||||||
|
import {SearchResult} from "../../../common/entities/SearchResult";
|
||||||
|
|
||||||
export class MongoSearchManager implements ISearchManager {
|
export class MongoSearchManager implements ISearchManager {
|
||||||
|
|
||||||
@ -35,6 +36,70 @@ export class MongoSearchManager implements ISearchManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
search(text, cb:(error:any, result:SearchResult) => void) {
|
||||||
|
console.log("instantSearch: " + text);
|
||||||
|
let result:SearchResult = new SearchResult();
|
||||||
|
result.searchText = text;
|
||||||
|
PhotoModel.find({
|
||||||
|
name: {
|
||||||
|
$regex: text,
|
||||||
|
$options: "i"
|
||||||
|
}
|
||||||
|
}).populate('directory', 'name path').exec((err, res:Array<any>) => {
|
||||||
|
if (err || !res) {
|
||||||
|
return cb(err, null);
|
||||||
|
}
|
||||||
|
result.photos = res;
|
||||||
|
|
||||||
|
DirectoryModel.find({
|
||||||
|
name: {
|
||||||
|
$regex: text,
|
||||||
|
$options: "i"
|
||||||
|
}
|
||||||
|
}).select('name').exec((err, res:Array<any>) => {
|
||||||
|
if (err || !res) {
|
||||||
|
return cb(err, null);
|
||||||
|
}
|
||||||
|
result.directories = res;
|
||||||
|
return cb(null, result);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
instantSearch(text, cb:(error:any, result:SearchResult) => void) {
|
||||||
|
console.log("instantSearch: " + text);
|
||||||
|
let result:SearchResult = new SearchResult();
|
||||||
|
result.searchText = text;
|
||||||
|
PhotoModel.find({
|
||||||
|
name: {
|
||||||
|
$regex: text,
|
||||||
|
$options: "i"
|
||||||
|
}
|
||||||
|
}).limit(10).populate('directory', 'name path').exec((err, res:Array<any>) => {
|
||||||
|
if (err || !res) {
|
||||||
|
return cb(err, null);
|
||||||
|
}
|
||||||
|
result.photos = res;
|
||||||
|
|
||||||
|
DirectoryModel.find({
|
||||||
|
name: {
|
||||||
|
$regex: text,
|
||||||
|
$options: "i"
|
||||||
|
}
|
||||||
|
}).limit(10).exec((err, res:Array<any>) => {
|
||||||
|
if (err || !res) {
|
||||||
|
return cb(err, null);
|
||||||
|
}
|
||||||
|
result.directories = res;
|
||||||
|
return cb(null, result);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private encapsulateAutoComplete(values:Array<string>, type:AutoCompeleteTypes) {
|
private encapsulateAutoComplete(values:Array<string>, type:AutoCompeleteTypes) {
|
||||||
let res = [];
|
let res = [];
|
||||||
values.forEach((value)=> {
|
values.forEach((value)=> {
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import {DatabaseManager} from "../DatabaseManager";
|
import {DatabaseManager} from "../DatabaseManager";
|
||||||
|
import {Schema} from "mongoose";
|
||||||
|
|
||||||
|
|
||||||
export var PhotoModel = DatabaseManager.getInstance().getModel('photo',{
|
export var PhotoModel = DatabaseManager.getInstance().getModel('photo',{
|
||||||
name:String,
|
name:String,
|
||||||
width:Number,
|
width:Number,
|
||||||
height:Number
|
height: Number,
|
||||||
|
directory: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: 'directory'
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ export class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static updateKeys(targetObject, sourceObject) {
|
public static updateKeys(targetObject, sourceObject) {
|
||||||
Object.keys(sourceObject).forEach((key)=> {
|
Object.keys(sourceObject).forEach((key)=> {
|
||||||
if (typeof targetObject[key] === "undefined") {
|
if (typeof targetObject[key] === "undefined") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import {Utils} from "../Utils";
|
import {Utils} from "../Utils";
|
||||||
import {Directory} from "./Directory";
|
import {Directory} from "./Directory";
|
||||||
export class Photo {
|
export class Photo {
|
||||||
constructor(public id:number, public name:string, public width:number, public height:number) {
|
constructor(public id?:number, public name?:string, public directory?:Directory, public width?:number, public height?:number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getThumbnailPath(directory:Directory, photo:Photo) {
|
public static getThumbnailPath(photo:Photo) {
|
||||||
return Utils.concatUrls("/api/gallery/content/", directory.path, directory.name, photo.name, "thumbnail");
|
return Utils.concatUrls("/api/gallery/content/", photo.directory.path, photo.directory.name, photo.name, "thumbnail");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getPhotoPath(directory:Directory, photo:Photo) {
|
public static getPhotoPath(photo:Photo) {
|
||||||
return Utils.concatUrls("/api/gallery/content/", directory.path, directory.name, photo.name);
|
return Utils.concatUrls("/api/gallery/content/", photo.directory.path, photo.directory.name, photo.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,11 +2,8 @@ import {Directory} from "./Directory";
|
|||||||
import {Photo} from "./Photo";
|
import {Photo} from "./Photo";
|
||||||
export class SearchResult {
|
export class SearchResult {
|
||||||
|
|
||||||
|
public searchText:string;
|
||||||
public directories:Array<Directory>;
|
public directories:Array<Directory>;
|
||||||
public photos:Array<Photo>;
|
public photos:Array<Photo>;
|
||||||
|
|
||||||
constructor(directories:Array<Directory>, photos:Array<Photo>) {
|
|
||||||
this.directories = directories;
|
|
||||||
this.photos = photos;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,6 +7,14 @@
|
|||||||
<div *ngFor="let directory of _galleryService.content.directory.directories">
|
<div *ngFor="let directory of _galleryService.content.directory.directories">
|
||||||
<gallery-directory *ngIf="directory" [directory]="directory"></gallery-directory>
|
<gallery-directory *ngIf="directory" [directory]="directory"></gallery-directory>
|
||||||
</div>
|
</div>
|
||||||
<gallery-grid [directory]="_galleryService.content.directory" [lightbox]="lightbox"></gallery-grid>
|
<gallery-grid [photos]="_galleryService.content.directory.photos" [lightbox]="lightbox"></gallery-grid>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div body class="container" style="width: 100%; padding:0" *ngIf="_galleryService.content.searchResult">
|
||||||
|
<div> Searching for: {{_galleryService.content.searchResult.searchText}}</div>
|
||||||
|
<div *ngFor="let directory of _galleryService.content.searchResult.directories">
|
||||||
|
<gallery-directory *ngIf="directory" [directory]="directory"></gallery-directory>
|
||||||
|
</div>
|
||||||
|
<gallery-grid [photos]="_galleryService.content.searchResult.photos" [lightbox]="lightbox"></gallery-grid>
|
||||||
</div>
|
</div>
|
||||||
</app-frame>
|
</app-frame>
|
@ -4,12 +4,16 @@ import {Injectable} from "@angular/core";
|
|||||||
import {NetworkService} from "../model/network/network.service.ts";
|
import {NetworkService} from "../model/network/network.service.ts";
|
||||||
import {Message} from "../../../common/entities/Message";
|
import {Message} from "../../../common/entities/Message";
|
||||||
import {ContentWrapper} from "../../../common/entities/ConentWrapper";
|
import {ContentWrapper} from "../../../common/entities/ConentWrapper";
|
||||||
|
import {Photo} from "../../../common/entities/Photo";
|
||||||
|
import {Directory} from "../../../common/entities/Directory";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GalleryService {
|
export class GalleryService {
|
||||||
|
|
||||||
public content:ContentWrapper;
|
public content:ContentWrapper;
|
||||||
|
private lastDirectory:Directory;
|
||||||
|
private searchId:any;
|
||||||
|
|
||||||
constructor(private _networkService:NetworkService) {
|
constructor(private _networkService:NetworkService) {
|
||||||
this.content = new ContentWrapper();
|
this.content = new ContentWrapper();
|
||||||
}
|
}
|
||||||
@ -18,13 +22,21 @@ export class GalleryService {
|
|||||||
return this._networkService.getJson("/gallery/content/" + directoryName).then(
|
return this._networkService.getJson("/gallery/content/" + directoryName).then(
|
||||||
(message:Message<ContentWrapper>) => {
|
(message:Message<ContentWrapper>) => {
|
||||||
if (!message.error && message.result) {
|
if (!message.error && message.result) {
|
||||||
|
message.result.directory.photos.forEach((photo:Photo) => {
|
||||||
|
photo.directory = message.result.directory;
|
||||||
|
});
|
||||||
|
this.lastDirectory = message.result.directory;
|
||||||
this.content = message.result;
|
this.content = message.result;
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: cache
|
||||||
public search(text:string):Promise<Message<ContentWrapper>> {
|
public search(text:string):Promise<Message<ContentWrapper>> {
|
||||||
|
if (text === null || text === '') {
|
||||||
|
return Promise.resolve(new Message(null, null));
|
||||||
|
}
|
||||||
return this._networkService.getJson("/gallery/search/" + text).then(
|
return this._networkService.getJson("/gallery/search/" + text).then(
|
||||||
(message:Message<ContentWrapper>) => {
|
(message:Message<ContentWrapper>) => {
|
||||||
if (!message.error && message.result) {
|
if (!message.error && message.result) {
|
||||||
@ -34,7 +46,24 @@ export class GalleryService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: cache (together with normal search)
|
||||||
public instantSearch(text:string):Promise<Message<ContentWrapper>> {
|
public instantSearch(text:string):Promise<Message<ContentWrapper>> {
|
||||||
|
if (text === null || text === '') {
|
||||||
|
this.content.directory = this.lastDirectory;
|
||||||
|
this.content.searchResult = null;
|
||||||
|
clearTimeout(this.searchId);
|
||||||
|
return Promise.resolve(new Message(null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.searchId != null) {
|
||||||
|
clearTimeout(this.searchId);
|
||||||
|
|
||||||
|
}
|
||||||
|
this.searchId = setTimeout(() => {
|
||||||
|
this.search(text);
|
||||||
|
this.searchId = null;
|
||||||
|
}, 3000); //TODO: set timeout to config
|
||||||
|
|
||||||
return this._networkService.getJson("/gallery/instant-search/" + text).then(
|
return this._networkService.getJson("/gallery/instant-search/" + text).then(
|
||||||
(message:Message<ContentWrapper>) => {
|
(message:Message<ContentWrapper>) => {
|
||||||
if (!message.error && message.result) {
|
if (!message.error && message.result) {
|
||||||
@ -42,6 +71,7 @@ export class GalleryService {
|
|||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
*ngFor="let gridPhoto of photosToRender"
|
*ngFor="let gridPhoto of photosToRender"
|
||||||
(click)="lightbox.show(gridPhoto.photo)"
|
(click)="lightbox.show(gridPhoto.photo)"
|
||||||
[photo]="gridPhoto.photo"
|
[photo]="gridPhoto.photo"
|
||||||
[directory]="directory"
|
|
||||||
[style.width.px]="gridPhoto.renderWidth"
|
[style.width.px]="gridPhoto.renderWidth"
|
||||||
[style.height.px]="gridPhoto.renderHeight"
|
[style.height.px]="gridPhoto.renderHeight"
|
||||||
[style.marginLeft.px]="IMAGE_MARGIN"
|
[style.marginLeft.px]="IMAGE_MARGIN"
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
QueryList,
|
QueryList,
|
||||||
AfterViewInit
|
AfterViewInit
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import {Directory} from "../../../../common/entities/Directory";
|
|
||||||
import {Photo} from "../../../../common/entities/Photo";
|
import {Photo} from "../../../../common/entities/Photo";
|
||||||
import {GalleryPhotoComponent} from "../photo/photo.gallery.component";
|
import {GalleryPhotoComponent} from "../photo/photo.gallery.component";
|
||||||
import {GridRowBuilder} from "./GridRowBuilder";
|
import {GridRowBuilder} from "./GridRowBuilder";
|
||||||
@ -27,7 +26,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
@ViewChild('gridContainer') gridContainer:ElementRef;
|
@ViewChild('gridContainer') gridContainer:ElementRef;
|
||||||
@ViewChildren(GalleryPhotoComponent) gridPhotoQL:QueryList<GalleryPhotoComponent>;
|
@ViewChildren(GalleryPhotoComponent) gridPhotoQL:QueryList<GalleryPhotoComponent>;
|
||||||
|
|
||||||
@Input() directory:Directory;
|
@Input() photos:Array<Photo>;
|
||||||
@Input() lightbox:GalleryLightboxComponent;
|
@Input() lightbox:GalleryLightboxComponent;
|
||||||
|
|
||||||
photosToRender:Array<GridPhoto> = [];
|
photosToRender:Array<GridPhoto> = [];
|
||||||
@ -41,7 +40,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
// this.renderPhotos();
|
this.renderPhotos();
|
||||||
}
|
}
|
||||||
|
|
||||||
onResize() {
|
onResize() {
|
||||||
@ -92,9 +91,9 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
this.photosToRender = [];
|
this.photosToRender = [];
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
while (i < this.directory.photos.length) {
|
while (i < this.photos.length) {
|
||||||
|
|
||||||
let photoRowBuilder = new GridRowBuilder(this.directory.photos, i, this.IMAGE_MARGIN, containerWidth);
|
let photoRowBuilder = new GridRowBuilder(this.photos, i, this.IMAGE_MARGIN, containerWidth);
|
||||||
photoRowBuilder.addPhotos(this.TARGET_COL_COUNT);
|
photoRowBuilder.addPhotos(this.TARGET_COL_COUNT);
|
||||||
photoRowBuilder.adjustRowHeightBetween(minRowHeight, maxRowHeight);
|
photoRowBuilder.adjustRowHeightBetween(minRowHeight, maxRowHeight);
|
||||||
|
|
||||||
|
@ -150,14 +150,14 @@ export class GalleryLightboxComponent {
|
|||||||
if (!this.activePhoto) {
|
if (!this.activePhoto) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return Photo.getPhotoPath(this.activePhoto.directory, this.activePhoto.photo);
|
return Photo.getPhotoPath(this.activePhoto.photo);
|
||||||
}
|
}
|
||||||
|
|
||||||
getThumbnailPath() {
|
getThumbnailPath() {
|
||||||
if (!this.activePhoto) {
|
if (!this.activePhoto) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return Photo.getThumbnailPath(this.activePhoto.directory, this.activePhoto.photo);
|
return Photo.getThumbnailPath(this.activePhoto.photo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getBodyScrollTop() {
|
private getBodyScrollTop() {
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import {Component, Input, ElementRef, ViewChild} from "@angular/core";
|
import {Component, Input, ElementRef, ViewChild} from "@angular/core";
|
||||||
import {Photo} from "../../../../common/entities/Photo";
|
import {Photo} from "../../../../common/entities/Photo";
|
||||||
import {Directory} from "../../../../common/entities/Directory";
|
|
||||||
import {IRenderable, Dimension} from "../../model/IRenderable";
|
import {IRenderable, Dimension} from "../../model/IRenderable";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -11,15 +10,14 @@ import {IRenderable, Dimension} from "../../model/IRenderable";
|
|||||||
styleUrls: ['app/gallery/photo/photo.gallery.component.css'],
|
styleUrls: ['app/gallery/photo/photo.gallery.component.css'],
|
||||||
})
|
})
|
||||||
export class GalleryPhotoComponent implements IRenderable {
|
export class GalleryPhotoComponent implements IRenderable {
|
||||||
@Input() photo:Photo;
|
@Input() photo:Photo;
|
||||||
@Input() directory:Directory;
|
|
||||||
@ViewChild("image") imageRef:ElementRef;
|
@ViewChild("image") imageRef:ElementRef;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
getPhotoPath() {
|
getPhotoPath() {
|
||||||
return Photo.getThumbnailPath(this.directory, this.photo);
|
return Photo.getThumbnailPath(this.photo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<div class="col-sm-4 col-md-5 pull-right">
|
<div class="col-sm-4 col-md-5 pull-right">
|
||||||
<form class="navbar-form" role="search">
|
<form class="navbar-form" role="search" #SearchForm="ngForm">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="form-control" placeholder="Search" (keyup)="getSuggestions($event)" (blur)="onFocusLost($event)"
|
<input type="text" class="form-control" placeholder="Search" (keyup)="onSearchChange($event)"
|
||||||
name="srch-term" id="srch-term" autocomplete="off" >
|
(blur)="onFocusLost($event)" [(ngModel)]="searchText" #name="ngForm" ngControl="search"
|
||||||
|
name="srch-term" id="srch-term" autocomplete="off" >
|
||||||
|
|
||||||
<div class="autocomplete-list" *ngIf="autoCompleteItems.length > 0" >
|
<div class="autocomplete-list" *ngIf="autoCompleteItems.length > 0" >
|
||||||
<div class="autocomplete-item" *ngFor="let item of autoCompleteItems">
|
<div class="autocomplete-item" *ngFor="let item of autoCompleteItems">
|
||||||
@ -11,7 +12,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group-btn" style="display: block">
|
<div class="input-group-btn" style="display: block">
|
||||||
<button class="btn btn-default dropdown-toggle" type="button"><i class="glyphicon glyphicon-search"></i>
|
<button class="btn btn-default dropdown-toggle" type="button" (click)="onSearch()"><i
|
||||||
|
class="glyphicon glyphicon-search"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,21 +4,25 @@ import {Component} from "@angular/core";
|
|||||||
import {AutoCompleteService} from "./autocomplete.service";
|
import {AutoCompleteService} from "./autocomplete.service";
|
||||||
import {AutoCompleteItem} from "../../../../common/entities/AutoCompleteItem";
|
import {AutoCompleteItem} from "../../../../common/entities/AutoCompleteItem";
|
||||||
import {Message} from "../../../../common/entities/Message";
|
import {Message} from "../../../../common/entities/Message";
|
||||||
|
import {GalleryService} from "../gallery.service";
|
||||||
|
import {FORM_DIRECTIVES} from "@angular/common";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'gallery-search',
|
selector: 'gallery-search',
|
||||||
templateUrl: 'app/gallery/search/search.gallery.component.html',
|
templateUrl: 'app/gallery/search/search.gallery.component.html',
|
||||||
styleUrls: ['app/gallery/search/search.gallery.component.css'],
|
styleUrls: ['app/gallery/search/search.gallery.component.css'],
|
||||||
providers: [AutoCompleteService]
|
providers: [AutoCompleteService],
|
||||||
|
directives: [FORM_DIRECTIVES]
|
||||||
})
|
})
|
||||||
export class GallerySearchComponent {
|
export class GallerySearchComponent {
|
||||||
|
|
||||||
autoCompleteItems:Array<AutoCompleteRenderItem> = [];
|
autoCompleteItems:Array<AutoCompleteRenderItem> = [];
|
||||||
|
private searchText:string = "";
|
||||||
|
|
||||||
constructor(private _autoCompleteService:AutoCompleteService) {
|
constructor(private _autoCompleteService:AutoCompleteService, private _galleryService:GalleryService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
getSuggestions(event:KeyboardEvent) {
|
onSearchChange(event:KeyboardEvent) {
|
||||||
let searchText = (<HTMLInputElement>event.target).value;
|
let searchText = (<HTMLInputElement>event.target).value;
|
||||||
if (searchText.trim().length > 0) {
|
if (searchText.trim().length > 0) {
|
||||||
this._autoCompleteService.autoComplete(searchText).then((message:Message<Array<AutoCompleteItem>>) => {
|
this._autoCompleteService.autoComplete(searchText).then((message:Message<Array<AutoCompleteItem>>) => {
|
||||||
@ -32,8 +36,14 @@ export class GallerySearchComponent {
|
|||||||
} else {
|
} else {
|
||||||
this.emptyAutoComplete();
|
this.emptyAutoComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._galleryService.instantSearch(searchText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onSearch() {
|
||||||
|
this._galleryService.search(this.searchText);
|
||||||
|
}
|
||||||
|
|
||||||
private showSuggestions(suggestions:Array<AutoCompleteItem>, searchText:string) {
|
private showSuggestions(suggestions:Array<AutoCompleteItem>, searchText:string) {
|
||||||
this.emptyAutoComplete();
|
this.emptyAutoComplete();
|
||||||
suggestions.forEach((item)=> {
|
suggestions.forEach((item)=> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user