adding persons support for frontend
@ -113,7 +113,7 @@ export class ObjectManagerRepository {
|
|||||||
const UserManager = require('./sql/UserManager').UserManager;
|
const UserManager = require('./sql/UserManager').UserManager;
|
||||||
const SearchManager = require('./sql/SearchManager').SearchManager;
|
const SearchManager = require('./sql/SearchManager').SearchManager;
|
||||||
const SharingManager = require('./sql/SharingManager').SharingManager;
|
const SharingManager = require('./sql/SharingManager').SharingManager;
|
||||||
const IndexingTaskManager = require('./sql/IndexingManager').IndexingTaskManager;
|
const IndexingTaskManager = require('./sql/IndexingTaskManager').IndexingTaskManager;
|
||||||
const IndexingManager = require('./sql/IndexingManager').IndexingManager;
|
const IndexingManager = require('./sql/IndexingManager').IndexingManager;
|
||||||
const PersonManager = require('./sql/PersonManager').PersonManager;
|
const PersonManager = require('./sql/PersonManager').PersonManager;
|
||||||
ObjectManagerRepository.getInstance().GalleryManager = new GalleryManager();
|
ObjectManagerRepository.getInstance().GalleryManager = new GalleryManager();
|
||||||
|
@ -6,6 +6,8 @@ import {PhotoEntity} from './enitites/PhotoEntity';
|
|||||||
import {DirectoryEntity} from './enitites/DirectoryEntity';
|
import {DirectoryEntity} from './enitites/DirectoryEntity';
|
||||||
import {MediaEntity} from './enitites/MediaEntity';
|
import {MediaEntity} from './enitites/MediaEntity';
|
||||||
import {VideoEntity} from './enitites/VideoEntity';
|
import {VideoEntity} from './enitites/VideoEntity';
|
||||||
|
import {PersonEntry} from './enitites/PersonEntry';
|
||||||
|
import {FaceRegionEntry} from './enitites/FaceRegionEntry';
|
||||||
|
|
||||||
export class SearchManager implements ISearchManager {
|
export class SearchManager implements ISearchManager {
|
||||||
|
|
||||||
@ -29,7 +31,7 @@ export class SearchManager implements ISearchManager {
|
|||||||
let result: AutoCompleteItem[] = [];
|
let result: AutoCompleteItem[] = [];
|
||||||
const photoRepository = connection.getRepository(PhotoEntity);
|
const photoRepository = connection.getRepository(PhotoEntity);
|
||||||
const videoRepository = connection.getRepository(VideoEntity);
|
const videoRepository = connection.getRepository(VideoEntity);
|
||||||
const mediaRepository = connection.getRepository(MediaEntity);
|
const personRepository = connection.getRepository(PersonEntry);
|
||||||
const directoryRepository = connection.getRepository(DirectoryEntity);
|
const directoryRepository = connection.getRepository(DirectoryEntity);
|
||||||
|
|
||||||
|
|
||||||
@ -45,6 +47,14 @@ export class SearchManager implements ISearchManager {
|
|||||||
.filter(k => k.toLowerCase().indexOf(text.toLowerCase()) !== -1), SearchTypes.keyword));
|
.filter(k => k.toLowerCase().indexOf(text.toLowerCase()) !== -1), SearchTypes.keyword));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
result = result.concat(this.encapsulateAutoComplete((await personRepository
|
||||||
|
.createQueryBuilder('person')
|
||||||
|
.select('DISTINCT(person.name)')
|
||||||
|
.where('person.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
||||||
|
.limit(5)
|
||||||
|
.getRawMany())
|
||||||
|
.map(r => r.name), SearchTypes.person));
|
||||||
|
|
||||||
(await photoRepository
|
(await photoRepository
|
||||||
.createQueryBuilder('photo')
|
.createQueryBuilder('photo')
|
||||||
.select('photo.metadata.positionData.country as country, ' +
|
.select('photo.metadata.positionData.country as country, ' +
|
||||||
@ -112,16 +122,19 @@ export class SearchManager implements ISearchManager {
|
|||||||
resultOverflow: false
|
resultOverflow: false
|
||||||
};
|
};
|
||||||
|
|
||||||
let repostiroy = connection.getRepository(MediaEntity);
|
let repository = connection.getRepository(MediaEntity);
|
||||||
|
const faceRepository = connection.getRepository(FaceRegionEntry);
|
||||||
|
|
||||||
if (searchType === SearchTypes.photo) {
|
if (searchType === SearchTypes.photo) {
|
||||||
repostiroy = connection.getRepository(PhotoEntity);
|
repository = connection.getRepository(PhotoEntity);
|
||||||
} else if (searchType === SearchTypes.video) {
|
} else if (searchType === SearchTypes.video) {
|
||||||
repostiroy = connection.getRepository(VideoEntity);
|
repository = connection.getRepository(VideoEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = repostiroy.createQueryBuilder('media')
|
const query = repository.createQueryBuilder('media')
|
||||||
.innerJoinAndSelect('media.directory', 'directory')
|
.leftJoinAndSelect('media.directory', 'directory')
|
||||||
|
.leftJoin('media.metadata.faces', 'faces')
|
||||||
|
.leftJoin('faces.person', 'person')
|
||||||
.orderBy('media.metadata.creationDate', 'ASC');
|
.orderBy('media.metadata.creationDate', 'ASC');
|
||||||
|
|
||||||
|
|
||||||
@ -136,6 +149,9 @@ export class SearchManager implements ISearchManager {
|
|||||||
if (!searchType || searchType === SearchTypes.photo) {
|
if (!searchType || searchType === SearchTypes.photo) {
|
||||||
query.orWhere('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
query.orWhere('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
||||||
}
|
}
|
||||||
|
if (!searchType || searchType === SearchTypes.person) {
|
||||||
|
query.orWhere('person.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
||||||
|
}
|
||||||
|
|
||||||
if (!searchType || searchType === SearchTypes.position) {
|
if (!searchType || searchType === SearchTypes.position) {
|
||||||
query.orWhere('media.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
query.orWhere('media.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
||||||
@ -147,9 +163,20 @@ export class SearchManager implements ISearchManager {
|
|||||||
query.orWhere('media.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
query.orWhere('media.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
||||||
}
|
}
|
||||||
|
|
||||||
result.media = await query
|
|
||||||
.limit(2001)
|
result.media = (await query
|
||||||
.getMany();
|
.limit(5000).getMany()).slice(0, 2001);
|
||||||
|
|
||||||
|
for (let i = 0; i < result.media.length; i++) {
|
||||||
|
const faces = (await faceRepository
|
||||||
|
.createQueryBuilder('faces')
|
||||||
|
.leftJoinAndSelect('faces.person', 'person')
|
||||||
|
.where('faces.media = :media', {media: result.media[i].id})
|
||||||
|
.getMany()).map(fE => ({name: fE.person.name, box: fE.box}));
|
||||||
|
if (faces.length > 0) {
|
||||||
|
result.media[i].metadata.faces = faces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (result.media.length > 2000) {
|
if (result.media.length > 2000) {
|
||||||
result.resultOverflow = true;
|
result.resultOverflow = true;
|
||||||
@ -181,6 +208,8 @@ export class SearchManager implements ISearchManager {
|
|||||||
resultOverflow: false
|
resultOverflow: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const faceRepository = connection.getRepository(FaceRegionEntry);
|
||||||
|
|
||||||
result.media = await connection
|
result.media = await connection
|
||||||
.getRepository(MediaEntity)
|
.getRepository(MediaEntity)
|
||||||
.createQueryBuilder('media')
|
.createQueryBuilder('media')
|
||||||
@ -191,10 +220,23 @@ export class SearchManager implements ISearchManager {
|
|||||||
.orWhere('media.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('media.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('media.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('media.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
||||||
|
.orWhere('person.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
||||||
.innerJoinAndSelect('media.directory', 'directory')
|
.innerJoinAndSelect('media.directory', 'directory')
|
||||||
|
.leftJoin('media.metadata.faces', 'faces')
|
||||||
|
.leftJoin('faces.person', 'person')
|
||||||
.limit(10)
|
.limit(10)
|
||||||
.getMany();
|
.getMany();
|
||||||
|
|
||||||
|
for (let i = 0; i < result.media.length; i++) {
|
||||||
|
const faces = (await faceRepository
|
||||||
|
.createQueryBuilder('faces')
|
||||||
|
.leftJoinAndSelect('faces.person', 'person')
|
||||||
|
.where('faces.media = :media', {media: result.media[i].id})
|
||||||
|
.getMany()).map(fE => ({name: fE.person.name, box: fE.box}));
|
||||||
|
if (faces.length > 0) {
|
||||||
|
result.media[i].metadata.faces = faces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result.directories = await connection
|
result.directories = await connection
|
||||||
.getRepository(DirectoryEntity)
|
.getRepository(DirectoryEntity)
|
||||||
|
@ -4,7 +4,7 @@ import {Config} from '../../../common/config/private/Config';
|
|||||||
import {Logger} from '../../Logger';
|
import {Logger} from '../../Logger';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as sizeOf from 'image-size';
|
import * as sizeOf from 'image-size';
|
||||||
import {OrientationTypes, ExifParserFactory} from 'ts-exif-parser';
|
import {ExifParserFactory, OrientationTypes} from 'ts-exif-parser';
|
||||||
import {IptcParser} from 'ts-node-iptc';
|
import {IptcParser} from 'ts-node-iptc';
|
||||||
import {FFmpegFactory} from '../FFmpegFactory';
|
import {FFmpegFactory} from '../FFmpegFactory';
|
||||||
import {FfprobeData} from 'fluent-ffmpeg';
|
import {FfprobeData} from 'fluent-ffmpeg';
|
||||||
@ -147,10 +147,16 @@ export class MetadataLoader {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const iptcData = IptcParser.parse(data);
|
const iptcData = IptcParser.parse(data);
|
||||||
if (iptcData.country_or_primary_location_name || iptcData.province_or_state || iptcData.city) {
|
if (iptcData.country_or_primary_location_name) {
|
||||||
metadata.positionData = metadata.positionData || {};
|
metadata.positionData = metadata.positionData || {};
|
||||||
metadata.positionData.country = iptcData.country_or_primary_location_name.replace(/\0/g, '').trim();
|
metadata.positionData.country = iptcData.country_or_primary_location_name.replace(/\0/g, '').trim();
|
||||||
|
}
|
||||||
|
if (iptcData.province_or_state) {
|
||||||
|
metadata.positionData = metadata.positionData || {};
|
||||||
metadata.positionData.state = iptcData.province_or_state.replace(/\0/g, '').trim();
|
metadata.positionData.state = iptcData.province_or_state.replace(/\0/g, '').trim();
|
||||||
|
}
|
||||||
|
if (iptcData.city) {
|
||||||
|
metadata.positionData = metadata.positionData || {};
|
||||||
metadata.positionData.city = iptcData.city.replace(/\0/g, '').trim();
|
metadata.positionData.city = iptcData.city.replace(/\0/g, '').trim();
|
||||||
}
|
}
|
||||||
if (iptcData.caption) {
|
if (iptcData.caption) {
|
||||||
@ -160,7 +166,7 @@ export class MetadataLoader {
|
|||||||
metadata.creationDate = <number>(iptcData.date_time ? iptcData.date_time.getTime() : metadata.creationDate);
|
metadata.creationDate = <number>(iptcData.date_time ? iptcData.date_time.getTime() : metadata.creationDate);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Logger.debug(LOG_TAG, 'Error parsing iptc data', fullPath, err);
|
Logger.debug(LOG_TAG, 'Error parsing iptc data', fullPath, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.creationDate = metadata.creationDate || 0;
|
metadata.creationDate = metadata.creationDate || 0;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
export enum SearchTypes {
|
export enum SearchTypes {
|
||||||
directory = 1,
|
directory = 1,
|
||||||
keyword = 2,
|
person = 2,
|
||||||
position = 3,
|
keyword = 3,
|
||||||
photo = 4,
|
position = 5,
|
||||||
video = 5
|
photo = 6,
|
||||||
|
video = 7
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AutoCompleteItem {
|
export class AutoCompleteItem {
|
||||||
|
Before Width: | Height: | Size: 695 KiB After Width: | Height: | Size: 696 KiB |
Before Width: | Height: | Size: 883 KiB After Width: | Height: | Size: 884 KiB |
Before Width: | Height: | Size: 452 KiB After Width: | Height: | Size: 453 KiB |
Before Width: | Height: | Size: 442 KiB After Width: | Height: | Size: 445 KiB |
Before Width: | Height: | Size: 528 KiB After Width: | Height: | Size: 530 KiB |
@ -92,7 +92,7 @@ a {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-indicator{
|
.video-indicator {
|
||||||
font-size: large;
|
font-size: large;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -102,12 +102,16 @@ a {
|
|||||||
background-color: rgba(0, 0, 0, 0.5);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
color: white;
|
color: white;
|
||||||
transition: background-color .3s ease-out;
|
transition: background-color .3s ease-out;
|
||||||
-moz-transition: background-color .3s ease-out;
|
-moz-transition: background-color .3s ease-out;
|
||||||
-webkit-transition: background-color .3s ease-out;
|
-webkit-transition: background-color .3s ease-out;
|
||||||
-o-transition: background-color .3s ease-out;
|
-o-transition: background-color .3s ease-out;
|
||||||
-ms-transition: background-color .3s ease-out;
|
-ms-transition: background-color .3s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-container:hover .video-indicator{
|
.photo-container:hover .video-indicator {
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.photo-keywords .oi-person{
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
@ -36,12 +36,18 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="photo-keywords" *ngIf="gridPhoto.media.metadata.keywords && gridPhoto.media.metadata.keywords.length">
|
<div class="photo-keywords" *ngIf="keywords">
|
||||||
<ng-template ngFor let-keyword [ngForOf]="gridPhoto.media.metadata.keywords" let-last="last">
|
<ng-template ngFor let-keyword [ngForOf]="keywords" let-last="last">
|
||||||
<a *ngIf="searchEnabled"
|
<a *ngIf="searchEnabled"
|
||||||
[routerLink]="['/search', keyword, {type: SearchTypes[SearchTypes.keyword]}]">#{{keyword}}</a>
|
[routerLink]="['/search', keyword.value, {type: SearchTypes[keyword.type]}]" [ngSwitch]="keyword.type">
|
||||||
<span *ngIf="!searchEnabled">#{{keyword}}</span>
|
<ng-template [ngSwitchCase]="SearchTypes.keyword">#</ng-template><!--
|
||||||
<ng-template [ngIf]="!last">, </ng-template>
|
--><ng-template [ngSwitchCase]="SearchTypes.person"><span class="oi oi-person"></span></ng-template><!--
|
||||||
|
-->{{keyword.value}}</a>
|
||||||
|
<span *ngIf="!searchEnabled" [ngSwitch]="keyword.type">
|
||||||
|
<ng-template [ngSwitchCase]="SearchTypes.keyword">#</ng-template><!--
|
||||||
|
--><ng-template [ngSwitchCase]="SearchTypes.person"><span class="oi oi-person"></span></ng-template><!--
|
||||||
|
-->{{keyword.value}}</span>
|
||||||
|
<ng-template [ngIf]="!last">,</ng-template>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,9 +5,8 @@ import {SearchTypes} from '../../../../../common/entities/AutoCompleteItem';
|
|||||||
import {RouterLink} from '@angular/router';
|
import {RouterLink} from '@angular/router';
|
||||||
import {Thumbnail, ThumbnailManagerService} from '../../thumbnailManager.service';
|
import {Thumbnail, ThumbnailManagerService} from '../../thumbnailManager.service';
|
||||||
import {Config} from '../../../../../common/config/public/Config';
|
import {Config} from '../../../../../common/config/public/Config';
|
||||||
import {AnimationBuilder} from '@angular/animations';
|
|
||||||
import {PageHelper} from '../../../model/page.helper';
|
import {PageHelper} from '../../../model/page.helper';
|
||||||
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
|
import {PhotoDTO, PhotoMetadata} from '../../../../../common/entities/PhotoDTO';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-gallery-grid-photo',
|
selector: 'app-gallery-grid-photo',
|
||||||
@ -22,6 +21,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
|
|||||||
@ViewChild('photoContainer') container: ElementRef;
|
@ViewChild('photoContainer') container: ElementRef;
|
||||||
|
|
||||||
thumbnail: Thumbnail;
|
thumbnail: Thumbnail;
|
||||||
|
keywords: { value: string, type: SearchTypes }[] = null;
|
||||||
infoBar = {
|
infoBar = {
|
||||||
marginTop: 0,
|
marginTop: 0,
|
||||||
visible: false,
|
visible: false,
|
||||||
@ -34,17 +34,40 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
|
|||||||
|
|
||||||
wasInView: boolean = null;
|
wasInView: boolean = null;
|
||||||
|
|
||||||
constructor(private thumbnailService: ThumbnailManagerService,
|
constructor(private thumbnailService: ThumbnailManagerService) {
|
||||||
private _animationBuilder: AnimationBuilder) {
|
|
||||||
this.SearchTypes = SearchTypes;
|
this.SearchTypes = SearchTypes;
|
||||||
this.searchEnabled = Config.Client.Search.enabled;
|
this.searchEnabled = Config.Client.Search.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
get ScrollListener(): boolean {
|
||||||
this.thumbnail = this.thumbnailService.getThumbnail(this.gridPhoto);
|
return !this.thumbnail.Available && !this.thumbnail.Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
get Title(): string {
|
||||||
|
if (Config.Client.Other.captionFirstNaming === false) {
|
||||||
|
return this.gridPhoto.media.name;
|
||||||
|
}
|
||||||
|
if ((<PhotoDTO>this.gridPhoto.media).metadata.caption) {
|
||||||
|
if ((<PhotoDTO>this.gridPhoto.media).metadata.caption.length > 20) {
|
||||||
|
return (<PhotoDTO>this.gridPhoto.media).metadata.caption.substring(0, 17) + '...';
|
||||||
|
}
|
||||||
|
return (<PhotoDTO>this.gridPhoto.media).metadata.caption;
|
||||||
|
}
|
||||||
|
return this.gridPhoto.media.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.thumbnail = this.thumbnailService.getThumbnail(this.gridPhoto);
|
||||||
|
const metadata = this.gridPhoto.media.metadata as PhotoMetadata;
|
||||||
|
if ((metadata.keywords && metadata.keywords.length > 0) ||
|
||||||
|
(metadata.faces && metadata.faces.length > 0)) {
|
||||||
|
this.keywords = (metadata.faces || []).map(f => ({value: f.name, type: SearchTypes.person}))
|
||||||
|
.concat((metadata.keywords || []).map(k => ({value: k, type: SearchTypes.keyword})));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.thumbnail.destroy();
|
this.thumbnail.destroy();
|
||||||
|
|
||||||
@ -53,16 +76,11 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
isInView(): boolean {
|
isInView(): boolean {
|
||||||
return PageHelper.ScrollY < this.container.nativeElement.offsetTop + this.container.nativeElement.clientHeight
|
return PageHelper.ScrollY < this.container.nativeElement.offsetTop + this.container.nativeElement.clientHeight
|
||||||
&& PageHelper.ScrollY + window.innerHeight > this.container.nativeElement.offsetTop;
|
&& PageHelper.ScrollY + window.innerHeight > this.container.nativeElement.offsetTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
get ScrollListener(): boolean {
|
|
||||||
return !this.thumbnail.Available && !this.thumbnail.Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
onScroll() {
|
onScroll() {
|
||||||
if (this.thumbnail.Available === true || this.thumbnail.Error === true) {
|
if (this.thumbnail.Available === true || this.thumbnail.Error === true) {
|
||||||
return;
|
return;
|
||||||
@ -74,7 +92,6 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getPositionText(): string {
|
getPositionText(): string {
|
||||||
if (!this.gridPhoto || !this.gridPhoto.isPhoto()) {
|
if (!this.gridPhoto || !this.gridPhoto.isPhoto()) {
|
||||||
return '';
|
return '';
|
||||||
@ -84,7 +101,6 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
|
|||||||
(<PhotoDTO>this.gridPhoto.media).metadata.positionData.country;
|
(<PhotoDTO>this.gridPhoto.media).metadata.positionData.country;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mouseOver() {
|
mouseOver() {
|
||||||
this.infoBar.visible = true;
|
this.infoBar.visible = true;
|
||||||
if (this.animationTimer != null) {
|
if (this.animationTimer != null) {
|
||||||
@ -124,19 +140,6 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get Title(): string {
|
|
||||||
if (Config.Client.Other.captionFirstNaming === false) {
|
|
||||||
return this.gridPhoto.media.name;
|
|
||||||
}
|
|
||||||
if ((<PhotoDTO>this.gridPhoto.media).metadata.caption) {
|
|
||||||
if ((<PhotoDTO>this.gridPhoto.media).metadata.caption.length > 20) {
|
|
||||||
return (<PhotoDTO>this.gridPhoto.media).metadata.caption.substring(0, 17) + '...';
|
|
||||||
}
|
|
||||||
return (<PhotoDTO>this.gridPhoto.media).metadata.caption;
|
|
||||||
}
|
|
||||||
return this.gridPhoto.media.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
onImageLoad() {
|
onImageLoad() {
|
||||||
this.loading.show = false;
|
this.loading.show = false;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
<span *ngSwitchCase="SearchTypes.video" class="oi oi-video"></span>
|
<span *ngSwitchCase="SearchTypes.video" class="oi oi-video"></span>
|
||||||
<span *ngSwitchCase="SearchTypes.directory" class="oi oi-folder"></span>
|
<span *ngSwitchCase="SearchTypes.directory" class="oi oi-folder"></span>
|
||||||
<span *ngSwitchCase="SearchTypes.keyword" class="oi oi-tag"></span>
|
<span *ngSwitchCase="SearchTypes.keyword" class="oi oi-tag"></span>
|
||||||
|
<span *ngSwitchCase="SearchTypes.person" class="oi oi-person"></span>
|
||||||
<span *ngSwitchCase="SearchTypes.position" class="oi oi-map-marker"></span>
|
<span *ngSwitchCase="SearchTypes.position" class="oi oi-map-marker"></span>
|
||||||
</span>
|
</span>
|
||||||
<strong> {{searchResult.searchText}}</strong>
|
<strong> {{searchResult.searchText}}</strong>
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<span *ngSwitchCase="SearchTypes.video" class="oi oi-video"></span>
|
<span *ngSwitchCase="SearchTypes.video" class="oi oi-video"></span>
|
||||||
<span *ngSwitchCase="SearchTypes.directory" class="oi oi-folder"></span>
|
<span *ngSwitchCase="SearchTypes.directory" class="oi oi-folder"></span>
|
||||||
<span *ngSwitchCase="SearchTypes.keyword" class="oi oi-tag"></span>
|
<span *ngSwitchCase="SearchTypes.keyword" class="oi oi-tag"></span>
|
||||||
|
<span *ngSwitchCase="SearchTypes.person" class="oi oi-person"></span>
|
||||||
<span *ngSwitchCase="SearchTypes.position" class="oi oi-map-marker"></span>
|
<span *ngSwitchCase="SearchTypes.position" class="oi oi-map-marker"></span>
|
||||||
</span>
|
</span>
|
||||||
{{item.preText}}<strong>{{item.highLightText}}</strong>{{item.postText}}
|
{{item.preText}}<strong>{{item.highLightText}}</strong>{{item.postText}}
|
||||||
|