diff --git a/backend/model/DiskManger.ts b/backend/model/DiskManger.ts index a7397f60..38d7f1ce 100644 --- a/backend/model/DiskManger.ts +++ b/backend/model/DiskManger.ts @@ -26,7 +26,7 @@ export class DiskManager { let directory = { name: directoryName, path: directoryParent, - lastUpdate: new Date(), + lastUpdate: Date.now(), directories: [], photos: [] }; @@ -46,7 +46,7 @@ export class DiskManager { directory.directories.push({ name: file, path: relativeDirectoryName, - lastUpdate: new Date(), + lastUpdate: Date.now(), directories: [], photos: [] }); @@ -85,11 +85,9 @@ export class DiskManager { let extension = mime.lookup(fullPath); - if (imageMimeTypes.indexOf(extension) !== -1) { - return true; - } + return imageMimeTypes.indexOf(extension) !== -1; + - return false; } /* @@ -168,7 +166,7 @@ export class DiskManager { }; let keywords: [string] = iptcData.keywords.map((s: string) => decode(s)); - let creationDate: Date = iptcData.date_time; + let creationDate: number = iptcData.date_time.getTime(); let metadata: PhotoMetadata = { diff --git a/backend/model/mysql/GalleryManager.ts b/backend/model/mysql/GalleryManager.ts index bf0f64e5..ac125799 100644 --- a/backend/model/mysql/GalleryManager.ts +++ b/backend/model/mysql/GalleryManager.ts @@ -1,7 +1,7 @@ import {IGalleryManager} from "../interfaces/IGalleryManager"; import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import * as path from "path"; -import {DirectoryEnitity} from "./enitites/DirectoryEntity"; +import {DirectoryEntity} from "./enitites/DirectoryEntity"; import {MySQLConnection} from "./MySQLConnection"; import {DiskManager} from "../DiskManger"; import {PhotoEntity} from "./enitites/PhotoEntity"; @@ -18,7 +18,7 @@ export class GalleryManager implements IGalleryManager { MySQLConnection.getConnection().then(async connection => { let dir = await connection - .getRepository(DirectoryEnitity) + .getRepository(DirectoryEntity) .createQueryBuilder("directory_entity") .where("directory_entity.name = :name AND directory_entity.path = :path", { name: directoryName, @@ -54,7 +54,7 @@ export class GalleryManager implements IGalleryManager { DiskManager.scanDirectory(relativeDirectoryName, (err, scannedDirectory) => { MySQLConnection.getConnection().then(async connection => { - let directoryRepository = connection.getRepository(DirectoryEnitity); + let directoryRepository = connection.getRepository(DirectoryEntity); let photosRepository = connection.getRepository(PhotoEntity); let parentDir = await directoryRepository.persist(scannedDirectory); diff --git a/backend/model/mysql/MySQLConnection.ts b/backend/model/mysql/MySQLConnection.ts index b7b5ed29..51ec06b8 100644 --- a/backend/model/mysql/MySQLConnection.ts +++ b/backend/model/mysql/MySQLConnection.ts @@ -4,7 +4,7 @@ import {Config} from "../../config/Config"; import {UserEntity} from "./enitites/UserEntity"; import {UserRoles} from "../../../common/entities/UserDTO"; import {PhotoEntity, PhotoMetadataEntity} from "./enitites/PhotoEntity"; -import {DirectoryEnitity} from "./enitites/DirectoryEntity"; +import {DirectoryEntity} from "./enitites/DirectoryEntity"; export class MySQLConnection { @@ -34,7 +34,7 @@ export class MySQLConnection { }, entities: [ UserEntity, - DirectoryEnitity, + DirectoryEntity, PhotoMetadataEntity, PhotoEntity ], diff --git a/backend/model/mysql/SearchManager.ts b/backend/model/mysql/SearchManager.ts index 899ca9c8..24376924 100644 --- a/backend/model/mysql/SearchManager.ts +++ b/backend/model/mysql/SearchManager.ts @@ -3,7 +3,7 @@ import {ISearchManager} from "../interfaces/ISearchManager"; import {SearchResultDTO} from "../../../common/entities/SearchResult"; import {MySQLConnection} from "./MySQLConnection"; import {PhotoEntity} from "./enitites/PhotoEntity"; -import {DirectoryEnitity} from "./enitites/DirectoryEntity"; +import {DirectoryEntity} from "./enitites/DirectoryEntity"; import {PositionMetaData} from "../../../common/entities/PhotoDTO"; export class SearchManager implements ISearchManager { @@ -15,7 +15,7 @@ export class SearchManager implements ISearchManager { try { let result: Array = []; let photoRepository = connection.getRepository(PhotoEntity); - let directoryRepository = connection.getRepository(DirectoryEnitity); + let directoryRepository = connection.getRepository(DirectoryEntity); (await photoRepository @@ -71,11 +71,101 @@ export class SearchManager implements ISearchManager { } search(text: string, searchType: SearchTypes, cb: (error: any, result: SearchResultDTO) => void) { - throw new Error("not implemented"); + MySQLConnection.getConnection().then(async connection => { + + let result: SearchResultDTO = { + searchText: text, + searchType: searchType, + directories: [], + photos: [] + }; + + let query = connection + .getRepository(PhotoEntity) + .createQueryBuilder("photo"); + + + if (!searchType || searchType === SearchTypes.image) { + query.orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}); + } + + if (!searchType || searchType === SearchTypes.position) { + query.orWhere('photo.metadata.positionData LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}); + } + if (!searchType || searchType === SearchTypes.keyword) { + query.orWhere('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}); + } + let photos = await query + .innerJoinAndSelect("photo.directory", "directory") + .getMany(); + + + if (photos) { + for (let i = 0; i < photos.length; i++) { + photos[i].metadata.keywords = JSON.parse(photos[i].metadata.keywords); + photos[i].metadata.cameraData = JSON.parse(photos[i].metadata.cameraData); + photos[i].metadata.positionData = JSON.parse(photos[i].metadata.positionData); + photos[i].metadata.size = JSON.parse(photos[i].metadata.size); + } + result.photos = photos; + } + + result.directories = await connection + .getRepository(DirectoryEntity) + .createQueryBuilder("dir") + .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) + .getMany(); + + + return cb(null, result); + }).catch((error) => { + return cb(error, null); + }); } instantSearch(text: string, cb: (error: any, result: SearchResultDTO) => void) { - throw new Error("not implemented"); + MySQLConnection.getConnection().then(async connection => { + + let result: SearchResultDTO = { + searchText: text, + directories: [], + photos: [] + }; + + let photos = await connection + .getRepository(PhotoEntity) + .createQueryBuilder("photo") + .where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) + .orWhere('photo.metadata.positionData LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) + .orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) + .innerJoinAndSelect("photo.directory", "directory") + .setLimit(10) + .getMany(); + + + if (photos) { + for (let i = 0; i < photos.length; i++) { + photos[i].metadata.keywords = JSON.parse(photos[i].metadata.keywords); + photos[i].metadata.cameraData = JSON.parse(photos[i].metadata.cameraData); + photos[i].metadata.positionData = JSON.parse(photos[i].metadata.positionData); + photos[i].metadata.size = JSON.parse(photos[i].metadata.size); + } + result.photos = photos; + } + + let directories = await connection + .getRepository(DirectoryEntity) + .createQueryBuilder("dir") + .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) + .setLimit(10) + .getMany(); + + result.directories = directories; + + return cb(null, result); + }).catch((error) => { + return cb(error, null); + }); } private encapsulateAutoComplete(values: Array, type: SearchTypes) { diff --git a/backend/model/mysql/enitites/DirectoryEntity.ts b/backend/model/mysql/enitites/DirectoryEntity.ts index 7c950235..a8fffbd1 100644 --- a/backend/model/mysql/enitites/DirectoryEntity.ts +++ b/backend/model/mysql/enitites/DirectoryEntity.ts @@ -3,7 +3,7 @@ import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; import {PhotoEntity} from "./PhotoEntity"; @Table() -export class DirectoryEnitity implements DirectoryDTO { +export class DirectoryEntity implements DirectoryDTO { @PrimaryGeneratedColumn() id: number; @@ -19,14 +19,14 @@ export class DirectoryEnitity implements DirectoryDTO { path: string; - @Column('datetime') - public lastUpdate: Date; + @Column('number') + public lastUpdate: number; - @ManyToOne(type => DirectoryEnitity, directory => directory.directories) - public parent: DirectoryEnitity; + @ManyToOne(type => DirectoryEntity, directory => directory.directories) + public parent: DirectoryEntity; - @OneToMany(type => DirectoryEnitity, dir => dir.parent) - public directories: Array; + @OneToMany(type => DirectoryEntity, dir => dir.parent) + public directories: Array; @OneToMany(type => PhotoEntity, photo => photo.directory) public photos: Array; diff --git a/backend/model/mysql/enitites/PhotoEntity.ts b/backend/model/mysql/enitites/PhotoEntity.ts index 18121f98..e2ed01fa 100644 --- a/backend/model/mysql/enitites/PhotoEntity.ts +++ b/backend/model/mysql/enitites/PhotoEntity.ts @@ -7,7 +7,7 @@ import { ImageSize, PositionMetaData } from "../../../../common/entities/PhotoDTO"; -import {DirectoryEnitity} from "./DirectoryEntity"; +import {DirectoryEntity} from "./DirectoryEntity"; @Table() export class PhotoEntity implements PhotoDTO { @@ -18,7 +18,7 @@ export class PhotoEntity implements PhotoDTO { @Column("string") name: string; - @ManyToOne(type => DirectoryEnitity, directory => directory.photos) + @ManyToOne(type => DirectoryEntity, directory => directory.photos) directory: DirectoryDTO; @Embedded(type => PhotoMetadataEntity) @@ -44,8 +44,8 @@ export class PhotoMetadataEntity implements PhotoMetadata { @Column("string") size: ImageSize; - @Column("datetime") - creationDate: Date; + @Column("number") + creationDate: number; } /* diff --git a/backend/server.ts b/backend/server.ts index 3f8143f2..b1cb5d92 100644 --- a/backend/server.ts +++ b/backend/server.ts @@ -94,7 +94,7 @@ export class Server { throw error; } - var bind = typeof Config.Server.port === 'string' + const bind = typeof Config.Server.port === 'string' ? 'Pipe ' + Config.Server.port : 'Port ' + Config.Server.port; @@ -118,8 +118,8 @@ export class Server { * Event listener for HTTP server "listening" event. */ private onListening = () => { - var addr = this.server.address(); - var bind = typeof addr === 'string' + let addr = this.server.address(); + const bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; this.debug('Listening on ' + bind); diff --git a/common/entities/AutoCompleteItem.ts b/common/entities/AutoCompleteItem.ts index d6bbf5af..4dc165b7 100644 --- a/common/entities/AutoCompleteItem.ts +++ b/common/entities/AutoCompleteItem.ts @@ -1,8 +1,8 @@ export enum SearchTypes { - image, - directory, - keyword, - position + directory = 1, + keyword = 2, + position = 3, + image = 4 } export class AutoCompleteItem { diff --git a/common/entities/DirectoryDTO.ts b/common/entities/DirectoryDTO.ts index 658b461b..51b85430 100644 --- a/common/entities/DirectoryDTO.ts +++ b/common/entities/DirectoryDTO.ts @@ -4,7 +4,7 @@ export interface DirectoryDTO { id: number; name: string; path: string; - lastUpdate: Date; + lastUpdate: number; parent: DirectoryDTO; directories: Array; photos: Array; diff --git a/common/entities/PhotoDTO.ts b/common/entities/PhotoDTO.ts index d4d419ea..fccf06a3 100644 --- a/common/entities/PhotoDTO.ts +++ b/common/entities/PhotoDTO.ts @@ -13,7 +13,7 @@ export interface PhotoMetadata { cameraData: CameraMetadata; positionData: PositionMetaData; size: ImageSize; - creationDate: Date; + creationDate: number; } export interface ImageSize { diff --git a/frontend/app/gallery/cache.gallery.service.ts b/frontend/app/gallery/cache.gallery.service.ts index feb956d7..bf6f08f9 100644 --- a/frontend/app/gallery/cache.gallery.service.ts +++ b/frontend/app/gallery/cache.gallery.service.ts @@ -17,9 +17,6 @@ export class GalleryCacheService { let directory: DirectoryDTO = JSON.parse(value); - directory.photos.forEach((photo: PhotoDTO) => { - photo.metadata.creationDate = new Date(photo.metadata.creationDate); - }); directory.photos.forEach((photo: PhotoDTO) => { photo.directory = directory; diff --git a/frontend/app/gallery/gallery.service.ts b/frontend/app/gallery/gallery.service.ts index e10c8ef2..2003b033 100644 --- a/frontend/app/gallery/gallery.service.ts +++ b/frontend/app/gallery/gallery.service.ts @@ -38,10 +38,6 @@ export class GalleryService { } - message.result.directory.photos.forEach((photo: PhotoDTO) => { - photo.metadata.creationDate = new Date(photo.metadata.creationDate); - }); - message.result.directory.photos.forEach((photo: PhotoDTO) => { photo.directory = message.result.directory; }); diff --git a/frontend/app/gallery/grid/grid.gallery.component.ts b/frontend/app/gallery/grid/grid.gallery.component.ts index e45224ab..fb889086 100644 --- a/frontend/app/gallery/grid/grid.gallery.component.ts +++ b/frontend/app/gallery/grid/grid.gallery.component.ts @@ -88,7 +88,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit { private sortPhotos() { //sort pohots by date this.photos.sort((a: PhotoDTO, b: PhotoDTO) => { - return a.metadata.creationDate.getTime() - b.metadata.creationDate.getTime(); + return a.metadata.creationDate - b.metadata.creationDate; }); } diff --git a/frontend/app/gallery/grid/photo/photo.grid.gallery.component.html b/frontend/app/gallery/grid/photo/photo.grid.gallery.component.html index 210de9be..532a8bea 100644 --- a/frontend/app/gallery/grid/photo/photo.grid.gallery.component.html +++ b/frontend/app/gallery/grid/photo/photo.grid.gallery.component.html @@ -12,7 +12,7 @@