Compare commits
31 commits
main
...
feat/unmer
Author | SHA1 | Date | |
---|---|---|---|
|
c9feb474be | ||
|
00ee2aca62 | ||
|
fc0d358d4e | ||
|
c5ca5a528e | ||
|
9247eb4c1a | ||
|
c8d173697f | ||
|
f42cf33605 | ||
|
6027a2fda6 | ||
|
24f9968606 | ||
|
7a557c08db | ||
|
89ad9d58c5 | ||
|
1a1b3dd996 | ||
|
aa6c90c66c | ||
|
7a0047f631 | ||
|
6ef7844613 | ||
|
00d7052b84 | ||
|
47b3a8bad9 | ||
|
d7489cf808 | ||
|
348a827281 | ||
|
2babfe4ad4 | ||
|
8699d8cfbf | ||
|
26b2f66f0f | ||
|
8c37a7cb60 | ||
|
02f1b828d3 | ||
|
977a17f9c0 | ||
|
4dcc1131fa | ||
|
698e45a5cb | ||
|
f6170e5f7f | ||
|
79f7a95e66 | ||
|
a1f54de082 | ||
|
c30a5db8f4 |
45 changed files with 3961 additions and 310 deletions
503
cli/src/api/open-api/api.ts
generated
503
cli/src/api/open-api/api.ts
generated
|
@ -502,6 +502,81 @@ export const AssetBulkUploadCheckResultReasonEnum = {
|
||||||
|
|
||||||
export type AssetBulkUploadCheckResultReasonEnum = typeof AssetBulkUploadCheckResultReasonEnum[keyof typeof AssetBulkUploadCheckResultReasonEnum];
|
export type AssetBulkUploadCheckResultReasonEnum = typeof AssetBulkUploadCheckResultReasonEnum[keyof typeof AssetBulkUploadCheckResultReasonEnum];
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
export interface AssetFaceBoxDto {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'boundingBoxX1': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'boundingBoxX2': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'boundingBoxY1': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'boundingBoxY2': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'imageHeight': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'imageWidth': number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface AssetFaceUpdateDto
|
||||||
|
*/
|
||||||
|
export interface AssetFaceUpdateDto {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {Array<AssetFaceUpdateItem>}
|
||||||
|
* @memberof AssetFaceUpdateDto
|
||||||
|
*/
|
||||||
|
'data': Array<AssetFaceUpdateItem>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface AssetFaceUpdateItem
|
||||||
|
*/
|
||||||
|
export interface AssetFaceUpdateItem {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof AssetFaceUpdateItem
|
||||||
|
*/
|
||||||
|
'assetId': string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof AssetFaceUpdateItem
|
||||||
|
*/
|
||||||
|
'personId': string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
|
@ -744,10 +819,10 @@ export interface AssetResponseDto {
|
||||||
'ownerId': string;
|
'ownerId': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {Array<PersonResponseDto>}
|
* @type {Array<PeopleAssetResponseDto>}
|
||||||
* @memberof AssetResponseDto
|
* @memberof AssetResponseDto
|
||||||
*/
|
*/
|
||||||
'people'?: Array<PersonResponseDto>;
|
'people'?: Array<PeopleAssetResponseDto>;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
|
@ -796,6 +871,12 @@ export interface AssetResponseDto {
|
||||||
* @memberof AssetResponseDto
|
* @memberof AssetResponseDto
|
||||||
*/
|
*/
|
||||||
'type': AssetTypeEnum;
|
'type': AssetTypeEnum;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {Array<UnassignedFacesResponseDto>}
|
||||||
|
* @memberof AssetResponseDto
|
||||||
|
*/
|
||||||
|
'unassignedPeople'?: Array<UnassignedFacesResponseDto>;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -2315,6 +2396,25 @@ export const PathType = {
|
||||||
export type PathType = typeof PathType[keyof typeof PathType];
|
export type PathType = typeof PathType[keyof typeof PathType];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface PeopleAssetResponseDto
|
||||||
|
*/
|
||||||
|
export interface PeopleAssetResponseDto {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PeopleAssetResponseDto
|
||||||
|
*/
|
||||||
|
'assetFaceId': string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {PersonResponseDto}
|
||||||
|
* @memberof PeopleAssetResponseDto
|
||||||
|
*/
|
||||||
|
'person': PersonResponseDto;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
|
@ -3949,6 +4049,31 @@ export const TranscodePolicy = {
|
||||||
export type TranscodePolicy = typeof TranscodePolicy[keyof typeof TranscodePolicy];
|
export type TranscodePolicy = typeof TranscodePolicy[keyof typeof TranscodePolicy];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface UnassignedFacesResponseDto
|
||||||
|
*/
|
||||||
|
export interface UnassignedFacesResponseDto {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof UnassignedFacesResponseDto
|
||||||
|
*/
|
||||||
|
'assetFaceId': string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof UnassignedFacesResponseDto
|
||||||
|
*/
|
||||||
|
'assetId': string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {AssetFaceBoxDto}
|
||||||
|
* @memberof UnassignedFacesResponseDto
|
||||||
|
*/
|
||||||
|
'boudinxBox': AssetFaceBoxDto;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
|
@ -11766,6 +11891,50 @@ export class PartnerApi extends BaseAPI {
|
||||||
*/
|
*/
|
||||||
export const PersonApiAxiosParamCreator = function (configuration?: Configuration) {
|
export const PersonApiAxiosParamCreator = function (configuration?: Configuration) {
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
createPerson: async (assetFaceUpdateDto: AssetFaceUpdateDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'assetFaceUpdateDto' is not null or undefined
|
||||||
|
assertParamExists('createPerson', 'assetFaceUpdateDto', assetFaceUpdateDto)
|
||||||
|
const localVarPath = `/person`;
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication cookie required
|
||||||
|
|
||||||
|
// authentication api_key required
|
||||||
|
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||||
|
|
||||||
|
// authentication bearer required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
localVarRequestOptions.data = serializeDataIfNeeded(assetFaceUpdateDto, localVarRequestOptions, configuration)
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {boolean} [withHidden]
|
* @param {boolean} [withHidden]
|
||||||
|
@ -11800,6 +11969,52 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} assetId
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
getAssetFace: async (id: string, assetId: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'id' is not null or undefined
|
||||||
|
assertParamExists('getAssetFace', 'id', id)
|
||||||
|
// verify required parameter 'assetId' is not null or undefined
|
||||||
|
assertParamExists('getAssetFace', 'assetId', assetId)
|
||||||
|
const localVarPath = `/person/{id}/{assetId}/faceasset`
|
||||||
|
.replace(`{${"id"}}`, encodeURIComponent(String(id)))
|
||||||
|
.replace(`{${"assetId"}}`, encodeURIComponent(String(assetId)));
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication cookie required
|
||||||
|
|
||||||
|
// authentication api_key required
|
||||||
|
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||||
|
|
||||||
|
// authentication bearer required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
@ -12025,6 +12240,98 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
|
||||||
options: localVarRequestOptions,
|
options: localVarRequestOptions,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
reassignFaces: async (id: string, assetFaceUpdateDto: AssetFaceUpdateDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'id' is not null or undefined
|
||||||
|
assertParamExists('reassignFaces', 'id', id)
|
||||||
|
// verify required parameter 'assetFaceUpdateDto' is not null or undefined
|
||||||
|
assertParamExists('reassignFaces', 'assetFaceUpdateDto', assetFaceUpdateDto)
|
||||||
|
const localVarPath = `/person/{id}/reassign`
|
||||||
|
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication cookie required
|
||||||
|
|
||||||
|
// authentication api_key required
|
||||||
|
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||||
|
|
||||||
|
// authentication bearer required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
localVarRequestOptions.data = serializeDataIfNeeded(assetFaceUpdateDto, localVarRequestOptions, configuration)
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
unassignFaces: async (assetFaceUpdateDto: AssetFaceUpdateDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'assetFaceUpdateDto' is not null or undefined
|
||||||
|
assertParamExists('unassignFaces', 'assetFaceUpdateDto', assetFaceUpdateDto)
|
||||||
|
const localVarPath = `/person`;
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication cookie required
|
||||||
|
|
||||||
|
// authentication api_key required
|
||||||
|
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||||
|
|
||||||
|
// authentication bearer required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
localVarRequestOptions.data = serializeDataIfNeeded(assetFaceUpdateDto, localVarRequestOptions, configuration)
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PeopleUpdateDto} peopleUpdateDto
|
* @param {PeopleUpdateDto} peopleUpdateDto
|
||||||
|
@ -12127,6 +12434,16 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
|
||||||
export const PersonApiFp = function(configuration?: Configuration) {
|
export const PersonApiFp = function(configuration?: Configuration) {
|
||||||
const localVarAxiosParamCreator = PersonApiAxiosParamCreator(configuration)
|
const localVarAxiosParamCreator = PersonApiAxiosParamCreator(configuration)
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async createPerson(assetFaceUpdateDto: AssetFaceUpdateDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<PersonResponseDto>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.createPerson(assetFaceUpdateDto, options);
|
||||||
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {boolean} [withHidden]
|
* @param {boolean} [withHidden]
|
||||||
|
@ -12137,6 +12454,17 @@ export const PersonApiFp = function(configuration?: Configuration) {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getAllPeople(withHidden, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.getAllPeople(withHidden, options);
|
||||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} assetId
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async getAssetFace(id: string, assetId: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AssetFaceBoxDto>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.getAssetFace(id, assetId, options);
|
||||||
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
|
@ -12188,6 +12516,27 @@ export const PersonApiFp = function(configuration?: Configuration) {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
|
||||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async reassignFaces(id: string, assetFaceUpdateDto: AssetFaceUpdateDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<PersonResponseDto>>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.reassignFaces(id, assetFaceUpdateDto, options);
|
||||||
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async unassignFaces(assetFaceUpdateDto: AssetFaceUpdateDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<BulkIdResponseDto>>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.unassignFaces(assetFaceUpdateDto, options);
|
||||||
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PeopleUpdateDto} peopleUpdateDto
|
* @param {PeopleUpdateDto} peopleUpdateDto
|
||||||
|
@ -12219,6 +12568,15 @@ export const PersonApiFp = function(configuration?: Configuration) {
|
||||||
export const PersonApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
|
export const PersonApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
|
||||||
const localVarFp = PersonApiFp(configuration)
|
const localVarFp = PersonApiFp(configuration)
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiCreatePersonRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
createPerson(requestParameters: PersonApiCreatePersonRequest, options?: AxiosRequestConfig): AxiosPromise<PersonResponseDto> {
|
||||||
|
return localVarFp.createPerson(requestParameters.assetFaceUpdateDto, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiGetAllPeopleRequest} requestParameters Request parameters.
|
* @param {PersonApiGetAllPeopleRequest} requestParameters Request parameters.
|
||||||
|
@ -12228,6 +12586,15 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
|
||||||
getAllPeople(requestParameters: PersonApiGetAllPeopleRequest = {}, options?: AxiosRequestConfig): AxiosPromise<PeopleResponseDto> {
|
getAllPeople(requestParameters: PersonApiGetAllPeopleRequest = {}, options?: AxiosRequestConfig): AxiosPromise<PeopleResponseDto> {
|
||||||
return localVarFp.getAllPeople(requestParameters.withHidden, options).then((request) => request(axios, basePath));
|
return localVarFp.getAllPeople(requestParameters.withHidden, options).then((request) => request(axios, basePath));
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiGetAssetFaceRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
getAssetFace(requestParameters: PersonApiGetAssetFaceRequest, options?: AxiosRequestConfig): AxiosPromise<AssetFaceBoxDto> {
|
||||||
|
return localVarFp.getAssetFace(requestParameters.id, requestParameters.assetId, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiGetPersonRequest} requestParameters Request parameters.
|
* @param {PersonApiGetPersonRequest} requestParameters Request parameters.
|
||||||
|
@ -12273,6 +12640,24 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
|
||||||
mergePerson(requestParameters: PersonApiMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
|
mergePerson(requestParameters: PersonApiMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
|
||||||
return localVarFp.mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(axios, basePath));
|
return localVarFp.mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(axios, basePath));
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiReassignFacesRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
reassignFaces(requestParameters: PersonApiReassignFacesRequest, options?: AxiosRequestConfig): AxiosPromise<Array<PersonResponseDto>> {
|
||||||
|
return localVarFp.reassignFaces(requestParameters.id, requestParameters.assetFaceUpdateDto, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiUnassignFacesRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
unassignFaces(requestParameters: PersonApiUnassignFacesRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
|
||||||
|
return localVarFp.unassignFaces(requestParameters.assetFaceUpdateDto, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
||||||
|
@ -12294,6 +12679,20 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters for createPerson operation in PersonApi.
|
||||||
|
* @export
|
||||||
|
* @interface PersonApiCreatePersonRequest
|
||||||
|
*/
|
||||||
|
export interface PersonApiCreatePersonRequest {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {AssetFaceUpdateDto}
|
||||||
|
* @memberof PersonApiCreatePerson
|
||||||
|
*/
|
||||||
|
readonly assetFaceUpdateDto: AssetFaceUpdateDto
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request parameters for getAllPeople operation in PersonApi.
|
* Request parameters for getAllPeople operation in PersonApi.
|
||||||
* @export
|
* @export
|
||||||
|
@ -12308,6 +12707,27 @@ export interface PersonApiGetAllPeopleRequest {
|
||||||
readonly withHidden?: boolean
|
readonly withHidden?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters for getAssetFace operation in PersonApi.
|
||||||
|
* @export
|
||||||
|
* @interface PersonApiGetAssetFaceRequest
|
||||||
|
*/
|
||||||
|
export interface PersonApiGetAssetFaceRequest {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PersonApiGetAssetFace
|
||||||
|
*/
|
||||||
|
readonly id: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PersonApiGetAssetFace
|
||||||
|
*/
|
||||||
|
readonly assetId: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request parameters for getPerson operation in PersonApi.
|
* Request parameters for getPerson operation in PersonApi.
|
||||||
* @export
|
* @export
|
||||||
|
@ -12385,6 +12805,41 @@ export interface PersonApiMergePersonRequest {
|
||||||
readonly mergePersonDto: MergePersonDto
|
readonly mergePersonDto: MergePersonDto
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters for reassignFaces operation in PersonApi.
|
||||||
|
* @export
|
||||||
|
* @interface PersonApiReassignFacesRequest
|
||||||
|
*/
|
||||||
|
export interface PersonApiReassignFacesRequest {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PersonApiReassignFaces
|
||||||
|
*/
|
||||||
|
readonly id: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {AssetFaceUpdateDto}
|
||||||
|
* @memberof PersonApiReassignFaces
|
||||||
|
*/
|
||||||
|
readonly assetFaceUpdateDto: AssetFaceUpdateDto
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters for unassignFaces operation in PersonApi.
|
||||||
|
* @export
|
||||||
|
* @interface PersonApiUnassignFacesRequest
|
||||||
|
*/
|
||||||
|
export interface PersonApiUnassignFacesRequest {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {AssetFaceUpdateDto}
|
||||||
|
* @memberof PersonApiUnassignFaces
|
||||||
|
*/
|
||||||
|
readonly assetFaceUpdateDto: AssetFaceUpdateDto
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request parameters for updatePeople operation in PersonApi.
|
* Request parameters for updatePeople operation in PersonApi.
|
||||||
* @export
|
* @export
|
||||||
|
@ -12427,6 +12882,17 @@ export interface PersonApiUpdatePersonRequest {
|
||||||
* @extends {BaseAPI}
|
* @extends {BaseAPI}
|
||||||
*/
|
*/
|
||||||
export class PersonApi extends BaseAPI {
|
export class PersonApi extends BaseAPI {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiCreatePersonRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof PersonApi
|
||||||
|
*/
|
||||||
|
public createPerson(requestParameters: PersonApiCreatePersonRequest, options?: AxiosRequestConfig) {
|
||||||
|
return PersonApiFp(this.configuration).createPerson(requestParameters.assetFaceUpdateDto, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiGetAllPeopleRequest} requestParameters Request parameters.
|
* @param {PersonApiGetAllPeopleRequest} requestParameters Request parameters.
|
||||||
|
@ -12438,6 +12904,17 @@ export class PersonApi extends BaseAPI {
|
||||||
return PersonApiFp(this.configuration).getAllPeople(requestParameters.withHidden, options).then((request) => request(this.axios, this.basePath));
|
return PersonApiFp(this.configuration).getAllPeople(requestParameters.withHidden, options).then((request) => request(this.axios, this.basePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiGetAssetFaceRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof PersonApi
|
||||||
|
*/
|
||||||
|
public getAssetFace(requestParameters: PersonApiGetAssetFaceRequest, options?: AxiosRequestConfig) {
|
||||||
|
return PersonApiFp(this.configuration).getAssetFace(requestParameters.id, requestParameters.assetId, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiGetPersonRequest} requestParameters Request parameters.
|
* @param {PersonApiGetPersonRequest} requestParameters Request parameters.
|
||||||
|
@ -12493,6 +12970,28 @@ export class PersonApi extends BaseAPI {
|
||||||
return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
|
return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiReassignFacesRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof PersonApi
|
||||||
|
*/
|
||||||
|
public reassignFaces(requestParameters: PersonApiReassignFacesRequest, options?: AxiosRequestConfig) {
|
||||||
|
return PersonApiFp(this.configuration).reassignFaces(requestParameters.id, requestParameters.assetFaceUpdateDto, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiUnassignFacesRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof PersonApi
|
||||||
|
*/
|
||||||
|
public unassignFaces(requestParameters: PersonApiUnassignFacesRequest, options?: AxiosRequestConfig) {
|
||||||
|
return PersonApiFp(this.configuration).unassignFaces(requestParameters.assetFaceUpdateDto, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
||||||
|
|
15
mobile/openapi/.openapi-generator/FILES
generated
15
mobile/openapi/.openapi-generator/FILES
generated
|
@ -21,6 +21,9 @@ doc/AssetBulkUploadCheckDto.md
|
||||||
doc/AssetBulkUploadCheckItem.md
|
doc/AssetBulkUploadCheckItem.md
|
||||||
doc/AssetBulkUploadCheckResponseDto.md
|
doc/AssetBulkUploadCheckResponseDto.md
|
||||||
doc/AssetBulkUploadCheckResult.md
|
doc/AssetBulkUploadCheckResult.md
|
||||||
|
doc/AssetFaceBoxDto.md
|
||||||
|
doc/AssetFaceUpdateDto.md
|
||||||
|
doc/AssetFaceUpdateItem.md
|
||||||
doc/AssetFileUploadResponseDto.md
|
doc/AssetFileUploadResponseDto.md
|
||||||
doc/AssetIdsDto.md
|
doc/AssetIdsDto.md
|
||||||
doc/AssetIdsResponseDto.md
|
doc/AssetIdsResponseDto.md
|
||||||
|
@ -89,6 +92,7 @@ doc/OAuthConfigResponseDto.md
|
||||||
doc/PartnerApi.md
|
doc/PartnerApi.md
|
||||||
doc/PathEntityType.md
|
doc/PathEntityType.md
|
||||||
doc/PathType.md
|
doc/PathType.md
|
||||||
|
doc/PeopleAssetResponseDto.md
|
||||||
doc/PeopleResponseDto.md
|
doc/PeopleResponseDto.md
|
||||||
doc/PeopleUpdateDto.md
|
doc/PeopleUpdateDto.md
|
||||||
doc/PeopleUpdateItem.md
|
doc/PeopleUpdateItem.md
|
||||||
|
@ -147,6 +151,7 @@ doc/TimeBucketSize.md
|
||||||
doc/ToneMapping.md
|
doc/ToneMapping.md
|
||||||
doc/TranscodeHWAccel.md
|
doc/TranscodeHWAccel.md
|
||||||
doc/TranscodePolicy.md
|
doc/TranscodePolicy.md
|
||||||
|
doc/UnassignedFacesResponseDto.md
|
||||||
doc/UpdateAlbumDto.md
|
doc/UpdateAlbumDto.md
|
||||||
doc/UpdateAssetDto.md
|
doc/UpdateAssetDto.md
|
||||||
doc/UpdateLibraryDto.md
|
doc/UpdateLibraryDto.md
|
||||||
|
@ -200,6 +205,9 @@ lib/model/asset_bulk_upload_check_dto.dart
|
||||||
lib/model/asset_bulk_upload_check_item.dart
|
lib/model/asset_bulk_upload_check_item.dart
|
||||||
lib/model/asset_bulk_upload_check_response_dto.dart
|
lib/model/asset_bulk_upload_check_response_dto.dart
|
||||||
lib/model/asset_bulk_upload_check_result.dart
|
lib/model/asset_bulk_upload_check_result.dart
|
||||||
|
lib/model/asset_face_box_dto.dart
|
||||||
|
lib/model/asset_face_update_dto.dart
|
||||||
|
lib/model/asset_face_update_item.dart
|
||||||
lib/model/asset_file_upload_response_dto.dart
|
lib/model/asset_file_upload_response_dto.dart
|
||||||
lib/model/asset_ids_dto.dart
|
lib/model/asset_ids_dto.dart
|
||||||
lib/model/asset_ids_response_dto.dart
|
lib/model/asset_ids_response_dto.dart
|
||||||
|
@ -262,6 +270,7 @@ lib/model/o_auth_config_dto.dart
|
||||||
lib/model/o_auth_config_response_dto.dart
|
lib/model/o_auth_config_response_dto.dart
|
||||||
lib/model/path_entity_type.dart
|
lib/model/path_entity_type.dart
|
||||||
lib/model/path_type.dart
|
lib/model/path_type.dart
|
||||||
|
lib/model/people_asset_response_dto.dart
|
||||||
lib/model/people_response_dto.dart
|
lib/model/people_response_dto.dart
|
||||||
lib/model/people_update_dto.dart
|
lib/model/people_update_dto.dart
|
||||||
lib/model/people_update_item.dart
|
lib/model/people_update_item.dart
|
||||||
|
@ -314,6 +323,7 @@ lib/model/time_bucket_size.dart
|
||||||
lib/model/tone_mapping.dart
|
lib/model/tone_mapping.dart
|
||||||
lib/model/transcode_hw_accel.dart
|
lib/model/transcode_hw_accel.dart
|
||||||
lib/model/transcode_policy.dart
|
lib/model/transcode_policy.dart
|
||||||
|
lib/model/unassigned_faces_response_dto.dart
|
||||||
lib/model/update_album_dto.dart
|
lib/model/update_album_dto.dart
|
||||||
lib/model/update_asset_dto.dart
|
lib/model/update_asset_dto.dart
|
||||||
lib/model/update_library_dto.dart
|
lib/model/update_library_dto.dart
|
||||||
|
@ -344,6 +354,9 @@ test/asset_bulk_upload_check_dto_test.dart
|
||||||
test/asset_bulk_upload_check_item_test.dart
|
test/asset_bulk_upload_check_item_test.dart
|
||||||
test/asset_bulk_upload_check_response_dto_test.dart
|
test/asset_bulk_upload_check_response_dto_test.dart
|
||||||
test/asset_bulk_upload_check_result_test.dart
|
test/asset_bulk_upload_check_result_test.dart
|
||||||
|
test/asset_face_box_dto_test.dart
|
||||||
|
test/asset_face_update_dto_test.dart
|
||||||
|
test/asset_face_update_item_test.dart
|
||||||
test/asset_file_upload_response_dto_test.dart
|
test/asset_file_upload_response_dto_test.dart
|
||||||
test/asset_ids_dto_test.dart
|
test/asset_ids_dto_test.dart
|
||||||
test/asset_ids_response_dto_test.dart
|
test/asset_ids_response_dto_test.dart
|
||||||
|
@ -412,6 +425,7 @@ test/o_auth_config_response_dto_test.dart
|
||||||
test/partner_api_test.dart
|
test/partner_api_test.dart
|
||||||
test/path_entity_type_test.dart
|
test/path_entity_type_test.dart
|
||||||
test/path_type_test.dart
|
test/path_type_test.dart
|
||||||
|
test/people_asset_response_dto_test.dart
|
||||||
test/people_response_dto_test.dart
|
test/people_response_dto_test.dart
|
||||||
test/people_update_dto_test.dart
|
test/people_update_dto_test.dart
|
||||||
test/people_update_item_test.dart
|
test/people_update_item_test.dart
|
||||||
|
@ -470,6 +484,7 @@ test/time_bucket_size_test.dart
|
||||||
test/tone_mapping_test.dart
|
test/tone_mapping_test.dart
|
||||||
test/transcode_hw_accel_test.dart
|
test/transcode_hw_accel_test.dart
|
||||||
test/transcode_policy_test.dart
|
test/transcode_policy_test.dart
|
||||||
|
test/unassigned_faces_response_dto_test.dart
|
||||||
test/update_album_dto_test.dart
|
test/update_album_dto_test.dart
|
||||||
test/update_asset_dto_test.dart
|
test/update_asset_dto_test.dart
|
||||||
test/update_library_dto_test.dart
|
test/update_library_dto_test.dart
|
||||||
|
|
9
mobile/openapi/README.md
generated
9
mobile/openapi/README.md
generated
|
@ -148,12 +148,16 @@ Class | Method | HTTP request | Description
|
||||||
*PartnerApi* | [**createPartner**](doc//PartnerApi.md#createpartner) | **POST** /partner/{id} |
|
*PartnerApi* | [**createPartner**](doc//PartnerApi.md#createpartner) | **POST** /partner/{id} |
|
||||||
*PartnerApi* | [**getPartners**](doc//PartnerApi.md#getpartners) | **GET** /partner |
|
*PartnerApi* | [**getPartners**](doc//PartnerApi.md#getpartners) | **GET** /partner |
|
||||||
*PartnerApi* | [**removePartner**](doc//PartnerApi.md#removepartner) | **DELETE** /partner/{id} |
|
*PartnerApi* | [**removePartner**](doc//PartnerApi.md#removepartner) | **DELETE** /partner/{id} |
|
||||||
|
*PersonApi* | [**createPerson**](doc//PersonApi.md#createperson) | **POST** /person |
|
||||||
*PersonApi* | [**getAllPeople**](doc//PersonApi.md#getallpeople) | **GET** /person |
|
*PersonApi* | [**getAllPeople**](doc//PersonApi.md#getallpeople) | **GET** /person |
|
||||||
|
*PersonApi* | [**getAssetFace**](doc//PersonApi.md#getassetface) | **GET** /person/{id}/{assetId}/faceasset |
|
||||||
*PersonApi* | [**getPerson**](doc//PersonApi.md#getperson) | **GET** /person/{id} |
|
*PersonApi* | [**getPerson**](doc//PersonApi.md#getperson) | **GET** /person/{id} |
|
||||||
*PersonApi* | [**getPersonAssets**](doc//PersonApi.md#getpersonassets) | **GET** /person/{id}/assets |
|
*PersonApi* | [**getPersonAssets**](doc//PersonApi.md#getpersonassets) | **GET** /person/{id}/assets |
|
||||||
*PersonApi* | [**getPersonStatistics**](doc//PersonApi.md#getpersonstatistics) | **GET** /person/{id}/statistics |
|
*PersonApi* | [**getPersonStatistics**](doc//PersonApi.md#getpersonstatistics) | **GET** /person/{id}/statistics |
|
||||||
*PersonApi* | [**getPersonThumbnail**](doc//PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail |
|
*PersonApi* | [**getPersonThumbnail**](doc//PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail |
|
||||||
*PersonApi* | [**mergePerson**](doc//PersonApi.md#mergeperson) | **POST** /person/{id}/merge |
|
*PersonApi* | [**mergePerson**](doc//PersonApi.md#mergeperson) | **POST** /person/{id}/merge |
|
||||||
|
*PersonApi* | [**reassignFaces**](doc//PersonApi.md#reassignfaces) | **PUT** /person/{id}/reassign |
|
||||||
|
*PersonApi* | [**unassignFaces**](doc//PersonApi.md#unassignfaces) | **DELETE** /person |
|
||||||
*PersonApi* | [**updatePeople**](doc//PersonApi.md#updatepeople) | **PUT** /person |
|
*PersonApi* | [**updatePeople**](doc//PersonApi.md#updatepeople) | **PUT** /person |
|
||||||
*PersonApi* | [**updatePerson**](doc//PersonApi.md#updateperson) | **PUT** /person/{id} |
|
*PersonApi* | [**updatePerson**](doc//PersonApi.md#updateperson) | **PUT** /person/{id} |
|
||||||
*SearchApi* | [**getExploreData**](doc//SearchApi.md#getexploredata) | **GET** /search/explore |
|
*SearchApi* | [**getExploreData**](doc//SearchApi.md#getexploredata) | **GET** /search/explore |
|
||||||
|
@ -215,6 +219,9 @@ Class | Method | HTTP request | Description
|
||||||
- [AssetBulkUploadCheckItem](doc//AssetBulkUploadCheckItem.md)
|
- [AssetBulkUploadCheckItem](doc//AssetBulkUploadCheckItem.md)
|
||||||
- [AssetBulkUploadCheckResponseDto](doc//AssetBulkUploadCheckResponseDto.md)
|
- [AssetBulkUploadCheckResponseDto](doc//AssetBulkUploadCheckResponseDto.md)
|
||||||
- [AssetBulkUploadCheckResult](doc//AssetBulkUploadCheckResult.md)
|
- [AssetBulkUploadCheckResult](doc//AssetBulkUploadCheckResult.md)
|
||||||
|
- [AssetFaceBoxDto](doc//AssetFaceBoxDto.md)
|
||||||
|
- [AssetFaceUpdateDto](doc//AssetFaceUpdateDto.md)
|
||||||
|
- [AssetFaceUpdateItem](doc//AssetFaceUpdateItem.md)
|
||||||
- [AssetFileUploadResponseDto](doc//AssetFileUploadResponseDto.md)
|
- [AssetFileUploadResponseDto](doc//AssetFileUploadResponseDto.md)
|
||||||
- [AssetIdsDto](doc//AssetIdsDto.md)
|
- [AssetIdsDto](doc//AssetIdsDto.md)
|
||||||
- [AssetIdsResponseDto](doc//AssetIdsResponseDto.md)
|
- [AssetIdsResponseDto](doc//AssetIdsResponseDto.md)
|
||||||
|
@ -277,6 +284,7 @@ Class | Method | HTTP request | Description
|
||||||
- [OAuthConfigResponseDto](doc//OAuthConfigResponseDto.md)
|
- [OAuthConfigResponseDto](doc//OAuthConfigResponseDto.md)
|
||||||
- [PathEntityType](doc//PathEntityType.md)
|
- [PathEntityType](doc//PathEntityType.md)
|
||||||
- [PathType](doc//PathType.md)
|
- [PathType](doc//PathType.md)
|
||||||
|
- [PeopleAssetResponseDto](doc//PeopleAssetResponseDto.md)
|
||||||
- [PeopleResponseDto](doc//PeopleResponseDto.md)
|
- [PeopleResponseDto](doc//PeopleResponseDto.md)
|
||||||
- [PeopleUpdateDto](doc//PeopleUpdateDto.md)
|
- [PeopleUpdateDto](doc//PeopleUpdateDto.md)
|
||||||
- [PeopleUpdateItem](doc//PeopleUpdateItem.md)
|
- [PeopleUpdateItem](doc//PeopleUpdateItem.md)
|
||||||
|
@ -329,6 +337,7 @@ Class | Method | HTTP request | Description
|
||||||
- [ToneMapping](doc//ToneMapping.md)
|
- [ToneMapping](doc//ToneMapping.md)
|
||||||
- [TranscodeHWAccel](doc//TranscodeHWAccel.md)
|
- [TranscodeHWAccel](doc//TranscodeHWAccel.md)
|
||||||
- [TranscodePolicy](doc//TranscodePolicy.md)
|
- [TranscodePolicy](doc//TranscodePolicy.md)
|
||||||
|
- [UnassignedFacesResponseDto](doc//UnassignedFacesResponseDto.md)
|
||||||
- [UpdateAlbumDto](doc//UpdateAlbumDto.md)
|
- [UpdateAlbumDto](doc//UpdateAlbumDto.md)
|
||||||
- [UpdateAssetDto](doc//UpdateAssetDto.md)
|
- [UpdateAssetDto](doc//UpdateAssetDto.md)
|
||||||
- [UpdateLibraryDto](doc//UpdateLibraryDto.md)
|
- [UpdateLibraryDto](doc//UpdateLibraryDto.md)
|
||||||
|
|
20
mobile/openapi/doc/AssetFaceBoxDto.md
generated
Normal file
20
mobile/openapi/doc/AssetFaceBoxDto.md
generated
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# openapi.model.AssetFaceBoxDto
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**boundingBoxX1** | **int** | |
|
||||||
|
**boundingBoxX2** | **int** | |
|
||||||
|
**boundingBoxY1** | **int** | |
|
||||||
|
**boundingBoxY2** | **int** | |
|
||||||
|
**imageHeight** | **int** | |
|
||||||
|
**imageWidth** | **int** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
15
mobile/openapi/doc/AssetFaceUpdateDto.md
generated
Normal file
15
mobile/openapi/doc/AssetFaceUpdateDto.md
generated
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# openapi.model.AssetFaceUpdateDto
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**data** | [**List<AssetFaceUpdateItem>**](AssetFaceUpdateItem.md) | | [default to const []]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
16
mobile/openapi/doc/AssetFaceUpdateItem.md
generated
Normal file
16
mobile/openapi/doc/AssetFaceUpdateItem.md
generated
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# openapi.model.AssetFaceUpdateItem
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**assetId** | **String** | |
|
||||||
|
**personId** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
3
mobile/openapi/doc/AssetResponseDto.md
generated
3
mobile/openapi/doc/AssetResponseDto.md
generated
|
@ -30,7 +30,7 @@ Name | Type | Description | Notes
|
||||||
**originalPath** | **String** | |
|
**originalPath** | **String** | |
|
||||||
**owner** | [**UserResponseDto**](UserResponseDto.md) | | [optional]
|
**owner** | [**UserResponseDto**](UserResponseDto.md) | | [optional]
|
||||||
**ownerId** | **String** | |
|
**ownerId** | **String** | |
|
||||||
**people** | [**List<PersonResponseDto>**](PersonResponseDto.md) | | [optional] [default to const []]
|
**people** | [**List<PeopleAssetResponseDto>**](PeopleAssetResponseDto.md) | | [optional] [default to const []]
|
||||||
**resized** | **bool** | |
|
**resized** | **bool** | |
|
||||||
**smartInfo** | [**SmartInfoResponseDto**](SmartInfoResponseDto.md) | | [optional]
|
**smartInfo** | [**SmartInfoResponseDto**](SmartInfoResponseDto.md) | | [optional]
|
||||||
**stack** | [**List<AssetResponseDto>**](AssetResponseDto.md) | | [optional] [default to const []]
|
**stack** | [**List<AssetResponseDto>**](AssetResponseDto.md) | | [optional] [default to const []]
|
||||||
|
@ -39,6 +39,7 @@ Name | Type | Description | Notes
|
||||||
**tags** | [**List<TagResponseDto>**](TagResponseDto.md) | | [optional] [default to const []]
|
**tags** | [**List<TagResponseDto>**](TagResponseDto.md) | | [optional] [default to const []]
|
||||||
**thumbhash** | **String** | |
|
**thumbhash** | **String** | |
|
||||||
**type** | [**AssetTypeEnum**](AssetTypeEnum.md) | |
|
**type** | [**AssetTypeEnum**](AssetTypeEnum.md) | |
|
||||||
|
**unassignedPeople** | [**List<UnassignedFacesResponseDto>**](UnassignedFacesResponseDto.md) | | [optional] [default to const []]
|
||||||
**updatedAt** | [**DateTime**](DateTime.md) | |
|
**updatedAt** | [**DateTime**](DateTime.md) | |
|
||||||
|
|
||||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
16
mobile/openapi/doc/PeopleAssetResponseDto.md
generated
Normal file
16
mobile/openapi/doc/PeopleAssetResponseDto.md
generated
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# openapi.model.PeopleAssetResponseDto
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**assetFaceId** | **String** | |
|
||||||
|
**person** | [**PersonResponseDto**](PersonResponseDto.md) | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
228
mobile/openapi/doc/PersonApi.md
generated
228
mobile/openapi/doc/PersonApi.md
generated
|
@ -9,16 +9,75 @@ All URIs are relative to */api*
|
||||||
|
|
||||||
Method | HTTP request | Description
|
Method | HTTP request | Description
|
||||||
------------- | ------------- | -------------
|
------------- | ------------- | -------------
|
||||||
|
[**createPerson**](PersonApi.md#createperson) | **POST** /person |
|
||||||
[**getAllPeople**](PersonApi.md#getallpeople) | **GET** /person |
|
[**getAllPeople**](PersonApi.md#getallpeople) | **GET** /person |
|
||||||
|
[**getAssetFace**](PersonApi.md#getassetface) | **GET** /person/{id}/{assetId}/faceasset |
|
||||||
[**getPerson**](PersonApi.md#getperson) | **GET** /person/{id} |
|
[**getPerson**](PersonApi.md#getperson) | **GET** /person/{id} |
|
||||||
[**getPersonAssets**](PersonApi.md#getpersonassets) | **GET** /person/{id}/assets |
|
[**getPersonAssets**](PersonApi.md#getpersonassets) | **GET** /person/{id}/assets |
|
||||||
[**getPersonStatistics**](PersonApi.md#getpersonstatistics) | **GET** /person/{id}/statistics |
|
[**getPersonStatistics**](PersonApi.md#getpersonstatistics) | **GET** /person/{id}/statistics |
|
||||||
[**getPersonThumbnail**](PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail |
|
[**getPersonThumbnail**](PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail |
|
||||||
[**mergePerson**](PersonApi.md#mergeperson) | **POST** /person/{id}/merge |
|
[**mergePerson**](PersonApi.md#mergeperson) | **POST** /person/{id}/merge |
|
||||||
|
[**reassignFaces**](PersonApi.md#reassignfaces) | **PUT** /person/{id}/reassign |
|
||||||
|
[**unassignFaces**](PersonApi.md#unassignfaces) | **DELETE** /person |
|
||||||
[**updatePeople**](PersonApi.md#updatepeople) | **PUT** /person |
|
[**updatePeople**](PersonApi.md#updatepeople) | **PUT** /person |
|
||||||
[**updatePerson**](PersonApi.md#updateperson) | **PUT** /person/{id} |
|
[**updatePerson**](PersonApi.md#updateperson) | **PUT** /person/{id} |
|
||||||
|
|
||||||
|
|
||||||
|
# **createPerson**
|
||||||
|
> PersonResponseDto createPerson(assetFaceUpdateDto)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = PersonApi();
|
||||||
|
final assetFaceUpdateDto = AssetFaceUpdateDto(); // AssetFaceUpdateDto |
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = api_instance.createPerson(assetFaceUpdateDto);
|
||||||
|
print(result);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling PersonApi->createPerson: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**assetFaceUpdateDto** | [**AssetFaceUpdateDto**](AssetFaceUpdateDto.md)| |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**PersonResponseDto**](PersonResponseDto.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **getAllPeople**
|
# **getAllPeople**
|
||||||
> PeopleResponseDto getAllPeople(withHidden)
|
> PeopleResponseDto getAllPeople(withHidden)
|
||||||
|
|
||||||
|
@ -74,6 +133,63 @@ Name | Type | Description | Notes
|
||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **getAssetFace**
|
||||||
|
> AssetFaceBoxDto getAssetFace(id, assetId)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = PersonApi();
|
||||||
|
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
|
||||||
|
final assetId = assetId_example; // String |
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = api_instance.getAssetFace(id, assetId);
|
||||||
|
print(result);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling PersonApi->getAssetFace: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**id** | **String**| |
|
||||||
|
**assetId** | **String**| |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**AssetFaceBoxDto**](AssetFaceBoxDto.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **getPerson**
|
# **getPerson**
|
||||||
> PersonResponseDto getPerson(id)
|
> PersonResponseDto getPerson(id)
|
||||||
|
|
||||||
|
@ -351,6 +467,118 @@ Name | Type | Description | Notes
|
||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **reassignFaces**
|
||||||
|
> List<PersonResponseDto> reassignFaces(id, assetFaceUpdateDto)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = PersonApi();
|
||||||
|
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
|
||||||
|
final assetFaceUpdateDto = AssetFaceUpdateDto(); // AssetFaceUpdateDto |
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = api_instance.reassignFaces(id, assetFaceUpdateDto);
|
||||||
|
print(result);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling PersonApi->reassignFaces: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**id** | **String**| |
|
||||||
|
**assetFaceUpdateDto** | [**AssetFaceUpdateDto**](AssetFaceUpdateDto.md)| |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**List<PersonResponseDto>**](PersonResponseDto.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **unassignFaces**
|
||||||
|
> List<BulkIdResponseDto> unassignFaces(assetFaceUpdateDto)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = PersonApi();
|
||||||
|
final assetFaceUpdateDto = AssetFaceUpdateDto(); // AssetFaceUpdateDto |
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = api_instance.unassignFaces(assetFaceUpdateDto);
|
||||||
|
print(result);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling PersonApi->unassignFaces: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**assetFaceUpdateDto** | [**AssetFaceUpdateDto**](AssetFaceUpdateDto.md)| |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**List<BulkIdResponseDto>**](BulkIdResponseDto.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **updatePeople**
|
# **updatePeople**
|
||||||
> List<BulkIdResponseDto> updatePeople(peopleUpdateDto)
|
> List<BulkIdResponseDto> updatePeople(peopleUpdateDto)
|
||||||
|
|
||||||
|
|
17
mobile/openapi/doc/UnassignedFacesResponseDto.md
generated
Normal file
17
mobile/openapi/doc/UnassignedFacesResponseDto.md
generated
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# openapi.model.UnassignedFacesResponseDto
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**assetFaceId** | **String** | |
|
||||||
|
**assetId** | **String** | |
|
||||||
|
**boudinxBox** | [**AssetFaceBoxDto**](AssetFaceBoxDto.md) | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
5
mobile/openapi/lib/api.dart
generated
5
mobile/openapi/lib/api.dart
generated
|
@ -60,6 +60,9 @@ part 'model/asset_bulk_upload_check_dto.dart';
|
||||||
part 'model/asset_bulk_upload_check_item.dart';
|
part 'model/asset_bulk_upload_check_item.dart';
|
||||||
part 'model/asset_bulk_upload_check_response_dto.dart';
|
part 'model/asset_bulk_upload_check_response_dto.dart';
|
||||||
part 'model/asset_bulk_upload_check_result.dart';
|
part 'model/asset_bulk_upload_check_result.dart';
|
||||||
|
part 'model/asset_face_box_dto.dart';
|
||||||
|
part 'model/asset_face_update_dto.dart';
|
||||||
|
part 'model/asset_face_update_item.dart';
|
||||||
part 'model/asset_file_upload_response_dto.dart';
|
part 'model/asset_file_upload_response_dto.dart';
|
||||||
part 'model/asset_ids_dto.dart';
|
part 'model/asset_ids_dto.dart';
|
||||||
part 'model/asset_ids_response_dto.dart';
|
part 'model/asset_ids_response_dto.dart';
|
||||||
|
@ -122,6 +125,7 @@ part 'model/o_auth_config_dto.dart';
|
||||||
part 'model/o_auth_config_response_dto.dart';
|
part 'model/o_auth_config_response_dto.dart';
|
||||||
part 'model/path_entity_type.dart';
|
part 'model/path_entity_type.dart';
|
||||||
part 'model/path_type.dart';
|
part 'model/path_type.dart';
|
||||||
|
part 'model/people_asset_response_dto.dart';
|
||||||
part 'model/people_response_dto.dart';
|
part 'model/people_response_dto.dart';
|
||||||
part 'model/people_update_dto.dart';
|
part 'model/people_update_dto.dart';
|
||||||
part 'model/people_update_item.dart';
|
part 'model/people_update_item.dart';
|
||||||
|
@ -174,6 +178,7 @@ part 'model/time_bucket_size.dart';
|
||||||
part 'model/tone_mapping.dart';
|
part 'model/tone_mapping.dart';
|
||||||
part 'model/transcode_hw_accel.dart';
|
part 'model/transcode_hw_accel.dart';
|
||||||
part 'model/transcode_policy.dart';
|
part 'model/transcode_policy.dart';
|
||||||
|
part 'model/unassigned_faces_response_dto.dart';
|
||||||
part 'model/update_album_dto.dart';
|
part 'model/update_album_dto.dart';
|
||||||
part 'model/update_asset_dto.dart';
|
part 'model/update_asset_dto.dart';
|
||||||
part 'model/update_library_dto.dart';
|
part 'model/update_library_dto.dart';
|
||||||
|
|
205
mobile/openapi/lib/api/person_api.dart
generated
205
mobile/openapi/lib/api/person_api.dart
generated
|
@ -16,6 +16,53 @@ class PersonApi {
|
||||||
|
|
||||||
final ApiClient apiClient;
|
final ApiClient apiClient;
|
||||||
|
|
||||||
|
/// Performs an HTTP 'POST /person' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [AssetFaceUpdateDto] assetFaceUpdateDto (required):
|
||||||
|
Future<Response> createPersonWithHttpInfo(AssetFaceUpdateDto assetFaceUpdateDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/person';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = assetFaceUpdateDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'POST',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [AssetFaceUpdateDto] assetFaceUpdateDto (required):
|
||||||
|
Future<PersonResponseDto?> createPerson(AssetFaceUpdateDto assetFaceUpdateDto,) async {
|
||||||
|
final response = await createPersonWithHttpInfo(assetFaceUpdateDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'PersonResponseDto',) as PersonResponseDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'GET /person' operation and returns the [Response].
|
/// Performs an HTTP 'GET /person' operation and returns the [Response].
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
|
@ -67,6 +114,59 @@ class PersonApi {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'GET /person/{id}/{assetId}/faceasset' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
///
|
||||||
|
/// * [String] assetId (required):
|
||||||
|
Future<Response> getAssetFaceWithHttpInfo(String id, String assetId,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/person/{id}/{assetId}/faceasset'
|
||||||
|
.replaceAll('{id}', id)
|
||||||
|
.replaceAll('{assetId}', assetId);
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
///
|
||||||
|
/// * [String] assetId (required):
|
||||||
|
Future<AssetFaceBoxDto?> getAssetFace(String id, String assetId,) async {
|
||||||
|
final response = await getAssetFaceWithHttpInfo(id, assetId,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'AssetFaceBoxDto',) as AssetFaceBoxDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'GET /person/{id}' operation and returns the [Response].
|
/// Performs an HTTP 'GET /person/{id}' operation and returns the [Response].
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
|
@ -317,6 +417,111 @@ class PersonApi {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'PUT /person/{id}/reassign' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
///
|
||||||
|
/// * [AssetFaceUpdateDto] assetFaceUpdateDto (required):
|
||||||
|
Future<Response> reassignFacesWithHttpInfo(String id, AssetFaceUpdateDto assetFaceUpdateDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/person/{id}/reassign'
|
||||||
|
.replaceAll('{id}', id);
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = assetFaceUpdateDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'PUT',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
///
|
||||||
|
/// * [AssetFaceUpdateDto] assetFaceUpdateDto (required):
|
||||||
|
Future<List<PersonResponseDto>?> reassignFaces(String id, AssetFaceUpdateDto assetFaceUpdateDto,) async {
|
||||||
|
final response = await reassignFacesWithHttpInfo(id, assetFaceUpdateDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
final responseBody = await _decodeBodyBytes(response);
|
||||||
|
return (await apiClient.deserializeAsync(responseBody, 'List<PersonResponseDto>') as List)
|
||||||
|
.cast<PersonResponseDto>()
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'DELETE /person' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [AssetFaceUpdateDto] assetFaceUpdateDto (required):
|
||||||
|
Future<Response> unassignFacesWithHttpInfo(AssetFaceUpdateDto assetFaceUpdateDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/person';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = assetFaceUpdateDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'DELETE',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [AssetFaceUpdateDto] assetFaceUpdateDto (required):
|
||||||
|
Future<List<BulkIdResponseDto>?> unassignFaces(AssetFaceUpdateDto assetFaceUpdateDto,) async {
|
||||||
|
final response = await unassignFacesWithHttpInfo(assetFaceUpdateDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
final responseBody = await _decodeBodyBytes(response);
|
||||||
|
return (await apiClient.deserializeAsync(responseBody, 'List<BulkIdResponseDto>') as List)
|
||||||
|
.cast<BulkIdResponseDto>()
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'PUT /person' operation and returns the [Response].
|
/// Performs an HTTP 'PUT /person' operation and returns the [Response].
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
|
|
10
mobile/openapi/lib/api_client.dart
generated
10
mobile/openapi/lib/api_client.dart
generated
|
@ -211,6 +211,12 @@ class ApiClient {
|
||||||
return AssetBulkUploadCheckResponseDto.fromJson(value);
|
return AssetBulkUploadCheckResponseDto.fromJson(value);
|
||||||
case 'AssetBulkUploadCheckResult':
|
case 'AssetBulkUploadCheckResult':
|
||||||
return AssetBulkUploadCheckResult.fromJson(value);
|
return AssetBulkUploadCheckResult.fromJson(value);
|
||||||
|
case 'AssetFaceBoxDto':
|
||||||
|
return AssetFaceBoxDto.fromJson(value);
|
||||||
|
case 'AssetFaceUpdateDto':
|
||||||
|
return AssetFaceUpdateDto.fromJson(value);
|
||||||
|
case 'AssetFaceUpdateItem':
|
||||||
|
return AssetFaceUpdateItem.fromJson(value);
|
||||||
case 'AssetFileUploadResponseDto':
|
case 'AssetFileUploadResponseDto':
|
||||||
return AssetFileUploadResponseDto.fromJson(value);
|
return AssetFileUploadResponseDto.fromJson(value);
|
||||||
case 'AssetIdsDto':
|
case 'AssetIdsDto':
|
||||||
|
@ -335,6 +341,8 @@ class ApiClient {
|
||||||
return PathEntityTypeTypeTransformer().decode(value);
|
return PathEntityTypeTypeTransformer().decode(value);
|
||||||
case 'PathType':
|
case 'PathType':
|
||||||
return PathTypeTypeTransformer().decode(value);
|
return PathTypeTypeTransformer().decode(value);
|
||||||
|
case 'PeopleAssetResponseDto':
|
||||||
|
return PeopleAssetResponseDto.fromJson(value);
|
||||||
case 'PeopleResponseDto':
|
case 'PeopleResponseDto':
|
||||||
return PeopleResponseDto.fromJson(value);
|
return PeopleResponseDto.fromJson(value);
|
||||||
case 'PeopleUpdateDto':
|
case 'PeopleUpdateDto':
|
||||||
|
@ -439,6 +447,8 @@ class ApiClient {
|
||||||
return TranscodeHWAccelTypeTransformer().decode(value);
|
return TranscodeHWAccelTypeTransformer().decode(value);
|
||||||
case 'TranscodePolicy':
|
case 'TranscodePolicy':
|
||||||
return TranscodePolicyTypeTransformer().decode(value);
|
return TranscodePolicyTypeTransformer().decode(value);
|
||||||
|
case 'UnassignedFacesResponseDto':
|
||||||
|
return UnassignedFacesResponseDto.fromJson(value);
|
||||||
case 'UpdateAlbumDto':
|
case 'UpdateAlbumDto':
|
||||||
return UpdateAlbumDto.fromJson(value);
|
return UpdateAlbumDto.fromJson(value);
|
||||||
case 'UpdateAssetDto':
|
case 'UpdateAssetDto':
|
||||||
|
|
138
mobile/openapi/lib/model/asset_face_box_dto.dart
generated
Normal file
138
mobile/openapi/lib/model/asset_face_box_dto.dart
generated
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class AssetFaceBoxDto {
|
||||||
|
/// Returns a new [AssetFaceBoxDto] instance.
|
||||||
|
AssetFaceBoxDto({
|
||||||
|
required this.boundingBoxX1,
|
||||||
|
required this.boundingBoxX2,
|
||||||
|
required this.boundingBoxY1,
|
||||||
|
required this.boundingBoxY2,
|
||||||
|
required this.imageHeight,
|
||||||
|
required this.imageWidth,
|
||||||
|
});
|
||||||
|
|
||||||
|
int boundingBoxX1;
|
||||||
|
|
||||||
|
int boundingBoxX2;
|
||||||
|
|
||||||
|
int boundingBoxY1;
|
||||||
|
|
||||||
|
int boundingBoxY2;
|
||||||
|
|
||||||
|
int imageHeight;
|
||||||
|
|
||||||
|
int imageWidth;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is AssetFaceBoxDto &&
|
||||||
|
other.boundingBoxX1 == boundingBoxX1 &&
|
||||||
|
other.boundingBoxX2 == boundingBoxX2 &&
|
||||||
|
other.boundingBoxY1 == boundingBoxY1 &&
|
||||||
|
other.boundingBoxY2 == boundingBoxY2 &&
|
||||||
|
other.imageHeight == imageHeight &&
|
||||||
|
other.imageWidth == imageWidth;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(boundingBoxX1.hashCode) +
|
||||||
|
(boundingBoxX2.hashCode) +
|
||||||
|
(boundingBoxY1.hashCode) +
|
||||||
|
(boundingBoxY2.hashCode) +
|
||||||
|
(imageHeight.hashCode) +
|
||||||
|
(imageWidth.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'AssetFaceBoxDto[boundingBoxX1=$boundingBoxX1, boundingBoxX2=$boundingBoxX2, boundingBoxY1=$boundingBoxY1, boundingBoxY2=$boundingBoxY2, imageHeight=$imageHeight, imageWidth=$imageWidth]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'boundingBoxX1'] = this.boundingBoxX1;
|
||||||
|
json[r'boundingBoxX2'] = this.boundingBoxX2;
|
||||||
|
json[r'boundingBoxY1'] = this.boundingBoxY1;
|
||||||
|
json[r'boundingBoxY2'] = this.boundingBoxY2;
|
||||||
|
json[r'imageHeight'] = this.imageHeight;
|
||||||
|
json[r'imageWidth'] = this.imageWidth;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [AssetFaceBoxDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static AssetFaceBoxDto? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return AssetFaceBoxDto(
|
||||||
|
boundingBoxX1: mapValueOfType<int>(json, r'boundingBoxX1')!,
|
||||||
|
boundingBoxX2: mapValueOfType<int>(json, r'boundingBoxX2')!,
|
||||||
|
boundingBoxY1: mapValueOfType<int>(json, r'boundingBoxY1')!,
|
||||||
|
boundingBoxY2: mapValueOfType<int>(json, r'boundingBoxY2')!,
|
||||||
|
imageHeight: mapValueOfType<int>(json, r'imageHeight')!,
|
||||||
|
imageWidth: mapValueOfType<int>(json, r'imageWidth')!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<AssetFaceBoxDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <AssetFaceBoxDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = AssetFaceBoxDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, AssetFaceBoxDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, AssetFaceBoxDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = AssetFaceBoxDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of AssetFaceBoxDto-objects as value to a dart map
|
||||||
|
static Map<String, List<AssetFaceBoxDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<AssetFaceBoxDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = AssetFaceBoxDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'boundingBoxX1',
|
||||||
|
'boundingBoxX2',
|
||||||
|
'boundingBoxY1',
|
||||||
|
'boundingBoxY2',
|
||||||
|
'imageHeight',
|
||||||
|
'imageWidth',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
98
mobile/openapi/lib/model/asset_face_update_dto.dart
generated
Normal file
98
mobile/openapi/lib/model/asset_face_update_dto.dart
generated
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class AssetFaceUpdateDto {
|
||||||
|
/// Returns a new [AssetFaceUpdateDto] instance.
|
||||||
|
AssetFaceUpdateDto({
|
||||||
|
this.data = const [],
|
||||||
|
});
|
||||||
|
|
||||||
|
List<AssetFaceUpdateItem> data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is AssetFaceUpdateDto &&
|
||||||
|
other.data == data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(data.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'AssetFaceUpdateDto[data=$data]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'data'] = this.data;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [AssetFaceUpdateDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static AssetFaceUpdateDto? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return AssetFaceUpdateDto(
|
||||||
|
data: AssetFaceUpdateItem.listFromJson(json[r'data']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<AssetFaceUpdateDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <AssetFaceUpdateDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = AssetFaceUpdateDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, AssetFaceUpdateDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, AssetFaceUpdateDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = AssetFaceUpdateDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of AssetFaceUpdateDto-objects as value to a dart map
|
||||||
|
static Map<String, List<AssetFaceUpdateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<AssetFaceUpdateDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = AssetFaceUpdateDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'data',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
106
mobile/openapi/lib/model/asset_face_update_item.dart
generated
Normal file
106
mobile/openapi/lib/model/asset_face_update_item.dart
generated
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class AssetFaceUpdateItem {
|
||||||
|
/// Returns a new [AssetFaceUpdateItem] instance.
|
||||||
|
AssetFaceUpdateItem({
|
||||||
|
required this.assetId,
|
||||||
|
required this.personId,
|
||||||
|
});
|
||||||
|
|
||||||
|
String assetId;
|
||||||
|
|
||||||
|
String personId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is AssetFaceUpdateItem &&
|
||||||
|
other.assetId == assetId &&
|
||||||
|
other.personId == personId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(assetId.hashCode) +
|
||||||
|
(personId.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'AssetFaceUpdateItem[assetId=$assetId, personId=$personId]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'assetId'] = this.assetId;
|
||||||
|
json[r'personId'] = this.personId;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [AssetFaceUpdateItem] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static AssetFaceUpdateItem? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return AssetFaceUpdateItem(
|
||||||
|
assetId: mapValueOfType<String>(json, r'assetId')!,
|
||||||
|
personId: mapValueOfType<String>(json, r'personId')!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<AssetFaceUpdateItem> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <AssetFaceUpdateItem>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = AssetFaceUpdateItem.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, AssetFaceUpdateItem> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, AssetFaceUpdateItem>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = AssetFaceUpdateItem.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of AssetFaceUpdateItem-objects as value to a dart map
|
||||||
|
static Map<String, List<AssetFaceUpdateItem>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<AssetFaceUpdateItem>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = AssetFaceUpdateItem.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'assetId',
|
||||||
|
'personId',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
13
mobile/openapi/lib/model/asset_response_dto.dart
generated
13
mobile/openapi/lib/model/asset_response_dto.dart
generated
|
@ -44,6 +44,7 @@ class AssetResponseDto {
|
||||||
this.tags = const [],
|
this.tags = const [],
|
||||||
required this.thumbhash,
|
required this.thumbhash,
|
||||||
required this.type,
|
required this.type,
|
||||||
|
this.unassignedPeople = const [],
|
||||||
required this.updatedAt,
|
required this.updatedAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -104,7 +105,7 @@ class AssetResponseDto {
|
||||||
|
|
||||||
String ownerId;
|
String ownerId;
|
||||||
|
|
||||||
List<PersonResponseDto> people;
|
List<PeopleAssetResponseDto> people;
|
||||||
|
|
||||||
bool resized;
|
bool resized;
|
||||||
|
|
||||||
|
@ -128,6 +129,8 @@ class AssetResponseDto {
|
||||||
|
|
||||||
AssetTypeEnum type;
|
AssetTypeEnum type;
|
||||||
|
|
||||||
|
List<UnassignedFacesResponseDto> unassignedPeople;
|
||||||
|
|
||||||
DateTime updatedAt;
|
DateTime updatedAt;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -163,6 +166,7 @@ class AssetResponseDto {
|
||||||
other.tags == tags &&
|
other.tags == tags &&
|
||||||
other.thumbhash == thumbhash &&
|
other.thumbhash == thumbhash &&
|
||||||
other.type == type &&
|
other.type == type &&
|
||||||
|
other.unassignedPeople == unassignedPeople &&
|
||||||
other.updatedAt == updatedAt;
|
other.updatedAt == updatedAt;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -199,10 +203,11 @@ class AssetResponseDto {
|
||||||
(tags.hashCode) +
|
(tags.hashCode) +
|
||||||
(thumbhash == null ? 0 : thumbhash!.hashCode) +
|
(thumbhash == null ? 0 : thumbhash!.hashCode) +
|
||||||
(type.hashCode) +
|
(type.hashCode) +
|
||||||
|
(unassignedPeople.hashCode) +
|
||||||
(updatedAt.hashCode);
|
(updatedAt.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'AssetResponseDto[checksum=$checksum, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, isExternal=$isExternal, isFavorite=$isFavorite, isOffline=$isOffline, isReadOnly=$isReadOnly, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, resized=$resized, smartInfo=$smartInfo, stack=$stack, stackCount=$stackCount, stackParentId=$stackParentId, tags=$tags, thumbhash=$thumbhash, type=$type, updatedAt=$updatedAt]';
|
String toString() => 'AssetResponseDto[checksum=$checksum, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, isExternal=$isExternal, isFavorite=$isFavorite, isOffline=$isOffline, isReadOnly=$isReadOnly, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, resized=$resized, smartInfo=$smartInfo, stack=$stack, stackCount=$stackCount, stackParentId=$stackParentId, tags=$tags, thumbhash=$thumbhash, type=$type, unassignedPeople=$unassignedPeople, updatedAt=$updatedAt]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
|
@ -261,6 +266,7 @@ class AssetResponseDto {
|
||||||
// json[r'thumbhash'] = null;
|
// json[r'thumbhash'] = null;
|
||||||
}
|
}
|
||||||
json[r'type'] = this.type;
|
json[r'type'] = this.type;
|
||||||
|
json[r'unassignedPeople'] = this.unassignedPeople;
|
||||||
json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
|
json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +301,7 @@ class AssetResponseDto {
|
||||||
originalPath: mapValueOfType<String>(json, r'originalPath')!,
|
originalPath: mapValueOfType<String>(json, r'originalPath')!,
|
||||||
owner: UserResponseDto.fromJson(json[r'owner']),
|
owner: UserResponseDto.fromJson(json[r'owner']),
|
||||||
ownerId: mapValueOfType<String>(json, r'ownerId')!,
|
ownerId: mapValueOfType<String>(json, r'ownerId')!,
|
||||||
people: PersonResponseDto.listFromJson(json[r'people']),
|
people: PeopleAssetResponseDto.listFromJson(json[r'people']),
|
||||||
resized: mapValueOfType<bool>(json, r'resized')!,
|
resized: mapValueOfType<bool>(json, r'resized')!,
|
||||||
smartInfo: SmartInfoResponseDto.fromJson(json[r'smartInfo']),
|
smartInfo: SmartInfoResponseDto.fromJson(json[r'smartInfo']),
|
||||||
stack: AssetResponseDto.listFromJson(json[r'stack']),
|
stack: AssetResponseDto.listFromJson(json[r'stack']),
|
||||||
|
@ -304,6 +310,7 @@ class AssetResponseDto {
|
||||||
tags: TagResponseDto.listFromJson(json[r'tags']),
|
tags: TagResponseDto.listFromJson(json[r'tags']),
|
||||||
thumbhash: mapValueOfType<String>(json, r'thumbhash'),
|
thumbhash: mapValueOfType<String>(json, r'thumbhash'),
|
||||||
type: AssetTypeEnum.fromJson(json[r'type'])!,
|
type: AssetTypeEnum.fromJson(json[r'type'])!,
|
||||||
|
unassignedPeople: UnassignedFacesResponseDto.listFromJson(json[r'unassignedPeople']),
|
||||||
updatedAt: mapDateTime(json, r'updatedAt', '')!,
|
updatedAt: mapDateTime(json, r'updatedAt', '')!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
106
mobile/openapi/lib/model/people_asset_response_dto.dart
generated
Normal file
106
mobile/openapi/lib/model/people_asset_response_dto.dart
generated
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class PeopleAssetResponseDto {
|
||||||
|
/// Returns a new [PeopleAssetResponseDto] instance.
|
||||||
|
PeopleAssetResponseDto({
|
||||||
|
required this.assetFaceId,
|
||||||
|
required this.person,
|
||||||
|
});
|
||||||
|
|
||||||
|
String assetFaceId;
|
||||||
|
|
||||||
|
PersonResponseDto person;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is PeopleAssetResponseDto &&
|
||||||
|
other.assetFaceId == assetFaceId &&
|
||||||
|
other.person == person;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(assetFaceId.hashCode) +
|
||||||
|
(person.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'PeopleAssetResponseDto[assetFaceId=$assetFaceId, person=$person]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'assetFaceId'] = this.assetFaceId;
|
||||||
|
json[r'person'] = this.person;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [PeopleAssetResponseDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static PeopleAssetResponseDto? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return PeopleAssetResponseDto(
|
||||||
|
assetFaceId: mapValueOfType<String>(json, r'assetFaceId')!,
|
||||||
|
person: PersonResponseDto.fromJson(json[r'person'])!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<PeopleAssetResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <PeopleAssetResponseDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = PeopleAssetResponseDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, PeopleAssetResponseDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, PeopleAssetResponseDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = PeopleAssetResponseDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of PeopleAssetResponseDto-objects as value to a dart map
|
||||||
|
static Map<String, List<PeopleAssetResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<PeopleAssetResponseDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = PeopleAssetResponseDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'assetFaceId',
|
||||||
|
'person',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
114
mobile/openapi/lib/model/unassigned_faces_response_dto.dart
generated
Normal file
114
mobile/openapi/lib/model/unassigned_faces_response_dto.dart
generated
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class UnassignedFacesResponseDto {
|
||||||
|
/// Returns a new [UnassignedFacesResponseDto] instance.
|
||||||
|
UnassignedFacesResponseDto({
|
||||||
|
required this.assetFaceId,
|
||||||
|
required this.assetId,
|
||||||
|
required this.boudinxBox,
|
||||||
|
});
|
||||||
|
|
||||||
|
String assetFaceId;
|
||||||
|
|
||||||
|
String assetId;
|
||||||
|
|
||||||
|
AssetFaceBoxDto boudinxBox;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is UnassignedFacesResponseDto &&
|
||||||
|
other.assetFaceId == assetFaceId &&
|
||||||
|
other.assetId == assetId &&
|
||||||
|
other.boudinxBox == boudinxBox;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(assetFaceId.hashCode) +
|
||||||
|
(assetId.hashCode) +
|
||||||
|
(boudinxBox.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'UnassignedFacesResponseDto[assetFaceId=$assetFaceId, assetId=$assetId, boudinxBox=$boudinxBox]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'assetFaceId'] = this.assetFaceId;
|
||||||
|
json[r'assetId'] = this.assetId;
|
||||||
|
json[r'boudinxBox'] = this.boudinxBox;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [UnassignedFacesResponseDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static UnassignedFacesResponseDto? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return UnassignedFacesResponseDto(
|
||||||
|
assetFaceId: mapValueOfType<String>(json, r'assetFaceId')!,
|
||||||
|
assetId: mapValueOfType<String>(json, r'assetId')!,
|
||||||
|
boudinxBox: AssetFaceBoxDto.fromJson(json[r'boudinxBox'])!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<UnassignedFacesResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <UnassignedFacesResponseDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = UnassignedFacesResponseDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, UnassignedFacesResponseDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, UnassignedFacesResponseDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = UnassignedFacesResponseDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of UnassignedFacesResponseDto-objects as value to a dart map
|
||||||
|
static Map<String, List<UnassignedFacesResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<UnassignedFacesResponseDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = UnassignedFacesResponseDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'assetFaceId',
|
||||||
|
'assetId',
|
||||||
|
'boudinxBox',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
52
mobile/openapi/test/asset_face_box_dto_test.dart
generated
Normal file
52
mobile/openapi/test/asset_face_box_dto_test.dart
generated
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
// tests for AssetFaceBoxDto
|
||||||
|
void main() {
|
||||||
|
// final instance = AssetFaceBoxDto();
|
||||||
|
|
||||||
|
group('test AssetFaceBoxDto', () {
|
||||||
|
// int boundingBoxX1
|
||||||
|
test('to test the property `boundingBoxX1`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int boundingBoxX2
|
||||||
|
test('to test the property `boundingBoxX2`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int boundingBoxY1
|
||||||
|
test('to test the property `boundingBoxY1`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int boundingBoxY2
|
||||||
|
test('to test the property `boundingBoxY2`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int imageHeight
|
||||||
|
test('to test the property `imageHeight`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int imageWidth
|
||||||
|
test('to test the property `imageWidth`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
27
mobile/openapi/test/asset_face_update_dto_test.dart
generated
Normal file
27
mobile/openapi/test/asset_face_update_dto_test.dart
generated
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
// tests for AssetFaceUpdateDto
|
||||||
|
void main() {
|
||||||
|
// final instance = AssetFaceUpdateDto();
|
||||||
|
|
||||||
|
group('test AssetFaceUpdateDto', () {
|
||||||
|
// List<AssetFaceUpdateItem> data (default value: const [])
|
||||||
|
test('to test the property `data`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
32
mobile/openapi/test/asset_face_update_item_test.dart
generated
Normal file
32
mobile/openapi/test/asset_face_update_item_test.dart
generated
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
// tests for AssetFaceUpdateItem
|
||||||
|
void main() {
|
||||||
|
// final instance = AssetFaceUpdateItem();
|
||||||
|
|
||||||
|
group('test AssetFaceUpdateItem', () {
|
||||||
|
// String assetId
|
||||||
|
test('to test the property `assetId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String personId
|
||||||
|
test('to test the property `personId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
7
mobile/openapi/test/asset_response_dto_test.dart
generated
7
mobile/openapi/test/asset_response_dto_test.dart
generated
|
@ -127,7 +127,7 @@ void main() {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
// List<PersonResponseDto> people (default value: const [])
|
// List<PeopleAssetResponseDto> people (default value: const [])
|
||||||
test('to test the property `people`', () async {
|
test('to test the property `people`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
@ -172,6 +172,11 @@ void main() {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// List<UnassignedFacesResponseDto> unassignedPeople (default value: const [])
|
||||||
|
test('to test the property `unassignedPeople`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
// DateTime updatedAt
|
// DateTime updatedAt
|
||||||
test('to test the property `updatedAt`', () async {
|
test('to test the property `updatedAt`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
32
mobile/openapi/test/people_asset_response_dto_test.dart
generated
Normal file
32
mobile/openapi/test/people_asset_response_dto_test.dart
generated
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
// tests for PeopleAssetResponseDto
|
||||||
|
void main() {
|
||||||
|
// final instance = PeopleAssetResponseDto();
|
||||||
|
|
||||||
|
group('test PeopleAssetResponseDto', () {
|
||||||
|
// String assetFaceId
|
||||||
|
test('to test the property `assetFaceId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// PersonResponseDto person
|
||||||
|
test('to test the property `person`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
20
mobile/openapi/test/person_api_test.dart
generated
20
mobile/openapi/test/person_api_test.dart
generated
|
@ -17,11 +17,21 @@ void main() {
|
||||||
// final instance = PersonApi();
|
// final instance = PersonApi();
|
||||||
|
|
||||||
group('tests for PersonApi', () {
|
group('tests for PersonApi', () {
|
||||||
|
//Future<PersonResponseDto> createPerson(AssetFaceUpdateDto assetFaceUpdateDto) async
|
||||||
|
test('test createPerson', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
//Future<PeopleResponseDto> getAllPeople({ bool withHidden }) async
|
//Future<PeopleResponseDto> getAllPeople({ bool withHidden }) async
|
||||||
test('test getAllPeople', () async {
|
test('test getAllPeople', () async {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Future<AssetFaceBoxDto> getAssetFace(String id, String assetId) async
|
||||||
|
test('test getAssetFace', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
//Future<PersonResponseDto> getPerson(String id) async
|
//Future<PersonResponseDto> getPerson(String id) async
|
||||||
test('test getPerson', () async {
|
test('test getPerson', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -47,6 +57,16 @@ void main() {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Future<List<PersonResponseDto>> reassignFaces(String id, AssetFaceUpdateDto assetFaceUpdateDto) async
|
||||||
|
test('test reassignFaces', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
//Future<List<BulkIdResponseDto>> unassignFaces(AssetFaceUpdateDto assetFaceUpdateDto) async
|
||||||
|
test('test unassignFaces', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
//Future<List<BulkIdResponseDto>> updatePeople(PeopleUpdateDto peopleUpdateDto) async
|
//Future<List<BulkIdResponseDto>> updatePeople(PeopleUpdateDto peopleUpdateDto) async
|
||||||
test('test updatePeople', () async {
|
test('test updatePeople', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
37
mobile/openapi/test/unassigned_faces_response_dto_test.dart
generated
Normal file
37
mobile/openapi/test/unassigned_faces_response_dto_test.dart
generated
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
// tests for UnassignedFacesResponseDto
|
||||||
|
void main() {
|
||||||
|
// final instance = UnassignedFacesResponseDto();
|
||||||
|
|
||||||
|
group('test UnassignedFacesResponseDto', () {
|
||||||
|
// String assetFaceId
|
||||||
|
test('to test the property `assetFaceId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String assetId
|
||||||
|
test('to test the property `assetId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// AssetFaceBoxDto boudinxBox
|
||||||
|
test('to test the property `boudinxBox`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
|
@ -3357,6 +3357,49 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/person": {
|
"/person": {
|
||||||
|
"delete": {
|
||||||
|
"operationId": "unassignFaces",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AssetFaceUpdateDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/BulkIdResponseDto"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Person"
|
||||||
|
]
|
||||||
|
},
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "getAllPeople",
|
"operationId": "getAllPeople",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
|
@ -3397,6 +3440,46 @@
|
||||||
"Person"
|
"Person"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"post": {
|
||||||
|
"operationId": "createPerson",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AssetFaceUpdateDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/PersonResponseDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Person"
|
||||||
|
]
|
||||||
|
},
|
||||||
"put": {
|
"put": {
|
||||||
"operationId": "updatePeople",
|
"operationId": "updatePeople",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
|
@ -3633,6 +3716,61 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/person/{id}/reassign": {
|
||||||
|
"put": {
|
||||||
|
"operationId": "reassignFaces",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"required": true,
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AssetFaceUpdateDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/PersonResponseDto"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Person"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/person/{id}/statistics": {
|
"/person/{id}/statistics": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "getPersonStatistics",
|
"operationId": "getPersonStatistics",
|
||||||
|
@ -3718,6 +3856,56 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/person/{id}/{assetId}/faceasset": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "getAssetFace",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"required": true,
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "assetId",
|
||||||
|
"required": true,
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AssetFaceBoxDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Person"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/search": {
|
"/search": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "search",
|
"operationId": "search",
|
||||||
|
@ -5816,6 +6004,66 @@
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"AssetFaceBoxDto": {
|
||||||
|
"properties": {
|
||||||
|
"boundingBoxX1": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"boundingBoxX2": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"boundingBoxY1": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"boundingBoxY2": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"imageHeight": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"imageWidth": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"imageWidth",
|
||||||
|
"imageHeight",
|
||||||
|
"boundingBoxX1",
|
||||||
|
"boundingBoxY1",
|
||||||
|
"boundingBoxX2",
|
||||||
|
"boundingBoxY2"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"AssetFaceUpdateDto": {
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/AssetFaceUpdateItem"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"data"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"AssetFaceUpdateItem": {
|
||||||
|
"properties": {
|
||||||
|
"assetId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"personId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"personId",
|
||||||
|
"assetId"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"AssetFileUploadResponseDto": {
|
"AssetFileUploadResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"duplicate": {
|
"duplicate": {
|
||||||
|
@ -5971,7 +6219,7 @@
|
||||||
},
|
},
|
||||||
"people": {
|
"people": {
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/components/schemas/PersonResponseDto"
|
"$ref": "#/components/schemas/PeopleAssetResponseDto"
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
|
@ -6007,6 +6255,12 @@
|
||||||
"type": {
|
"type": {
|
||||||
"$ref": "#/components/schemas/AssetTypeEnum"
|
"$ref": "#/components/schemas/AssetTypeEnum"
|
||||||
},
|
},
|
||||||
|
"unassignedPeople": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/UnassignedFacesResponseDto"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
"updatedAt": {
|
"updatedAt": {
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -7275,6 +7529,21 @@
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"PeopleAssetResponseDto": {
|
||||||
|
"properties": {
|
||||||
|
"assetFaceId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"person": {
|
||||||
|
"$ref": "#/components/schemas/PersonResponseDto"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"assetFaceId",
|
||||||
|
"person"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"PeopleResponseDto": {
|
"PeopleResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"people": {
|
"people": {
|
||||||
|
@ -8539,6 +8808,25 @@
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"UnassignedFacesResponseDto": {
|
||||||
|
"properties": {
|
||||||
|
"assetFaceId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"assetId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"boudinxBox": {
|
||||||
|
"$ref": "#/components/schemas/AssetFaceBoxDto"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"assetFaceId",
|
||||||
|
"assetId",
|
||||||
|
"boudinxBox"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"UpdateAlbumDto": {
|
"UpdateAlbumDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"albumName": {
|
"albumName": {
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import { AssetEntity, AssetType } from '@app/infra/entities';
|
import { AssetEntity, AssetType } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { PersonResponseDto, mapFace } from '../../person/person.dto';
|
import {
|
||||||
|
PeopleAssetResponseDto,
|
||||||
|
UnassignedFacesResponseDto,
|
||||||
|
mapFace,
|
||||||
|
mapUnassignedFace,
|
||||||
|
} from '../../person/person.dto';
|
||||||
import { TagResponseDto, mapTag } from '../../tag';
|
import { TagResponseDto, mapTag } from '../../tag';
|
||||||
import { UserResponseDto, mapUser } from '../../user/response-dto/user-response.dto';
|
import { UserResponseDto, mapUser } from '../../user/response-dto/user-response.dto';
|
||||||
import { ExifResponseDto, mapExif } from './exif-response.dto';
|
import { ExifResponseDto, mapExif } from './exif-response.dto';
|
||||||
|
@ -39,7 +44,8 @@ export class AssetResponseDto extends SanitizedAssetResponseDto {
|
||||||
exifInfo?: ExifResponseDto;
|
exifInfo?: ExifResponseDto;
|
||||||
smartInfo?: SmartInfoResponseDto;
|
smartInfo?: SmartInfoResponseDto;
|
||||||
tags?: TagResponseDto[];
|
tags?: TagResponseDto[];
|
||||||
people?: PersonResponseDto[];
|
unassignedPeople?: UnassignedFacesResponseDto[];
|
||||||
|
people?: PeopleAssetResponseDto[];
|
||||||
/**base64 encoded sha1 hash */
|
/**base64 encoded sha1 hash */
|
||||||
checksum!: string;
|
checksum!: string;
|
||||||
stackParentId?: string | null;
|
stackParentId?: string | null;
|
||||||
|
@ -96,9 +102,12 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As
|
||||||
smartInfo: entity.smartInfo ? mapSmartInfo(entity.smartInfo) : undefined,
|
smartInfo: entity.smartInfo ? mapSmartInfo(entity.smartInfo) : undefined,
|
||||||
livePhotoVideoId: entity.livePhotoVideoId,
|
livePhotoVideoId: entity.livePhotoVideoId,
|
||||||
tags: entity.tags?.map(mapTag),
|
tags: entity.tags?.map(mapTag),
|
||||||
|
unassignedPeople: entity.faces
|
||||||
|
?.map(mapUnassignedFace)
|
||||||
|
.filter((assetFace) => assetFace) as UnassignedFacesResponseDto[],
|
||||||
people: entity.faces
|
people: entity.faces
|
||||||
?.map(mapFace)
|
?.map(mapFace)
|
||||||
.filter((person): person is PersonResponseDto => person !== null && !person.isHidden),
|
.filter((assetFace) => assetFace && !assetFace.person.isHidden) as PeopleAssetResponseDto[],
|
||||||
checksum: entity.checksum.toString('base64'),
|
checksum: entity.checksum.toString('base64'),
|
||||||
stackParentId: entity.stackParentId,
|
stackParentId: entity.stackParentId,
|
||||||
stack: withStack ? entity.stack?.map((a) => mapAsset(a, { stripMetadata })) ?? undefined : undefined,
|
stack: withStack ? entity.stack?.map((a) => mapAsset(a, { stripMetadata })) ?? undefined : undefined,
|
||||||
|
|
|
@ -44,6 +44,23 @@ export class PeopleUpdateDto {
|
||||||
people!: PeopleUpdateItem[];
|
people!: PeopleUpdateItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class AssetFaceUpdateDto {
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => AssetFaceUpdateItem)
|
||||||
|
data!: AssetFaceUpdateItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AssetFaceUpdateItem {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
personId!: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
assetId!: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class PeopleUpdateItem extends PersonUpdateDto {
|
export class PeopleUpdateItem extends PersonUpdateDto {
|
||||||
/**
|
/**
|
||||||
* Person id.
|
* Person id.
|
||||||
|
@ -64,6 +81,26 @@ export class PersonSearchDto {
|
||||||
withHidden?: boolean = false;
|
withHidden?: boolean = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class AssetFaceBoxDto {
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
imageWidth!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
imageHeight!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
boundingBoxX1!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
boundingBoxY1!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
boundingBoxX2!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
boundingBoxY2!: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class PersonResponseDto {
|
export class PersonResponseDto {
|
||||||
id!: string;
|
id!: string;
|
||||||
name!: string;
|
name!: string;
|
||||||
|
@ -73,6 +110,17 @@ export class PersonResponseDto {
|
||||||
isHidden!: boolean;
|
isHidden!: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class PeopleAssetResponseDto {
|
||||||
|
assetFaceId!: string;
|
||||||
|
person!: PersonResponseDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UnassignedFacesResponseDto {
|
||||||
|
assetFaceId!: string;
|
||||||
|
assetId!: string;
|
||||||
|
boudinxBox!: AssetFaceBoxDto;
|
||||||
|
}
|
||||||
|
|
||||||
export class PersonStatisticsResponseDto {
|
export class PersonStatisticsResponseDto {
|
||||||
@ApiProperty({ type: 'integer' })
|
@ApiProperty({ type: 'integer' })
|
||||||
assets!: number;
|
assets!: number;
|
||||||
|
@ -98,10 +146,32 @@ export function mapPerson(person: PersonEntity): PersonResponseDto {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapFace(face: AssetFaceEntity): PersonResponseDto | null {
|
export function mapFace(face: AssetFaceEntity): PeopleAssetResponseDto | null {
|
||||||
if (face.person) {
|
if (face.person) {
|
||||||
return mapPerson(face.person);
|
return {
|
||||||
|
assetFaceId: face.id,
|
||||||
|
person: face.person,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapUnassignedFace(face: AssetFaceEntity): UnassignedFacesResponseDto | null {
|
||||||
|
if (face.person !== null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
assetFaceId: face.id,
|
||||||
|
assetId: face.assetId,
|
||||||
|
boudinxBox: {
|
||||||
|
imageWidth: face.imageWidth,
|
||||||
|
imageHeight: face.imageHeight,
|
||||||
|
boundingBoxX1: face.boundingBoxX1,
|
||||||
|
boundingBoxY1: face.boundingBoxY1,
|
||||||
|
boundingBoxX2: face.boundingBoxX2,
|
||||||
|
boundingBoxY2: face.boundingBoxY2,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ import {
|
||||||
import { StorageCore } from '../storage';
|
import { StorageCore } from '../storage';
|
||||||
import { SystemConfigCore } from '../system-config';
|
import { SystemConfigCore } from '../system-config';
|
||||||
import {
|
import {
|
||||||
|
AssetFaceBoxDto,
|
||||||
|
AssetFaceUpdateDto,
|
||||||
MergePersonDto,
|
MergePersonDto,
|
||||||
PeopleResponseDto,
|
PeopleResponseDto,
|
||||||
PeopleUpdateDto,
|
PeopleUpdateDto,
|
||||||
|
@ -210,6 +212,137 @@ export class PersonService {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getFaceEntity(authUser: AuthUserDto, personId: string, assetId: string): Promise<AssetFaceBoxDto> {
|
||||||
|
await this.access.requirePermission(authUser, Permission.PERSON_READ, personId);
|
||||||
|
const [face] = await this.repository.getFacesByIds([{ personId, assetId }]);
|
||||||
|
if (!face) {
|
||||||
|
throw new BadRequestException('Invalid assetId for feature face');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
boundingBoxX1: face.boundingBoxX1,
|
||||||
|
boundingBoxX2: face.boundingBoxX2,
|
||||||
|
boundingBoxY1: face.boundingBoxY1,
|
||||||
|
boundingBoxY2: face.boundingBoxY2,
|
||||||
|
imageHeight: face.imageHeight,
|
||||||
|
imageWidth: face.imageWidth,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async createPerson(authUser: AuthUserDto, dto: AssetFaceUpdateDto): Promise<PersonResponseDto> {
|
||||||
|
const changeFeaturePhoto: string[] = [];
|
||||||
|
|
||||||
|
const newPerson = await this.repository.create({ ownerId: authUser.id });
|
||||||
|
for (const data of dto.data) {
|
||||||
|
try {
|
||||||
|
await this.repository.reassignFace(data.personId, newPerson.id, data.assetId);
|
||||||
|
|
||||||
|
await this.repository.update({
|
||||||
|
id: newPerson.id,
|
||||||
|
faceAssetId: data.assetId,
|
||||||
|
});
|
||||||
|
const [face] = await this.repository.getFacesByIds([{ personId: newPerson.id, assetId: data.assetId }]);
|
||||||
|
const oldPerson = await this.findOrFail(data.personId);
|
||||||
|
if (oldPerson.faceAssetId === face?.assetId) {
|
||||||
|
changeFeaturePhoto.push(oldPerson.id);
|
||||||
|
}
|
||||||
|
if (!face) {
|
||||||
|
throw new BadRequestException('Invalid assetId for feature face');
|
||||||
|
}
|
||||||
|
} catch (error: Error | any) {
|
||||||
|
this.logger.error(`Unable to create a new person`, error?.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const newPersonFeaturePhoto = await this.repository.getRandomFace(newPerson.id);
|
||||||
|
if (newPersonFeaturePhoto) {
|
||||||
|
await this.repository.update({
|
||||||
|
id: newPerson.id,
|
||||||
|
faceAssetId: newPersonFeaturePhoto.assetId,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.jobRepository.queue({
|
||||||
|
name: JobName.GENERATE_PERSON_THUMBNAIL,
|
||||||
|
data: {
|
||||||
|
id: newPerson.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.createNewFeaturePhoto(changeFeaturePhoto);
|
||||||
|
|
||||||
|
return newPerson;
|
||||||
|
}
|
||||||
|
|
||||||
|
async reassignFaces(authUser: AuthUserDto, personId: string, dto: AssetFaceUpdateDto): Promise<PersonResponseDto[]> {
|
||||||
|
await this.access.requirePermission(authUser, Permission.PERSON_WRITE, personId);
|
||||||
|
|
||||||
|
const result: PersonResponseDto[] = [];
|
||||||
|
const changeFeaturePhoto: string[] = [];
|
||||||
|
|
||||||
|
for (const data of dto.data) {
|
||||||
|
try {
|
||||||
|
const [face] = await this.repository.getFacesByIds([{ personId: data.personId, assetId: data.assetId }]);
|
||||||
|
const oldPerson = await this.findOrFail(data.personId);
|
||||||
|
if (oldPerson.faceAssetId === face?.assetId) {
|
||||||
|
changeFeaturePhoto.push(oldPerson.id);
|
||||||
|
}
|
||||||
|
await this.repository.reassignFace(data.personId, personId, data.assetId);
|
||||||
|
|
||||||
|
result.push(await this.findOrFail(personId).then(mapPerson));
|
||||||
|
} catch (error: Error | any) {
|
||||||
|
this.logger.error(
|
||||||
|
`Unable to un-merge asset ${data.assetId} from ${data.personId} to ${personId}`,
|
||||||
|
error?.stack,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.createNewFeaturePhoto(changeFeaturePhoto);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async unassignFaces(authUser: AuthUserDto, dto: AssetFaceUpdateDto): Promise<BulkIdResponseDto[]> {
|
||||||
|
const results: BulkIdResponseDto[] = [];
|
||||||
|
|
||||||
|
for (const data of dto.data) {
|
||||||
|
try {
|
||||||
|
const [face] = await this.repository.getFacesByIds([{ personId: data.personId, assetId: data.assetId }]);
|
||||||
|
await this.access.requirePermission(authUser, Permission.ASSET_VIEW, face.assetId);
|
||||||
|
await this.repository.unassignFace(face.id);
|
||||||
|
|
||||||
|
results.push({id:face.id, success:true});
|
||||||
|
} catch (error: Error | any) {
|
||||||
|
this.logger.error(
|
||||||
|
`Unable to un-merge asset ${data.assetId} from ${data.personId}`,
|
||||||
|
error?.stack,
|
||||||
|
);
|
||||||
|
results.push({ id: 'face.id', success: false, error: BulkIdErrorReason.UNKNOWN });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createNewFeaturePhoto(changeFeaturePhoto: string[]) {
|
||||||
|
for (const personId of changeFeaturePhoto) {
|
||||||
|
const assetFace = await this.repository.getRandomFace(personId);
|
||||||
|
if (assetFace !== null) {
|
||||||
|
await this.repository.update({
|
||||||
|
id: personId,
|
||||||
|
faceAssetId: assetFace.assetId,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.jobRepository.queue({
|
||||||
|
name: JobName.GENERATE_PERSON_THUMBNAIL,
|
||||||
|
data: {
|
||||||
|
id: personId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async handleRecognizeFaces({ id }: IEntityJob) {
|
async handleRecognizeFaces({ id }: IEntityJob) {
|
||||||
const { machineLearning } = await this.configCore.getConfig();
|
const { machineLearning } = await this.configCore.getConfig();
|
||||||
if (!machineLearning.enabled || !machineLearning.facialRecognition.enabled) {
|
if (!machineLearning.enabled || !machineLearning.facialRecognition.enabled) {
|
||||||
|
|
|
@ -36,6 +36,8 @@ export interface IPersonRepository {
|
||||||
getAssets(personId: string): Promise<AssetEntity[]>;
|
getAssets(personId: string): Promise<AssetEntity[]>;
|
||||||
prepareReassignFaces(data: UpdateFacesData): Promise<string[]>;
|
prepareReassignFaces(data: UpdateFacesData): Promise<string[]>;
|
||||||
reassignFaces(data: UpdateFacesData): Promise<number>;
|
reassignFaces(data: UpdateFacesData): Promise<number>;
|
||||||
|
reassignFace(oldPersonId: string, newPersonId: string, assetId: string): Promise<number>;
|
||||||
|
unassignFace(id: string): Promise<number>;
|
||||||
|
|
||||||
create(entity: Partial<PersonEntity>): Promise<PersonEntity>;
|
create(entity: Partial<PersonEntity>): Promise<PersonEntity>;
|
||||||
update(entity: Partial<PersonEntity>): Promise<PersonEntity>;
|
update(entity: Partial<PersonEntity>): Promise<PersonEntity>;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import {
|
import {
|
||||||
|
AssetFaceBoxDto,
|
||||||
|
AssetFaceUpdateDto,
|
||||||
AssetResponseDto,
|
AssetResponseDto,
|
||||||
AuthUserDto,
|
AuthUserDto,
|
||||||
BulkIdResponseDto,
|
BulkIdResponseDto,
|
||||||
|
@ -12,8 +14,9 @@ import {
|
||||||
PersonStatisticsResponseDto,
|
PersonStatisticsResponseDto,
|
||||||
PersonUpdateDto,
|
PersonUpdateDto,
|
||||||
} from '@app/domain';
|
} from '@app/domain';
|
||||||
import { Body, Controller, Get, Param, Post, Put, Query, StreamableFile } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, Param, Post, Put, Query, StreamableFile } from '@nestjs/common';
|
||||||
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||||
|
import { ParseMeUUIDPipe } from '../api-v1/validation/parse-me-uuid-pipe';
|
||||||
import { AuthUser, Authenticated } from '../app.guard';
|
import { AuthUser, Authenticated } from '../app.guard';
|
||||||
import { UseValidation } from '../app.utils';
|
import { UseValidation } from '../app.utils';
|
||||||
import { UUIDParamDto } from './dto/uuid-param.dto';
|
import { UUIDParamDto } from './dto/uuid-param.dto';
|
||||||
|
@ -29,6 +32,37 @@ function asStreamableFile({ stream, type, length }: ImmichReadStream) {
|
||||||
export class PersonController {
|
export class PersonController {
|
||||||
constructor(private service: PersonService) {}
|
constructor(private service: PersonService) {}
|
||||||
|
|
||||||
|
@Put(':id/reassign')
|
||||||
|
reassignFaces(
|
||||||
|
@AuthUser() authUser: AuthUserDto,
|
||||||
|
@Param() { id }: UUIDParamDto,
|
||||||
|
@Body() dto: AssetFaceUpdateDto,
|
||||||
|
): Promise<PersonResponseDto[]> {
|
||||||
|
return this.service.reassignFaces(authUser, id, dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete('')
|
||||||
|
unassignFaces(
|
||||||
|
@AuthUser() authUser: AuthUserDto,
|
||||||
|
@Body() dto: AssetFaceUpdateDto,
|
||||||
|
): Promise<BulkIdResponseDto[]> {
|
||||||
|
return this.service.unassignFaces(authUser, dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id/:assetId/faceasset')
|
||||||
|
getAssetFace(
|
||||||
|
@AuthUser() authUser: AuthUserDto,
|
||||||
|
@Param() { id }: UUIDParamDto,
|
||||||
|
@Param('assetId', new ParseMeUUIDPipe({ version: '4' })) assetId: string,
|
||||||
|
): Promise<AssetFaceBoxDto> {
|
||||||
|
return this.service.getFaceEntity(authUser, id, assetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('')
|
||||||
|
createPerson(@AuthUser() authUser: AuthUserDto, @Body() dto: AssetFaceUpdateDto): Promise<PersonResponseDto> {
|
||||||
|
return this.service.createPerson(authUser, dto);
|
||||||
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
getAllPeople(@AuthUser() authUser: AuthUserDto, @Query() withHidden: PersonSearchDto): Promise<PeopleResponseDto> {
|
getAllPeople(@AuthUser() authUser: AuthUserDto, @Query() withHidden: PersonSearchDto): Promise<PeopleResponseDto> {
|
||||||
return this.service.getAll(authUser, withHidden);
|
return this.service.getAll(authUser, withHidden);
|
||||||
|
|
|
@ -47,6 +47,29 @@ export class PersonRepository implements IPersonRepository {
|
||||||
return result.affected ?? 0;
|
return result.affected ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async reassignFace(oldPersonId: string, newPersonId: string, assetId: string): Promise<number> {
|
||||||
|
const result = await this.assetFaceRepository
|
||||||
|
.createQueryBuilder()
|
||||||
|
.update()
|
||||||
|
.set({ personId: newPersonId })
|
||||||
|
.where({ personId: oldPersonId })
|
||||||
|
.andWhere({ assetId })
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return result.affected ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async unassignFace(id: string): Promise<number> {
|
||||||
|
const result = await this.assetFaceRepository
|
||||||
|
.createQueryBuilder()
|
||||||
|
.update()
|
||||||
|
.set({ personId: null })
|
||||||
|
.where({ id })
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return result.affected ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
delete(entity: PersonEntity): Promise<PersonEntity | null> {
|
delete(entity: PersonEntity): Promise<PersonEntity | null> {
|
||||||
return this.personRepository.remove(entity);
|
return this.personRepository.remove(entity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ export const newPersonRepositoryMock = (): jest.Mocked<IPersonRepository> => {
|
||||||
getAssets: jest.fn(),
|
getAssets: jest.fn(),
|
||||||
getAllWithoutFaces: jest.fn(),
|
getAllWithoutFaces: jest.fn(),
|
||||||
|
|
||||||
|
reassignFace: jest.fn(),
|
||||||
getByName: jest.fn(),
|
getByName: jest.fn(),
|
||||||
|
|
||||||
create: jest.fn(),
|
create: jest.fn(),
|
||||||
|
|
503
web/src/api/open-api/api.ts
generated
503
web/src/api/open-api/api.ts
generated
|
@ -502,6 +502,81 @@ export const AssetBulkUploadCheckResultReasonEnum = {
|
||||||
|
|
||||||
export type AssetBulkUploadCheckResultReasonEnum = typeof AssetBulkUploadCheckResultReasonEnum[keyof typeof AssetBulkUploadCheckResultReasonEnum];
|
export type AssetBulkUploadCheckResultReasonEnum = typeof AssetBulkUploadCheckResultReasonEnum[keyof typeof AssetBulkUploadCheckResultReasonEnum];
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
export interface AssetFaceBoxDto {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'boundingBoxX1': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'boundingBoxX2': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'boundingBoxY1': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'boundingBoxY2': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'imageHeight': number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
* @memberof AssetFaceBoxDto
|
||||||
|
*/
|
||||||
|
'imageWidth': number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface AssetFaceUpdateDto
|
||||||
|
*/
|
||||||
|
export interface AssetFaceUpdateDto {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {Array<AssetFaceUpdateItem>}
|
||||||
|
* @memberof AssetFaceUpdateDto
|
||||||
|
*/
|
||||||
|
'data': Array<AssetFaceUpdateItem>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface AssetFaceUpdateItem
|
||||||
|
*/
|
||||||
|
export interface AssetFaceUpdateItem {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof AssetFaceUpdateItem
|
||||||
|
*/
|
||||||
|
'assetId': string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof AssetFaceUpdateItem
|
||||||
|
*/
|
||||||
|
'personId': string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
|
@ -744,10 +819,10 @@ export interface AssetResponseDto {
|
||||||
'ownerId': string;
|
'ownerId': string;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {Array<PersonResponseDto>}
|
* @type {Array<PeopleAssetResponseDto>}
|
||||||
* @memberof AssetResponseDto
|
* @memberof AssetResponseDto
|
||||||
*/
|
*/
|
||||||
'people'?: Array<PersonResponseDto>;
|
'people'?: Array<PeopleAssetResponseDto>;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
|
@ -796,6 +871,12 @@ export interface AssetResponseDto {
|
||||||
* @memberof AssetResponseDto
|
* @memberof AssetResponseDto
|
||||||
*/
|
*/
|
||||||
'type': AssetTypeEnum;
|
'type': AssetTypeEnum;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {Array<UnassignedFacesResponseDto>}
|
||||||
|
* @memberof AssetResponseDto
|
||||||
|
*/
|
||||||
|
'unassignedPeople'?: Array<UnassignedFacesResponseDto>;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -2315,6 +2396,25 @@ export const PathType = {
|
||||||
export type PathType = typeof PathType[keyof typeof PathType];
|
export type PathType = typeof PathType[keyof typeof PathType];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface PeopleAssetResponseDto
|
||||||
|
*/
|
||||||
|
export interface PeopleAssetResponseDto {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PeopleAssetResponseDto
|
||||||
|
*/
|
||||||
|
'assetFaceId': string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {PersonResponseDto}
|
||||||
|
* @memberof PeopleAssetResponseDto
|
||||||
|
*/
|
||||||
|
'person': PersonResponseDto;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
|
@ -3949,6 +4049,31 @@ export const TranscodePolicy = {
|
||||||
export type TranscodePolicy = typeof TranscodePolicy[keyof typeof TranscodePolicy];
|
export type TranscodePolicy = typeof TranscodePolicy[keyof typeof TranscodePolicy];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface UnassignedFacesResponseDto
|
||||||
|
*/
|
||||||
|
export interface UnassignedFacesResponseDto {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof UnassignedFacesResponseDto
|
||||||
|
*/
|
||||||
|
'assetFaceId': string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof UnassignedFacesResponseDto
|
||||||
|
*/
|
||||||
|
'assetId': string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {AssetFaceBoxDto}
|
||||||
|
* @memberof UnassignedFacesResponseDto
|
||||||
|
*/
|
||||||
|
'boudinxBox': AssetFaceBoxDto;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
|
@ -11766,6 +11891,50 @@ export class PartnerApi extends BaseAPI {
|
||||||
*/
|
*/
|
||||||
export const PersonApiAxiosParamCreator = function (configuration?: Configuration) {
|
export const PersonApiAxiosParamCreator = function (configuration?: Configuration) {
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
createPerson: async (assetFaceUpdateDto: AssetFaceUpdateDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'assetFaceUpdateDto' is not null or undefined
|
||||||
|
assertParamExists('createPerson', 'assetFaceUpdateDto', assetFaceUpdateDto)
|
||||||
|
const localVarPath = `/person`;
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication cookie required
|
||||||
|
|
||||||
|
// authentication api_key required
|
||||||
|
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||||
|
|
||||||
|
// authentication bearer required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
localVarRequestOptions.data = serializeDataIfNeeded(assetFaceUpdateDto, localVarRequestOptions, configuration)
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {boolean} [withHidden]
|
* @param {boolean} [withHidden]
|
||||||
|
@ -11800,6 +11969,52 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} assetId
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
getAssetFace: async (id: string, assetId: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'id' is not null or undefined
|
||||||
|
assertParamExists('getAssetFace', 'id', id)
|
||||||
|
// verify required parameter 'assetId' is not null or undefined
|
||||||
|
assertParamExists('getAssetFace', 'assetId', assetId)
|
||||||
|
const localVarPath = `/person/{id}/{assetId}/faceasset`
|
||||||
|
.replace(`{${"id"}}`, encodeURIComponent(String(id)))
|
||||||
|
.replace(`{${"assetId"}}`, encodeURIComponent(String(assetId)));
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication cookie required
|
||||||
|
|
||||||
|
// authentication api_key required
|
||||||
|
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||||
|
|
||||||
|
// authentication bearer required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
@ -12025,6 +12240,98 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
|
||||||
options: localVarRequestOptions,
|
options: localVarRequestOptions,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
reassignFaces: async (id: string, assetFaceUpdateDto: AssetFaceUpdateDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'id' is not null or undefined
|
||||||
|
assertParamExists('reassignFaces', 'id', id)
|
||||||
|
// verify required parameter 'assetFaceUpdateDto' is not null or undefined
|
||||||
|
assertParamExists('reassignFaces', 'assetFaceUpdateDto', assetFaceUpdateDto)
|
||||||
|
const localVarPath = `/person/{id}/reassign`
|
||||||
|
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication cookie required
|
||||||
|
|
||||||
|
// authentication api_key required
|
||||||
|
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||||
|
|
||||||
|
// authentication bearer required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
localVarRequestOptions.data = serializeDataIfNeeded(assetFaceUpdateDto, localVarRequestOptions, configuration)
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
unassignFaces: async (assetFaceUpdateDto: AssetFaceUpdateDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
// verify required parameter 'assetFaceUpdateDto' is not null or undefined
|
||||||
|
assertParamExists('unassignFaces', 'assetFaceUpdateDto', assetFaceUpdateDto)
|
||||||
|
const localVarPath = `/person`;
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication cookie required
|
||||||
|
|
||||||
|
// authentication api_key required
|
||||||
|
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
|
||||||
|
|
||||||
|
// authentication bearer required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
localVarRequestOptions.data = serializeDataIfNeeded(assetFaceUpdateDto, localVarRequestOptions, configuration)
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PeopleUpdateDto} peopleUpdateDto
|
* @param {PeopleUpdateDto} peopleUpdateDto
|
||||||
|
@ -12127,6 +12434,16 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
|
||||||
export const PersonApiFp = function(configuration?: Configuration) {
|
export const PersonApiFp = function(configuration?: Configuration) {
|
||||||
const localVarAxiosParamCreator = PersonApiAxiosParamCreator(configuration)
|
const localVarAxiosParamCreator = PersonApiAxiosParamCreator(configuration)
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async createPerson(assetFaceUpdateDto: AssetFaceUpdateDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<PersonResponseDto>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.createPerson(assetFaceUpdateDto, options);
|
||||||
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {boolean} [withHidden]
|
* @param {boolean} [withHidden]
|
||||||
|
@ -12137,6 +12454,17 @@ export const PersonApiFp = function(configuration?: Configuration) {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getAllPeople(withHidden, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.getAllPeople(withHidden, options);
|
||||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} assetId
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async getAssetFace(id: string, assetId: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AssetFaceBoxDto>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.getAssetFace(id, assetId, options);
|
||||||
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
|
@ -12188,6 +12516,27 @@ export const PersonApiFp = function(configuration?: Configuration) {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
|
||||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async reassignFaces(id: string, assetFaceUpdateDto: AssetFaceUpdateDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<PersonResponseDto>>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.reassignFaces(id, assetFaceUpdateDto, options);
|
||||||
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {AssetFaceUpdateDto} assetFaceUpdateDto
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async unassignFaces(assetFaceUpdateDto: AssetFaceUpdateDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<BulkIdResponseDto>>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.unassignFaces(assetFaceUpdateDto, options);
|
||||||
|
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PeopleUpdateDto} peopleUpdateDto
|
* @param {PeopleUpdateDto} peopleUpdateDto
|
||||||
|
@ -12219,6 +12568,15 @@ export const PersonApiFp = function(configuration?: Configuration) {
|
||||||
export const PersonApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
|
export const PersonApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
|
||||||
const localVarFp = PersonApiFp(configuration)
|
const localVarFp = PersonApiFp(configuration)
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiCreatePersonRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
createPerson(requestParameters: PersonApiCreatePersonRequest, options?: AxiosRequestConfig): AxiosPromise<PersonResponseDto> {
|
||||||
|
return localVarFp.createPerson(requestParameters.assetFaceUpdateDto, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiGetAllPeopleRequest} requestParameters Request parameters.
|
* @param {PersonApiGetAllPeopleRequest} requestParameters Request parameters.
|
||||||
|
@ -12228,6 +12586,15 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
|
||||||
getAllPeople(requestParameters: PersonApiGetAllPeopleRequest = {}, options?: AxiosRequestConfig): AxiosPromise<PeopleResponseDto> {
|
getAllPeople(requestParameters: PersonApiGetAllPeopleRequest = {}, options?: AxiosRequestConfig): AxiosPromise<PeopleResponseDto> {
|
||||||
return localVarFp.getAllPeople(requestParameters.withHidden, options).then((request) => request(axios, basePath));
|
return localVarFp.getAllPeople(requestParameters.withHidden, options).then((request) => request(axios, basePath));
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiGetAssetFaceRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
getAssetFace(requestParameters: PersonApiGetAssetFaceRequest, options?: AxiosRequestConfig): AxiosPromise<AssetFaceBoxDto> {
|
||||||
|
return localVarFp.getAssetFace(requestParameters.id, requestParameters.assetId, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiGetPersonRequest} requestParameters Request parameters.
|
* @param {PersonApiGetPersonRequest} requestParameters Request parameters.
|
||||||
|
@ -12273,6 +12640,24 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
|
||||||
mergePerson(requestParameters: PersonApiMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
|
mergePerson(requestParameters: PersonApiMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
|
||||||
return localVarFp.mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(axios, basePath));
|
return localVarFp.mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(axios, basePath));
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiReassignFacesRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
reassignFaces(requestParameters: PersonApiReassignFacesRequest, options?: AxiosRequestConfig): AxiosPromise<Array<PersonResponseDto>> {
|
||||||
|
return localVarFp.reassignFaces(requestParameters.id, requestParameters.assetFaceUpdateDto, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiUnassignFacesRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
unassignFaces(requestParameters: PersonApiUnassignFacesRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
|
||||||
|
return localVarFp.unassignFaces(requestParameters.assetFaceUpdateDto, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
||||||
|
@ -12294,6 +12679,20 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters for createPerson operation in PersonApi.
|
||||||
|
* @export
|
||||||
|
* @interface PersonApiCreatePersonRequest
|
||||||
|
*/
|
||||||
|
export interface PersonApiCreatePersonRequest {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {AssetFaceUpdateDto}
|
||||||
|
* @memberof PersonApiCreatePerson
|
||||||
|
*/
|
||||||
|
readonly assetFaceUpdateDto: AssetFaceUpdateDto
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request parameters for getAllPeople operation in PersonApi.
|
* Request parameters for getAllPeople operation in PersonApi.
|
||||||
* @export
|
* @export
|
||||||
|
@ -12308,6 +12707,27 @@ export interface PersonApiGetAllPeopleRequest {
|
||||||
readonly withHidden?: boolean
|
readonly withHidden?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters for getAssetFace operation in PersonApi.
|
||||||
|
* @export
|
||||||
|
* @interface PersonApiGetAssetFaceRequest
|
||||||
|
*/
|
||||||
|
export interface PersonApiGetAssetFaceRequest {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PersonApiGetAssetFace
|
||||||
|
*/
|
||||||
|
readonly id: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PersonApiGetAssetFace
|
||||||
|
*/
|
||||||
|
readonly assetId: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request parameters for getPerson operation in PersonApi.
|
* Request parameters for getPerson operation in PersonApi.
|
||||||
* @export
|
* @export
|
||||||
|
@ -12385,6 +12805,41 @@ export interface PersonApiMergePersonRequest {
|
||||||
readonly mergePersonDto: MergePersonDto
|
readonly mergePersonDto: MergePersonDto
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters for reassignFaces operation in PersonApi.
|
||||||
|
* @export
|
||||||
|
* @interface PersonApiReassignFacesRequest
|
||||||
|
*/
|
||||||
|
export interface PersonApiReassignFacesRequest {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof PersonApiReassignFaces
|
||||||
|
*/
|
||||||
|
readonly id: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {AssetFaceUpdateDto}
|
||||||
|
* @memberof PersonApiReassignFaces
|
||||||
|
*/
|
||||||
|
readonly assetFaceUpdateDto: AssetFaceUpdateDto
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters for unassignFaces operation in PersonApi.
|
||||||
|
* @export
|
||||||
|
* @interface PersonApiUnassignFacesRequest
|
||||||
|
*/
|
||||||
|
export interface PersonApiUnassignFacesRequest {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {AssetFaceUpdateDto}
|
||||||
|
* @memberof PersonApiUnassignFaces
|
||||||
|
*/
|
||||||
|
readonly assetFaceUpdateDto: AssetFaceUpdateDto
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request parameters for updatePeople operation in PersonApi.
|
* Request parameters for updatePeople operation in PersonApi.
|
||||||
* @export
|
* @export
|
||||||
|
@ -12427,6 +12882,17 @@ export interface PersonApiUpdatePersonRequest {
|
||||||
* @extends {BaseAPI}
|
* @extends {BaseAPI}
|
||||||
*/
|
*/
|
||||||
export class PersonApi extends BaseAPI {
|
export class PersonApi extends BaseAPI {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiCreatePersonRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof PersonApi
|
||||||
|
*/
|
||||||
|
public createPerson(requestParameters: PersonApiCreatePersonRequest, options?: AxiosRequestConfig) {
|
||||||
|
return PersonApiFp(this.configuration).createPerson(requestParameters.assetFaceUpdateDto, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiGetAllPeopleRequest} requestParameters Request parameters.
|
* @param {PersonApiGetAllPeopleRequest} requestParameters Request parameters.
|
||||||
|
@ -12438,6 +12904,17 @@ export class PersonApi extends BaseAPI {
|
||||||
return PersonApiFp(this.configuration).getAllPeople(requestParameters.withHidden, options).then((request) => request(this.axios, this.basePath));
|
return PersonApiFp(this.configuration).getAllPeople(requestParameters.withHidden, options).then((request) => request(this.axios, this.basePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiGetAssetFaceRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof PersonApi
|
||||||
|
*/
|
||||||
|
public getAssetFace(requestParameters: PersonApiGetAssetFaceRequest, options?: AxiosRequestConfig) {
|
||||||
|
return PersonApiFp(this.configuration).getAssetFace(requestParameters.id, requestParameters.assetId, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiGetPersonRequest} requestParameters Request parameters.
|
* @param {PersonApiGetPersonRequest} requestParameters Request parameters.
|
||||||
|
@ -12493,6 +12970,28 @@ export class PersonApi extends BaseAPI {
|
||||||
return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
|
return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiReassignFacesRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof PersonApi
|
||||||
|
*/
|
||||||
|
public reassignFaces(requestParameters: PersonApiReassignFacesRequest, options?: AxiosRequestConfig) {
|
||||||
|
return PersonApiFp(this.configuration).reassignFaces(requestParameters.id, requestParameters.assetFaceUpdateDto, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {PersonApiUnassignFacesRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof PersonApi
|
||||||
|
*/
|
||||||
|
public unassignFaces(requestParameters: PersonApiUnassignFacesRequest, options?: AxiosRequestConfig) {
|
||||||
|
return PersonApiFp(this.configuration).unassignFaces(requestParameters.assetFaceUpdateDto, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
||||||
|
|
|
@ -145,6 +145,9 @@
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{#if isOwner}
|
{#if isOwner}
|
||||||
|
{#if !asset.isReadOnly && !asset.isExternal}
|
||||||
|
<CircleIconButton isOpacity={true} icon={mdiDeleteOutline} on:click={() => dispatch('delete')} title="Delete" />
|
||||||
|
{/if}
|
||||||
<CircleIconButton
|
<CircleIconButton
|
||||||
isOpacity={true}
|
isOpacity={true}
|
||||||
icon={asset.isFavorite ? mdiHeart : mdiHeartOutline}
|
icon={asset.isFavorite ? mdiHeart : mdiHeartOutline}
|
||||||
|
|
|
@ -355,7 +355,7 @@
|
||||||
|
|
||||||
<section
|
<section
|
||||||
id="immich-asset-viewer"
|
id="immich-asset-viewer"
|
||||||
class="fixed left-0 top-0 z-[1001] grid h-screen w-screen grid-cols-4 grid-rows-[64px_1fr] overflow-y-hidden bg-black"
|
class="fixed left-0 top-0 z-[1001] grid h-screen w-screen grid-cols-4 grid-rows-[64px_1fr] overflow-x-hidden overflow-y-hidden bg-black"
|
||||||
bind:this={assetViewerHtmlElement}
|
bind:this={assetViewerHtmlElement}
|
||||||
>
|
>
|
||||||
<div class="z-[1000] col-span-4 col-start-1 row-span-1 row-start-1 transition-transform">
|
<div class="z-[1000] col-span-4 col-start-1 row-span-1 row-start-1 transition-transform">
|
||||||
|
|
|
@ -3,18 +3,44 @@
|
||||||
import { locale } from '$lib/stores/preferences.store';
|
import { locale } from '$lib/stores/preferences.store';
|
||||||
import { featureFlags, serverConfig } from '$lib/stores/server-config.store';
|
import { featureFlags, serverConfig } from '$lib/stores/server-config.store';
|
||||||
import { getAssetFilename } from '$lib/utils/asset-utils';
|
import { getAssetFilename } from '$lib/utils/asset-utils';
|
||||||
import { AlbumResponseDto, AssetResponseDto, ThumbnailFormat, api } from '@api';
|
import {
|
||||||
|
AlbumResponseDto,
|
||||||
|
AssetResponseDto,
|
||||||
|
PersonResponseDto,
|
||||||
|
ThumbnailFormat,
|
||||||
|
UnassignedFacesResponseDto,
|
||||||
|
api,
|
||||||
|
} from '@api';
|
||||||
import type { LatLngTuple } from 'leaflet';
|
import type { LatLngTuple } from 'leaflet';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
import { asByteUnitString } from '../../utils/byte-units';
|
import { asByteUnitString } from '../../utils/byte-units';
|
||||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||||
import UserAvatar from '../shared-components/user-avatar.svelte';
|
import UserAvatar from '../shared-components/user-avatar.svelte';
|
||||||
import { mdiCalendar, mdiCameraIris, mdiClose, mdiImageOutline, mdiMapMarkerOutline } from '@mdi/js';
|
import PersonSidePanel, { PersonToCreate } from '../faces-page/person-side-panel.svelte';
|
||||||
|
import { mdiCalendar, mdiCameraIris, mdiClose, mdiImageOutline, mdiMapMarkerOutline, mdiPencil } from '@mdi/js';
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
|
|
||||||
export let asset: AssetResponseDto;
|
export let asset: AssetResponseDto;
|
||||||
export let albums: AlbumResponseDto[] = [];
|
export let albums: AlbumResponseDto[] = [];
|
||||||
|
let unassignedFaces: UnassignedFacesResponseDto[] = [];
|
||||||
|
let people: PersonResponseDto[] = [];
|
||||||
|
|
||||||
|
let customFeaturePhoto = new Array<PersonToCreate | null>(asset.people?.length || 0);
|
||||||
|
|
||||||
|
let previousId: string;
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (!previousId) {
|
||||||
|
previousId = asset.id;
|
||||||
|
}
|
||||||
|
if (asset.id !== previousId) {
|
||||||
|
customFeaturePhoto = new Array<PersonToCreate | null>(asset.people?.length || 0);
|
||||||
|
showEditFaces = false;
|
||||||
|
previousId = asset.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let showEditFaces = false;
|
||||||
|
|
||||||
let textarea: HTMLTextAreaElement;
|
let textarea: HTMLTextAreaElement;
|
||||||
let description: string;
|
let description: string;
|
||||||
|
@ -23,9 +49,15 @@
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
// Get latest description from server
|
// Get latest description from server
|
||||||
if (asset.id && !api.isSharedLink) {
|
if (asset.id && !api.isSharedLink && !showEditFaces) {
|
||||||
api.assetApi.getAssetById({ id: asset.id }).then((res) => {
|
api.assetApi.getAssetById({ id: asset.id }).then((res) => {
|
||||||
people = res.data?.people || [];
|
if (res.data && res.data.people) {
|
||||||
|
unassignedFaces = res.data?.unassignedPeople || [];
|
||||||
|
people = (res.data?.people || [])
|
||||||
|
.map((peopleAsset) => peopleAsset.person)
|
||||||
|
.filter((person): person is PersonResponseDto => person !== null);
|
||||||
|
}
|
||||||
|
|
||||||
textarea.value = res.data?.exifInfo?.description || '';
|
textarea.value = res.data?.exifInfo?.description || '';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -43,8 +75,6 @@
|
||||||
$: lat = latlng ? latlng[0] : undefined;
|
$: lat = latlng ? latlng[0] : undefined;
|
||||||
$: lng = latlng ? latlng[1] : undefined;
|
$: lng = latlng ? latlng[1] : undefined;
|
||||||
|
|
||||||
$: people = asset.people || [];
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
const getMegapixel = (width: number, height: number): number | undefined => {
|
const getMegapixel = (width: number, height: number): number | undefined => {
|
||||||
|
@ -82,285 +112,307 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="p-2 dark:bg-immich-dark-bg dark:text-immich-dark-fg">
|
<div class="relative overflow-x-hidden">
|
||||||
<div class="flex place-items-center gap-2">
|
<section class="p-2 dark:bg-immich-dark-bg dark:text-immich-dark-fg">
|
||||||
<button
|
<div class="flex place-items-center gap-2">
|
||||||
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
<button
|
||||||
on:click={() => dispatch('close')}
|
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
>
|
on:click={() => dispatch('close')}
|
||||||
<Icon path={mdiClose} size="24" />
|
>
|
||||||
</button>
|
<Icon path={mdiClose} size="24" />
|
||||||
|
</button>
|
||||||
|
|
||||||
<p class="text-lg text-immich-fg dark:text-immich-dark-fg">Info</p>
|
<p class="text-lg text-immich-fg dark:text-immich-dark-fg">Info</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if asset.isOffline}
|
{#if asset.isOffline}
|
||||||
<section class="px-4 py-4">
|
<section class="px-4 py-4">
|
||||||
<div role="alert">
|
<div role="alert">
|
||||||
<div class="rounded-t bg-red-500 px-4 py-2 font-bold text-white">Asset offline</div>
|
<div class="rounded-t bg-red-500 px-4 py-2 font-bold text-white">Asset offline</div>
|
||||||
<div class="rounded-b border border-t-0 border-red-400 bg-red-100 px-4 py-3 text-red-700">
|
<div class="rounded-b border border-t-0 border-red-400 bg-red-100 px-4 py-3 text-red-700">
|
||||||
<p>
|
<p>
|
||||||
This asset is offline. Immich can not access its file location. Please ensure the asset is available and
|
This asset is offline. Immich can not access its file location. Please ensure the asset is available and
|
||||||
then rescan the library.
|
then rescan the library.
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<section class="mx-4 mt-10" style:display={!isOwner && textarea?.value == '' ? 'none' : 'block'}>
|
|
||||||
<textarea
|
|
||||||
bind:this={textarea}
|
|
||||||
class="max-h-[500px]
|
|
||||||
w-full resize-none overflow-hidden border-b border-gray-500 bg-transparent text-base text-black outline-none transition-all focus:border-b-2 focus:border-immich-primary disabled:border-none dark:text-white dark:focus:border-immich-dark-primary"
|
|
||||||
placeholder={!isOwner ? '' : 'Add a description'}
|
|
||||||
on:focusin={handleFocusIn}
|
|
||||||
on:focusout={handleFocusOut}
|
|
||||||
on:input={autoGrowHeight}
|
|
||||||
bind:value={description}
|
|
||||||
disabled={!isOwner}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{#if !api.isSharedLink && people.length > 0}
|
|
||||||
<section class="px-4 py-4 text-sm">
|
|
||||||
<h2>PEOPLE</h2>
|
|
||||||
|
|
||||||
<div class="mt-4 flex flex-wrap gap-2">
|
|
||||||
{#each people as person (person.id)}
|
|
||||||
<a href="/people/{person.id}" class="w-[90px]" on:click={() => dispatch('close-viewer')}>
|
|
||||||
<ImageThumbnail
|
|
||||||
curve
|
|
||||||
shadow
|
|
||||||
url={api.getPeopleThumbnailUrl(person.id)}
|
|
||||||
altText={person.name}
|
|
||||||
title={person.name}
|
|
||||||
widthStyle="90px"
|
|
||||||
heightStyle="90px"
|
|
||||||
thumbhash={null}
|
|
||||||
/>
|
|
||||||
<p class="mt-1 truncate font-medium" title={person.name}>{person.name}</p>
|
|
||||||
{#if person.birthDate}
|
|
||||||
{@const personBirthDate = DateTime.fromISO(person.birthDate)}
|
|
||||||
<p
|
|
||||||
class="font-light"
|
|
||||||
title={personBirthDate.toLocaleString(
|
|
||||||
{
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric',
|
|
||||||
year: 'numeric',
|
|
||||||
},
|
|
||||||
{ locale: $locale },
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
Age {Math.floor(DateTime.fromISO(asset.fileCreatedAt).diff(personBirthDate, 'years').years)}
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
</a>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="px-4 py-4">
|
|
||||||
{#if !asset.exifInfo && !asset.isExternal}
|
|
||||||
<p class="text-sm">NO EXIF INFO AVAILABLE</p>
|
|
||||||
{:else if !asset.exifInfo && asset.isExternal}
|
|
||||||
<div class="flex gap-4 py-4">
|
|
||||||
<div>
|
|
||||||
<p class="break-all">
|
|
||||||
Metadata not loaded for {asset.originalPath}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<p class="text-sm">DETAILS</p>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if asset.exifInfo?.dateTimeOriginal}
|
<section class="mx-4 mt-10" style:display={!isOwner && textarea?.value == '' ? 'none' : 'block'}>
|
||||||
{@const assetDateTimeOriginal = DateTime.fromISO(asset.exifInfo.dateTimeOriginal, {
|
<textarea
|
||||||
zone: asset.exifInfo.timeZone ?? undefined,
|
bind:this={textarea}
|
||||||
})}
|
class="max-h-[500px]
|
||||||
<div class="flex gap-4 py-4">
|
w-full resize-none overflow-hidden border-b border-gray-500 bg-transparent text-base text-black outline-none transition-all focus:border-b-2 focus:border-immich-primary disabled:border-none dark:text-white dark:focus:border-immich-dark-primary"
|
||||||
<div>
|
placeholder={!isOwner ? '' : 'Add a description'}
|
||||||
<Icon path={mdiCalendar} size="24" />
|
on:focusin={handleFocusIn}
|
||||||
</div>
|
on:focusout={handleFocusOut}
|
||||||
|
on:input={autoGrowHeight}
|
||||||
|
bind:value={description}
|
||||||
|
disabled={!isOwner}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
<div>
|
{#if !api.isSharedLink && people.length > 0}
|
||||||
<p>
|
<section class="px-4 py-4 text-sm">
|
||||||
{assetDateTimeOriginal.toLocaleString(
|
<div class="grid grid-cols-2 items-center">
|
||||||
{
|
<h2 class="justify-self-start uppercase">People</h2>
|
||||||
month: 'short',
|
<button class="justify-self-end" on:click={() => (showEditFaces = true)}>
|
||||||
day: 'numeric',
|
<Icon path={mdiPencil} size={18} />
|
||||||
year: 'numeric',
|
</button>
|
||||||
},
|
{#if unassignedFaces.length > 0}
|
||||||
{ locale: $locale },
|
<p>{`${unassignedFaces.length} face${unassignedFaces.length > 1 ? 's' : ''} available to add`}</p>
|
||||||
)}
|
{/if}
|
||||||
</p>
|
</div>
|
||||||
<div class="flex gap-2 text-sm">
|
{#if people.length > 0}
|
||||||
|
<div class="mt-4 flex flex-wrap gap-2">
|
||||||
|
{#each people as person, index (person.id)}
|
||||||
|
<a href="/people/{person.id}" class="w-[90px]" on:click={() => dispatch('close-viewer')}>
|
||||||
|
<ImageThumbnail
|
||||||
|
curve
|
||||||
|
shadow
|
||||||
|
url={customFeaturePhoto[index]?.thumbnail || api.getPeopleThumbnailUrl(person.id)}
|
||||||
|
altText={person.name}
|
||||||
|
title={person.name}
|
||||||
|
widthStyle="90px"
|
||||||
|
heightStyle="90px"
|
||||||
|
thumbhash={null}
|
||||||
|
/>
|
||||||
|
<p class="mt-1 truncate font-medium" title={person.name}>{person.name}</p>
|
||||||
|
{#if person.birthDate}
|
||||||
|
{@const personBirthDate = DateTime.fromISO(person.birthDate)}
|
||||||
|
<p
|
||||||
|
class="font-light"
|
||||||
|
title={personBirthDate.toLocaleString(
|
||||||
|
{
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
year: 'numeric',
|
||||||
|
},
|
||||||
|
{ locale: $locale },
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
Age {Math.floor(DateTime.fromISO(asset.fileCreatedAt).diff(personBirthDate, 'years').years)}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="px-4 py-4">
|
||||||
|
{#if !asset.exifInfo && !asset.isExternal}
|
||||||
|
<p class="text-sm">NO EXIF INFO AVAILABLE</p>
|
||||||
|
{:else if !asset.exifInfo && asset.isExternal}
|
||||||
|
<div class="flex gap-4 py-4">
|
||||||
|
<div>
|
||||||
|
<p class="break-all">
|
||||||
|
Metadata not loaded for {asset.originalPath}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<p class="text-sm">DETAILS</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if asset.exifInfo?.dateTimeOriginal}
|
||||||
|
{@const assetDateTimeOriginal = DateTime.fromISO(asset.exifInfo.dateTimeOriginal, {
|
||||||
|
zone: asset.exifInfo.timeZone ?? undefined,
|
||||||
|
})}
|
||||||
|
<div class="flex gap-4 py-4">
|
||||||
|
<div>
|
||||||
|
<Icon path={mdiCalendar} size="24" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
<p>
|
<p>
|
||||||
{assetDateTimeOriginal.toLocaleString(
|
{assetDateTimeOriginal.toLocaleString(
|
||||||
{
|
{
|
||||||
weekday: 'short',
|
month: 'short',
|
||||||
hour: 'numeric',
|
day: 'numeric',
|
||||||
minute: '2-digit',
|
year: 'numeric',
|
||||||
timeZoneName: 'longOffset',
|
|
||||||
},
|
},
|
||||||
{ locale: $locale },
|
{ locale: $locale },
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
<div class="flex gap-2 text-sm">
|
||||||
|
<p>
|
||||||
|
{assetDateTimeOriginal.toLocaleString(
|
||||||
|
{
|
||||||
|
weekday: 'short',
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: '2-digit',
|
||||||
|
timeZoneName: 'longOffset',
|
||||||
|
},
|
||||||
|
{ locale: $locale },
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>{/if}
|
||||||
|
|
||||||
|
{#if asset.exifInfo?.fileSizeInByte}
|
||||||
|
<div class="flex gap-4 py-4">
|
||||||
|
<div><Icon path={mdiImageOutline} size="24" /></div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p class="break-all">
|
||||||
|
{getAssetFilename(asset)}
|
||||||
|
</p>
|
||||||
|
<div class="flex gap-2 text-sm">
|
||||||
|
{#if asset.exifInfo.exifImageHeight && asset.exifInfo.exifImageWidth}
|
||||||
|
{#if getMegapixel(asset.exifInfo.exifImageHeight, asset.exifInfo.exifImageWidth)}
|
||||||
|
<p>
|
||||||
|
{getMegapixel(asset.exifInfo.exifImageHeight, asset.exifInfo.exifImageWidth)} MP
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<p>{asset.exifInfo.exifImageHeight} x {asset.exifInfo.exifImageWidth}</p>
|
||||||
|
{/if}
|
||||||
|
<p>{asByteUnitString(asset.exifInfo.fileSizeInByte, $locale)}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>{/if}
|
{/if}
|
||||||
|
|
||||||
{#if asset.exifInfo?.fileSizeInByte}
|
{#if asset.exifInfo?.make || asset.exifInfo?.model || asset.exifInfo?.fNumber}
|
||||||
<div class="flex gap-4 py-4">
|
<div class="flex gap-4 py-4">
|
||||||
<div><Icon path={mdiImageOutline} size="24" /></div>
|
<div><Icon path={mdiCameraIris} size="24" /></div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p class="break-all">
|
<p>{asset.exifInfo.make || ''} {asset.exifInfo.model || ''}</p>
|
||||||
{getAssetFilename(asset)}
|
<div class="flex gap-2 text-sm">
|
||||||
</p>
|
{#if asset.exifInfo?.fNumber}
|
||||||
<div class="flex gap-2 text-sm">
|
<p>{`ƒ/${asset.exifInfo.fNumber.toLocaleString($locale)}` || ''}</p>
|
||||||
{#if asset.exifInfo.exifImageHeight && asset.exifInfo.exifImageWidth}
|
{/if}
|
||||||
{#if getMegapixel(asset.exifInfo.exifImageHeight, asset.exifInfo.exifImageWidth)}
|
|
||||||
|
{#if asset.exifInfo.exposureTime}
|
||||||
|
<p>{`${asset.exifInfo.exposureTime}`}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if asset.exifInfo.focalLength}
|
||||||
|
<p>{`${asset.exifInfo.focalLength.toLocaleString($locale)} mm`}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if asset.exifInfo.iso}
|
||||||
<p>
|
<p>
|
||||||
{getMegapixel(asset.exifInfo.exifImageHeight, asset.exifInfo.exifImageWidth)} MP
|
{`ISO ${asset.exifInfo.iso}`}
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
<p>{asset.exifInfo.exifImageHeight} x {asset.exifInfo.exifImageWidth}</p>
|
|
||||||
{/if}
|
|
||||||
<p>{asByteUnitString(asset.exifInfo.fileSizeInByte, $locale)}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if asset.exifInfo?.make || asset.exifInfo?.model || asset.exifInfo?.fNumber}
|
{#if asset.exifInfo?.city}
|
||||||
<div class="flex gap-4 py-4">
|
<div class="flex gap-4 py-4">
|
||||||
<div><Icon path={mdiCameraIris} size="24" /></div>
|
<div><Icon path={mdiMapMarkerOutline} size="24" /></div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<p>{asset.exifInfo.make || ''} {asset.exifInfo.model || ''}</p>
|
|
||||||
<div class="flex gap-2 text-sm">
|
|
||||||
{#if asset.exifInfo?.fNumber}
|
|
||||||
<p>{`ƒ/${asset.exifInfo.fNumber.toLocaleString($locale)}` || ''}</p>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if asset.exifInfo.exposureTime}
|
|
||||||
<p>{`${asset.exifInfo.exposureTime}`}</p>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if asset.exifInfo.focalLength}
|
|
||||||
<p>{`${asset.exifInfo.focalLength.toLocaleString($locale)} mm`}</p>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if asset.exifInfo.iso}
|
|
||||||
<p>
|
|
||||||
{`ISO ${asset.exifInfo.iso}`}
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if asset.exifInfo?.city}
|
|
||||||
<div class="flex gap-4 py-4">
|
|
||||||
<div><Icon path={mdiMapMarkerOutline} size="24" /></div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<p>{asset.exifInfo.city}</p>
|
|
||||||
{#if asset.exifInfo?.state}
|
|
||||||
<div class="flex gap-2 text-sm">
|
|
||||||
<p>{asset.exifInfo.state}</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if asset.exifInfo?.country}
|
|
||||||
<div class="flex gap-2 text-sm">
|
|
||||||
<p>{asset.exifInfo.country}</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{#if latlng && $featureFlags.loaded && $featureFlags.map}
|
|
||||||
<div class="h-[360px]">
|
|
||||||
{#await import('../shared-components/leaflet') then { Map, TileLayer, Marker }}
|
|
||||||
<Map center={latlng} zoom={14}>
|
|
||||||
<TileLayer
|
|
||||||
urlTemplate={$serverConfig.mapTileUrl}
|
|
||||||
options={{
|
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Marker {latlng}>
|
|
||||||
<p>
|
|
||||||
{lat}, {lng}
|
|
||||||
</p>
|
|
||||||
<a href="https://www.openstreetmap.org/?mlat={lat}&mlon={lng}&zoom=15#map=15/{lat}/{lng}">
|
|
||||||
Open in OpenStreetMap
|
|
||||||
</a>
|
|
||||||
</Marker>
|
|
||||||
</Map>
|
|
||||||
{/await}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if asset.owner && !isOwner}
|
|
||||||
<section class="px-6 pt-6 dark:text-immich-dark-fg">
|
|
||||||
<p class="text-sm">SHARED BY</p>
|
|
||||||
<div class="flex gap-4 pt-4">
|
|
||||||
<div>
|
|
||||||
<UserAvatar user={asset.owner} size="md" autoColor />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-auto mt-auto">
|
|
||||||
<p>
|
|
||||||
{asset.owner.firstName}
|
|
||||||
{asset.owner.lastName}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if albums.length > 0}
|
|
||||||
<section class="p-6 dark:text-immich-dark-fg">
|
|
||||||
<p class="pb-4 text-sm">APPEARS IN</p>
|
|
||||||
{#each albums as album}
|
|
||||||
<a data-sveltekit-preload-data="hover" href={`/albums/${album.id}`}>
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
||||||
<div
|
|
||||||
class="flex gap-4 py-2 hover:cursor-pointer"
|
|
||||||
on:click={() => dispatch('click', album)}
|
|
||||||
on:keydown={() => dispatch('click', album)}
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<img
|
<div>
|
||||||
alt={album.albumName}
|
<p>{asset.exifInfo.city}</p>
|
||||||
class="h-[50px] w-[50px] rounded object-cover"
|
{#if asset.exifInfo?.state}
|
||||||
src={album.albumThumbnailAssetId &&
|
<div class="flex gap-2 text-sm">
|
||||||
api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Jpeg)}
|
<p>{asset.exifInfo.state}</p>
|
||||||
draggable="false"
|
</div>
|
||||||
/>
|
{/if}
|
||||||
</div>
|
{#if asset.exifInfo?.country}
|
||||||
|
<div class="flex gap-2 text-sm">
|
||||||
<div class="mb-auto mt-auto">
|
<p>{asset.exifInfo.country}</p>
|
||||||
<p class="dark:text-immich-dark-primary">{album.albumName}</p>
|
</div>
|
||||||
<div class="flex gap-2 text-sm">
|
|
||||||
<p>{album.assetCount} items</p>
|
|
||||||
{#if album.shared}
|
|
||||||
<p>· Shared</p>
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
{/if}
|
||||||
{/each}
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{#if latlng && $featureFlags.loaded && $featureFlags.map}
|
||||||
|
<div class="h-[360px]">
|
||||||
|
{#await import('../shared-components/leaflet') then { Map, TileLayer, Marker }}
|
||||||
|
<Map center={latlng} zoom={14}>
|
||||||
|
<TileLayer
|
||||||
|
urlTemplate={$serverConfig.mapTileUrl}
|
||||||
|
options={{
|
||||||
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Marker {latlng}>
|
||||||
|
<p>
|
||||||
|
{lat}, {lng}
|
||||||
|
</p>
|
||||||
|
<a href="https://www.openstreetmap.org/?mlat={lat}&mlon={lng}&zoom=15#map=15/{lat}/{lng}">
|
||||||
|
Open in OpenStreetMap
|
||||||
|
</a>
|
||||||
|
</Marker>
|
||||||
|
</Map>
|
||||||
|
{/await}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if asset.owner && !isOwner}
|
||||||
|
<section class="px-6 pt-6 dark:text-immich-dark-fg">
|
||||||
|
<p class="text-sm">SHARED BY</p>
|
||||||
|
<div class="flex gap-4 pt-4">
|
||||||
|
<div>
|
||||||
|
<UserAvatar user={asset.owner} size="md" autoColor />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-auto mt-auto">
|
||||||
|
<p>
|
||||||
|
{asset.owner.firstName}
|
||||||
|
{asset.owner.lastName}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if albums.length > 0}
|
||||||
|
<section class="p-6 dark:text-immich-dark-fg">
|
||||||
|
<p class="pb-4 text-sm">APPEARS IN</p>
|
||||||
|
{#each albums as album}
|
||||||
|
<a data-sveltekit-preload-data="hover" href={`/albums/${album.id}`}>
|
||||||
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
|
<div
|
||||||
|
class="flex gap-4 py-2 hover:cursor-pointer"
|
||||||
|
on:click={() => dispatch('click', album)}
|
||||||
|
on:keydown={() => dispatch('click', album)}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
alt={album.albumName}
|
||||||
|
class="h-[50px] w-[50px] rounded object-cover"
|
||||||
|
src={album.albumThumbnailAssetId &&
|
||||||
|
api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Jpeg)}
|
||||||
|
draggable="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-auto mt-auto">
|
||||||
|
<p class="dark:text-immich-dark-primary">{album.albumName}</p>
|
||||||
|
<div class="flex gap-2 text-sm">
|
||||||
|
<p>{album.assetCount} items</p>
|
||||||
|
{#if album.shared}
|
||||||
|
<p>· Shared</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</section>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if showEditFaces}
|
||||||
|
<PersonSidePanel
|
||||||
|
bind:people
|
||||||
|
bind:unassignedFaces
|
||||||
|
bind:selectedPersonToCreate={customFeaturePhoto}
|
||||||
|
assetId={asset.id}
|
||||||
|
on:close={() => (showEditFaces = false)}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="flex w-full h-14 place-items-center {suggestedPeople
|
class="flex w-full h-14 place-items-center {suggestedPeople
|
||||||
? 'rounded-t-lg dark:border-immich-dark-gray'
|
? 'rounded-t-lg border-immich-primary dark:border-immich-dark-gray'
|
||||||
: 'rounded-lg'} bg-gray-100 p-2 dark:bg-gray-700"
|
: 'rounded-lg'} bg-gray-200 p-2 dark:bg-gray-700"
|
||||||
>
|
>
|
||||||
<ImageThumbnail
|
<ImageThumbnail
|
||||||
circle
|
circle
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
<!-- svelte-ignore a11y-autofocus -->
|
<!-- svelte-ignore a11y-autofocus -->
|
||||||
<input
|
<input
|
||||||
autofocus
|
autofocus
|
||||||
class="w-full gap-2 bg-gray-100 dark:bg-gray-700 dark:text-white"
|
class="w-full gap-2 bg-gray-200 dark:bg-gray-700 dark:text-white"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="New name or nickname"
|
placeholder="New name or nickname"
|
||||||
bind:value={name}
|
bind:value={name}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { goto, invalidateAll } from '$app/navigation';
|
import { goto, invalidateAll } from '$app/navigation';
|
||||||
import { AppRoute } from '$lib/constants';
|
import { AppRoute } from '$lib/constants';
|
||||||
|
|
||||||
|
import PeopleList from './people-list.svelte';
|
||||||
import { mdiCallMerge, mdiMerge, mdiSwapHorizontal } from '@mdi/js';
|
import { mdiCallMerge, mdiMerge, mdiSwapHorizontal } from '@mdi/js';
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
|
|
||||||
|
@ -69,7 +71,6 @@
|
||||||
message: `Merged ${count} ${count === 1 ? 'person' : 'people'}`,
|
message: `Merged ${count} ${count === 1 ? 'person' : 'people'}`,
|
||||||
type: NotificationType.Info,
|
type: NotificationType.Info,
|
||||||
});
|
});
|
||||||
people = people.filter((person) => !results.some((result) => result.id === person.id && result.success === true));
|
|
||||||
await invalidateAll();
|
await invalidateAll();
|
||||||
dispatch('merge');
|
dispatch('merge');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -133,16 +134,8 @@
|
||||||
<FaceThumbnail {person} border circle selectable={false} thumbnailSize={180} />
|
<FaceThumbnail {person} border circle selectable={false} thumbnailSize={180} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="immich-scrollbar overflow-y-auto rounded-3xl bg-gray-200 p-10 dark:bg-immich-dark-gray"
|
<PeopleList people={unselectedPeople} {screenHeight} on:select={({ detail }) => onSelect(detail)} />
|
||||||
style:max-height={screenHeight - 200 - 200 + 'px'}
|
|
||||||
>
|
|
||||||
<div class="grid-col-2 grid gap-8 md:grid-cols-3 lg:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-10">
|
|
||||||
{#each unselectedPeople as person (person.id)}
|
|
||||||
<FaceThumbnail {person} on:click={() => onSelect(person)} circle border selectable />
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if isShowConfirmation}
|
{#if isShowConfirmation}
|
||||||
|
|
31
web/src/lib/components/faces-page/people-list.svelte
Normal file
31
web/src/lib/components/faces-page/people-list.svelte
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { PersonResponseDto } from '@api';
|
||||||
|
import FaceThumbnail from './face-thumbnail.svelte';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
export let screenHeight: number;
|
||||||
|
export let people: PersonResponseDto[] = [];
|
||||||
|
|
||||||
|
let dispatch = createEventDispatcher<{
|
||||||
|
select: PersonResponseDto;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="immich-scrollbar overflow-y-auto rounded-3xl bg-gray-200 p-10 dark:bg-immich-dark-gray"
|
||||||
|
style:max-height={screenHeight - 400 + 'px'}
|
||||||
|
>
|
||||||
|
<div class="grid-col-2 grid gap-8 md:grid-cols-3 lg:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-10">
|
||||||
|
{#each people as person (person.id)}
|
||||||
|
<FaceThumbnail
|
||||||
|
{person}
|
||||||
|
on:click={() => {
|
||||||
|
dispatch('select', person);
|
||||||
|
}}
|
||||||
|
circle
|
||||||
|
border
|
||||||
|
selectable
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
453
web/src/lib/components/faces-page/person-side-panel.svelte
Normal file
453
web/src/lib/components/faces-page/person-side-panel.svelte
Normal file
|
@ -0,0 +1,453 @@
|
||||||
|
<script lang="ts" context="module">
|
||||||
|
export type PersonToCreate = {
|
||||||
|
thumbnail: string;
|
||||||
|
canEdit: boolean;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { blur, fly } from 'svelte/transition';
|
||||||
|
|
||||||
|
import { linear } from 'svelte/easing';
|
||||||
|
import { api, ThumbnailFormat, type PersonResponseDto, UnassignedFacesResponseDto } from '@api';
|
||||||
|
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
|
import { createEventDispatcher, onMount } from 'svelte';
|
||||||
|
import { mdiRestart, mdiAccount, mdiMinus, mdiClose, mdiPlus, mdiMagnify, mdiArrowLeftThin } from '@mdi/js';
|
||||||
|
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
||||||
|
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||||
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
|
|
||||||
|
export let people: PersonResponseDto[];
|
||||||
|
export let unassignedFaces: UnassignedFacesResponseDto[];
|
||||||
|
export let assetId: string;
|
||||||
|
|
||||||
|
let peopleToAdd: (PersonResponseDto | string)[] = [];
|
||||||
|
let searchedPeople: PersonResponseDto[] = [];
|
||||||
|
let searchWord: string;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
let searchFaces = false;
|
||||||
|
let searchName = '';
|
||||||
|
let isSearchingPeople = false;
|
||||||
|
|
||||||
|
let allPeople: PersonResponseDto[] = [];
|
||||||
|
let editedPerson: number;
|
||||||
|
let selectedPersonToReassign: (PersonResponseDto | null)[] = new Array<PersonResponseDto | null>(people.length);
|
||||||
|
export let selectedPersonToCreate: (PersonToCreate | null)[] = new Array<PersonToCreate | null>(people.length);
|
||||||
|
|
||||||
|
let showSeletecFaces = false;
|
||||||
|
let showLoadingSpinner = false;
|
||||||
|
|
||||||
|
let editedPeople = cloneDeep(people);
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
const { data } = await api.personApi.getAllPeople({ withHidden: false });
|
||||||
|
allPeople = data.people;
|
||||||
|
|
||||||
|
peopleToAdd = await initUnassignedFaces();
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchPeople = async () => {
|
||||||
|
if ((people.length < 20 && searchName.startsWith(searchWord)) || searchName === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const timeout = setTimeout(() => (isSearchingPeople = true), 100);
|
||||||
|
try {
|
||||||
|
const { data } = await api.searchApi.searchPerson({ name: searchName });
|
||||||
|
searchedPeople = data.filter((item) => item.id !== people[editedPerson].id);
|
||||||
|
searchWord = searchName;
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, "Can't search people");
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
isSearchingPeople = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
$: {
|
||||||
|
searchedPeople = !searchName
|
||||||
|
? allPeople
|
||||||
|
: allPeople
|
||||||
|
.filter((person: PersonResponseDto) => {
|
||||||
|
const nameParts = person.name.split(' ');
|
||||||
|
return nameParts.some((splitName) => splitName.toLowerCase().startsWith(searchName.toLowerCase()));
|
||||||
|
})
|
||||||
|
.slice(0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
const initInput = (element: HTMLInputElement) => {
|
||||||
|
element.focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
const initUnassignedFaces = async (): Promise<string[]> => {
|
||||||
|
const results: string[] = [];
|
||||||
|
for (let i = 0; i < unassignedFaces.length; i++) {
|
||||||
|
const data = await api.getAssetThumbnailUrl(assetId, ThumbnailFormat.Jpeg);
|
||||||
|
const newFeaturePhoto = await zoomImageToBase64(
|
||||||
|
data,
|
||||||
|
unassignedFaces[i].boudinxBox.boundingBoxX1,
|
||||||
|
unassignedFaces[i].boudinxBox.boundingBoxX2,
|
||||||
|
unassignedFaces[i].boudinxBox.boundingBoxY1,
|
||||||
|
unassignedFaces[i].boudinxBox.boundingBoxY2,
|
||||||
|
);
|
||||||
|
if (newFeaturePhoto) {
|
||||||
|
results.push(newFeaturePhoto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBackButton = () => {
|
||||||
|
searchName = '';
|
||||||
|
searchFaces = false;
|
||||||
|
selectedPersonToCreate = new Array<PersonToCreate | null>(people.length);
|
||||||
|
if (showSeletecFaces) {
|
||||||
|
showSeletecFaces = false;
|
||||||
|
} else {
|
||||||
|
dispatch('close');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function zoomImageToBase64(
|
||||||
|
imageSrc: string,
|
||||||
|
x1: number,
|
||||||
|
x2: number,
|
||||||
|
y1: number,
|
||||||
|
y2: number,
|
||||||
|
): Promise<string | null> {
|
||||||
|
// Calculate width and height from the coordinates
|
||||||
|
const width = x2 - x1;
|
||||||
|
const height = y2 - y1;
|
||||||
|
|
||||||
|
// Create an image element and load the image source
|
||||||
|
const img = new Image();
|
||||||
|
img.src = imageSrc;
|
||||||
|
|
||||||
|
// Wait for the image to load
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
img.onload = resolve;
|
||||||
|
img.onerror = () => resolve(null); // Handle image load errors
|
||||||
|
});
|
||||||
|
|
||||||
|
// Calculate the new width and height after zooming out
|
||||||
|
const newWidth = width * 1.5;
|
||||||
|
const newHeight = height * 1.5;
|
||||||
|
|
||||||
|
// Create a canvas element to draw the zoomed-out image
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = newWidth;
|
||||||
|
canvas.height = newHeight;
|
||||||
|
|
||||||
|
// Draw the zoomed-out portion of the image onto the canvas
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
if (ctx) {
|
||||||
|
ctx.drawImage(
|
||||||
|
img,
|
||||||
|
x1 - (newWidth - width) / 2,
|
||||||
|
y1 - (newHeight - height) / 2,
|
||||||
|
newWidth,
|
||||||
|
newHeight,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
newWidth,
|
||||||
|
newHeight,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Convert the canvas content to base64
|
||||||
|
const base64Image = canvas.toDataURL('image/webp');
|
||||||
|
|
||||||
|
return base64Image;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleReset = (index: number) => {
|
||||||
|
editedPeople[index] = people[index];
|
||||||
|
if (selectedPersonToReassign[index]) {
|
||||||
|
selectedPersonToReassign[index] = null;
|
||||||
|
}
|
||||||
|
if (selectedPersonToCreate[index]) {
|
||||||
|
selectedPersonToCreate[index] = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditFaces = async () => {
|
||||||
|
const numberOfChanges =
|
||||||
|
selectedPersonToCreate.filter((person) => person !== null && person.canEdit !== false).length +
|
||||||
|
selectedPersonToReassign.filter((person) => person !== null).length;
|
||||||
|
if (numberOfChanges > 0) {
|
||||||
|
showLoadingSpinner = true;
|
||||||
|
try {
|
||||||
|
for (let i = 0; i < selectedPersonToReassign.length; i++) {
|
||||||
|
const personId = selectedPersonToReassign[i]?.id;
|
||||||
|
if (personId) {
|
||||||
|
await api.personApi.reassignFaces({
|
||||||
|
id: personId,
|
||||||
|
assetFaceUpdateDto: { data: [{ assetId: assetId, personId: people[i].id }] },
|
||||||
|
});
|
||||||
|
people[i] = selectedPersonToReassign[i] as PersonResponseDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < selectedPersonToCreate.length; i++) {
|
||||||
|
const personToCreate = selectedPersonToCreate[i];
|
||||||
|
if (personToCreate && personToCreate.canEdit !== false) {
|
||||||
|
const { data } = await api.personApi.createPerson({
|
||||||
|
assetFaceUpdateDto: { data: [{ assetId: assetId, personId: people[i].id }] },
|
||||||
|
});
|
||||||
|
people[i] = data;
|
||||||
|
selectedPersonToCreate[i] = personToCreate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notificationController.show({
|
||||||
|
message: `Edited ${numberOfChanges} ${numberOfChanges > 1 ? 'people' : 'person'}`,
|
||||||
|
type: NotificationType.Info,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, "Can't apply changes");
|
||||||
|
}
|
||||||
|
showLoadingSpinner = false;
|
||||||
|
}
|
||||||
|
dispatch('close');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCreatePerson = async () => {
|
||||||
|
const { data } = await api.personApi.getAssetFace({ id: people[editedPerson].id, assetId });
|
||||||
|
const assetFace = data;
|
||||||
|
for (let i = 0; i < people.length; i++) {
|
||||||
|
if (people[i].id === people[editedPerson].id) {
|
||||||
|
const data = await api.getAssetThumbnailUrl(assetId, ThumbnailFormat.Jpeg);
|
||||||
|
const newFeaturePhoto = await zoomImageToBase64(
|
||||||
|
data,
|
||||||
|
assetFace.boundingBoxX1,
|
||||||
|
assetFace.boundingBoxX2,
|
||||||
|
assetFace.boundingBoxY1,
|
||||||
|
assetFace.boundingBoxY2,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (newFeaturePhoto) {
|
||||||
|
selectedPersonToCreate[i] = { canEdit: true, thumbnail: data };
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showSeletecFaces = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReassignFace = (person: PersonResponseDto) => {
|
||||||
|
selectedPersonToReassign[editedPerson] = person;
|
||||||
|
editedPeople[editedPerson] = person;
|
||||||
|
console.log(selectedPersonToReassign);
|
||||||
|
showSeletecFaces = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePersonPicker = async (index: number) => {
|
||||||
|
editedPerson = index;
|
||||||
|
searchedPeople = allPeople.filter((item) => item.id !== people[index].id);
|
||||||
|
showSeletecFaces = true;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section
|
||||||
|
transition:fly={{ x: 360, duration: 100, easing: linear }}
|
||||||
|
class="absolute top-0 z-[2000] h-full w-[360px] overflow-x-hidden p-2 dark:bg-immich-dark-bg dark:text-immich-dark-fg"
|
||||||
|
>
|
||||||
|
<div class="flex place-items-center justify-between gap-2">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
class="flex place-content-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
|
on:click={handleBackButton}
|
||||||
|
>
|
||||||
|
<Icon path={mdiArrowLeftThin} size="24" />
|
||||||
|
</button>
|
||||||
|
<p class="flex text-lg text-immich-fg dark:text-immich-dark-fg">Edit faces</p>
|
||||||
|
</div>
|
||||||
|
{#if !showLoadingSpinner}
|
||||||
|
<button
|
||||||
|
class="justify-self-end rounded-lg p-2 hover:bg-immich-dark-primary hover:dark:bg-immich-dark-primary/50"
|
||||||
|
on:click={() => handleEditFaces()}
|
||||||
|
>
|
||||||
|
Done
|
||||||
|
</button>
|
||||||
|
{:else}
|
||||||
|
<LoadingSpinner />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="px-4 py-4 text-sm">
|
||||||
|
<div class="mt-4 flex flex-wrap gap-2">
|
||||||
|
{#each editedPeople as person, index}
|
||||||
|
<div class="relative h-[115px] w-[95px]">
|
||||||
|
<a href="/people/{person.id}">
|
||||||
|
<div class="absolute top-0 left-1/2 transform -translate-x-1/2 h-[90px] w-[90px]">
|
||||||
|
<ImageThumbnail
|
||||||
|
curve
|
||||||
|
shadow
|
||||||
|
url={selectedPersonToCreate[index]?.thumbnail || api.getPeopleThumbnailUrl(person.id)}
|
||||||
|
altText={person.name}
|
||||||
|
title={person.name}
|
||||||
|
widthStyle="90px"
|
||||||
|
heightStyle="90px"
|
||||||
|
thumbhash={null}
|
||||||
|
/>
|
||||||
|
<p class="relative mt-1 truncate font-medium" title={person.name}>
|
||||||
|
{person.name}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div
|
||||||
|
transition:blur={{ amount: 10, duration: 50 }}
|
||||||
|
class="absolute -left-[5px] -top-[5px] h-[20px] w-[20px] rounded-full bg-red-700"
|
||||||
|
>
|
||||||
|
<button on:click={() => handleReset(index)} class="flex h-full w-full">
|
||||||
|
<div class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform">
|
||||||
|
<Icon path={mdiMinus} size={18} />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
transition:blur={{ amount: 10, duration: 50 }}
|
||||||
|
class="absolute -right-[5px] -top-[5px] h-[20px] w-[20px] rounded-full bg-blue-700"
|
||||||
|
>
|
||||||
|
{#if (selectedPersonToCreate[index] && selectedPersonToCreate[index]?.canEdit !== false) || selectedPersonToReassign[index]}
|
||||||
|
<button on:click={() => handleReset(index)} class="flex h-full w-full">
|
||||||
|
<div class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform">
|
||||||
|
<Icon path={mdiRestart} size={18} />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{:else}
|
||||||
|
<button on:click={() => handlePersonPicker(index)} class="flex h-full w-full">
|
||||||
|
<div class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform">
|
||||||
|
<Icon path={mdiAccount} size={18} />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{#each peopleToAdd as face, index}
|
||||||
|
<div class="relative h-[115px] w-[95px]">
|
||||||
|
<div class="absolute top-0 left-1/2 transform -translate-x-1/2 h-[90px] w-[90px]">
|
||||||
|
<ImageThumbnail
|
||||||
|
curve
|
||||||
|
shadow
|
||||||
|
url={typeof face === 'string' ? face : api.getPeopleThumbnailUrl(face.id)}
|
||||||
|
altText="Unassigned face"
|
||||||
|
title="TO DO"
|
||||||
|
widthStyle="90px"
|
||||||
|
heightStyle="90px"
|
||||||
|
thumbhash={null}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
transition:blur={{ amount: 10, duration: 50 }}
|
||||||
|
class="absolute -right-[5px] -top-[5px] h-[20px] w-[20px] rounded-full bg-blue-700"
|
||||||
|
>
|
||||||
|
<button on:click={() => handlePersonPicker(index)} class="flex h-full w-full">
|
||||||
|
<div class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform">
|
||||||
|
<Icon path={mdiMinus} size={18} />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{#if showSeletecFaces}
|
||||||
|
<section
|
||||||
|
transition:fly={{ x: 360, duration: 100, easing: linear }}
|
||||||
|
class="absolute top-0 z-[2001] h-full overflow-x-hidden p-2 dark:bg-immich-dark-bg dark:text-immich-dark-fg"
|
||||||
|
>
|
||||||
|
<div class="flex place-items-center justify-between gap-2">
|
||||||
|
{#if !searchFaces}
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
class="flex place-content-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
|
on:click={handleBackButton}
|
||||||
|
>
|
||||||
|
<Icon path={mdiArrowLeftThin} size="24" />
|
||||||
|
</button>
|
||||||
|
<p class="flex text-lg text-immich-fg dark:text-immich-dark-fg">Select face</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
{#if isSearchingPeople}
|
||||||
|
<button
|
||||||
|
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
|
title="Search existing person"
|
||||||
|
on:click={() => {
|
||||||
|
searchFaces = true;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon path={mdiMagnify} size="24" />
|
||||||
|
</button>
|
||||||
|
{:else}
|
||||||
|
<div
|
||||||
|
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
|
>
|
||||||
|
<LoadingSpinner />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
|
on:click={() => handleCreatePerson()}
|
||||||
|
title="Create new person"
|
||||||
|
>
|
||||||
|
<Icon path={mdiPlus} size="24" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<button
|
||||||
|
class="flex place-content-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
|
on:click={handleBackButton}
|
||||||
|
>
|
||||||
|
<Icon path={mdiArrowLeftThin} size="24" />
|
||||||
|
</button>
|
||||||
|
<input
|
||||||
|
class="w-full gap-2 bg-immich-bg dark:bg-immich-dark-bg"
|
||||||
|
type="text"
|
||||||
|
placeholder="Name or nickname"
|
||||||
|
bind:value={searchName}
|
||||||
|
on:input={() => searchPeople()}
|
||||||
|
use:initInput
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
|
on:click={() => (searchFaces = false)}
|
||||||
|
>
|
||||||
|
<Icon path={mdiClose} size="24" />
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="px-4 py-4 text-sm">
|
||||||
|
<h2 class="mb-8 mt-4 uppercase">All people</h2>
|
||||||
|
<div class="immich-scrollbar mt-4 flex flex-wrap gap-2 overflow-y-auto">
|
||||||
|
{#each searchName == '' ? allPeople : searchedPeople as person (person.id)}
|
||||||
|
<div class="w-fit">
|
||||||
|
<button class="w-[90px]" on:click={() => handleReassignFace(person)}>
|
||||||
|
<ImageThumbnail
|
||||||
|
curve
|
||||||
|
shadow
|
||||||
|
url={api.getPeopleThumbnailUrl(person.id)}
|
||||||
|
altText={person.name}
|
||||||
|
title={person.name}
|
||||||
|
widthStyle="90px"
|
||||||
|
heightStyle="90px"
|
||||||
|
thumbhash={null}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<p class="mt-1 truncate font-medium" title={person.name}>{person.name}</p>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{/if}
|
200
web/src/lib/components/faces-page/unmerge-face-selector.svelte
Normal file
200
web/src/lib/components/faces-page/unmerge-face-selector.svelte
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { createEventDispatcher, onMount } from 'svelte';
|
||||||
|
import FaceThumbnail from './face-thumbnail.svelte';
|
||||||
|
import { quintOut } from 'svelte/easing';
|
||||||
|
import { fly } from 'svelte/transition';
|
||||||
|
import { api, AssetFaceUpdateItem, type PersonResponseDto } from '@api';
|
||||||
|
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||||
|
import Button from '../elements/buttons/button.svelte';
|
||||||
|
import { mdiPlus, mdiCloseThick, mdiMerge } from '@mdi/js';
|
||||||
|
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||||
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
|
import { notificationController, NotificationType } from '../shared-components/notification/notification';
|
||||||
|
import PeopleList from './people-list.svelte';
|
||||||
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
|
|
||||||
|
let people: PersonResponseDto[] = [];
|
||||||
|
export let assetIds: string[];
|
||||||
|
export let personId: string;
|
||||||
|
|
||||||
|
const data: AssetFaceUpdateItem[] = [];
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
const { data } = await api.personApi.getAllPeople({ withHidden: false });
|
||||||
|
people = data.people;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const assetId of assetIds) {
|
||||||
|
data.push({ assetId, personId });
|
||||||
|
}
|
||||||
|
|
||||||
|
let selectedPerson: PersonResponseDto | null = null;
|
||||||
|
let disableButtons = false;
|
||||||
|
let showLoadingSpinnerCreate = false;
|
||||||
|
let showLoadingSpinnerReassign = false;
|
||||||
|
let showLoadingSpinnerUnassign = false;
|
||||||
|
|
||||||
|
let hasSelection = false;
|
||||||
|
|
||||||
|
let screenHeight: number;
|
||||||
|
let dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
dispatch('close');
|
||||||
|
};
|
||||||
|
const handleSelectedPerson = (person: PersonResponseDto) => {
|
||||||
|
if (selectedPerson && selectedPerson.id === person.id) {
|
||||||
|
handleRemoveSelectedPerson();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedPerson = person;
|
||||||
|
hasSelection = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemoveSelectedPerson = () => {
|
||||||
|
selectedPerson = null;
|
||||||
|
hasSelection = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUnassign = async () => {
|
||||||
|
try {
|
||||||
|
showLoadingSpinnerCreate = true;
|
||||||
|
disableButtons = true;
|
||||||
|
await api.personApi.unassignFaces({
|
||||||
|
assetFaceUpdateDto: { data },
|
||||||
|
});
|
||||||
|
notificationController.show({
|
||||||
|
message: `Re-assigned ${assetIds.length} asset${assetIds.length > 1 ? 's' : ''} to a new person`,
|
||||||
|
type: NotificationType.Info,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, 'Unable to reassign assets to a new person');
|
||||||
|
}
|
||||||
|
dispatch('confirm');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCreate = async () => {
|
||||||
|
try {
|
||||||
|
showLoadingSpinnerCreate = true;
|
||||||
|
disableButtons = true;
|
||||||
|
await api.personApi.createPerson({
|
||||||
|
assetFaceUpdateDto: { data },
|
||||||
|
});
|
||||||
|
notificationController.show({
|
||||||
|
message: `Re-assigned ${assetIds.length} asset${assetIds.length > 1 ? 's' : ''} to a new person`,
|
||||||
|
type: NotificationType.Info,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, 'Unable to reassign assets to a new person');
|
||||||
|
}
|
||||||
|
dispatch('confirm');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReassign = async () => {
|
||||||
|
try {
|
||||||
|
showLoadingSpinnerReassign = true;
|
||||||
|
disableButtons = true;
|
||||||
|
if (selectedPerson) {
|
||||||
|
await api.personApi.reassignFaces({
|
||||||
|
id: selectedPerson.id,
|
||||||
|
assetFaceUpdateDto: { data },
|
||||||
|
});
|
||||||
|
notificationController.show({
|
||||||
|
message: `Re-assigned ${assetIds.length} asset${assetIds.length > 1 ? 's' : ''} to ${
|
||||||
|
selectedPerson.name || 'an existing person'
|
||||||
|
}`,
|
||||||
|
type: NotificationType.Info,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, `Unable to reassign assets to ${selectedPerson?.name || 'an existing person'}`);
|
||||||
|
}
|
||||||
|
dispatch('confirm');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:window bind:innerHeight={screenHeight} />
|
||||||
|
|
||||||
|
<section
|
||||||
|
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
||||||
|
class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
|
||||||
|
>
|
||||||
|
<ControlAppBar on:close-button-click={onClose}>
|
||||||
|
<svelte:fragment slot="leading">
|
||||||
|
<slot name="header" />
|
||||||
|
<div />
|
||||||
|
</svelte:fragment>
|
||||||
|
<svelte:fragment slot="trailing">
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<!-- TODO: Implement actions -->
|
||||||
|
<Button
|
||||||
|
title={'Unassign selected assets'}
|
||||||
|
size={'sm'}
|
||||||
|
disabled={disableButtons || hasSelection}
|
||||||
|
on:click={() => {
|
||||||
|
handleUnassign();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#if !showLoadingSpinnerUnassign}
|
||||||
|
<Icon path={mdiCloseThick} size={18} />
|
||||||
|
{:else}
|
||||||
|
<LoadingSpinner />
|
||||||
|
{/if}
|
||||||
|
<span class="ml-2"> Unassign assets</span></Button
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
title={'Assign selected assets to a new person'}
|
||||||
|
size={'sm'}
|
||||||
|
disabled={disableButtons || hasSelection}
|
||||||
|
on:click={() => {
|
||||||
|
handleCreate();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#if !showLoadingSpinnerCreate}
|
||||||
|
<Icon path={mdiPlus} size={18} />
|
||||||
|
{:else}
|
||||||
|
<LoadingSpinner />
|
||||||
|
{/if}
|
||||||
|
<span class="ml-2"> Create new Person</span></Button
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
size={'sm'}
|
||||||
|
title={'Assign selected assets to an existing person'}
|
||||||
|
disabled={disableButtons || !hasSelection}
|
||||||
|
on:click={() => {
|
||||||
|
handleReassign();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#if !showLoadingSpinnerReassign}
|
||||||
|
<Icon path={mdiMerge} size={18} class="rotate-180" />
|
||||||
|
{:else}
|
||||||
|
<LoadingSpinner />
|
||||||
|
{/if}
|
||||||
|
<span class="ml-2"> Reassign</span></Button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</svelte:fragment>
|
||||||
|
</ControlAppBar>
|
||||||
|
<slot name="merge" />
|
||||||
|
<section class="bg-immich-bg px-[70px] pt-[100px] dark:bg-immich-dark-bg">
|
||||||
|
<section id="merge-face-selector relative">
|
||||||
|
{#if selectedPerson !== null}
|
||||||
|
<div class="mb-10 h-[200px] place-content-center place-items-center">
|
||||||
|
<p class="mb-4 text-center uppercase dark:text-white">Choose matching faces to re assign</p>
|
||||||
|
|
||||||
|
<div class="grid grid-flow-col-dense place-content-center place-items-center gap-4">
|
||||||
|
<FaceThumbnail
|
||||||
|
person={selectedPerson}
|
||||||
|
border
|
||||||
|
circle
|
||||||
|
selectable
|
||||||
|
thumbnailSize={180}
|
||||||
|
on:click={handleRemoveSelectedPerson}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<PeopleList {people} {screenHeight} on:select={({ detail }) => handleSelectedPerson(detail)} />
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</section>
|
|
@ -22,7 +22,9 @@
|
||||||
OBJECTS = 'smartInfo.objects',
|
OBJECTS = 'smartInfo.objects',
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_ITEMS = 12;
|
let MAX_ITEMS = 12;
|
||||||
|
let innerWidth: number | null = null;
|
||||||
|
|
||||||
const getFieldItems = (items: SearchExploreResponseDto[], field: Field) => {
|
const getFieldItems = (items: SearchExploreResponseDto[], field: Field) => {
|
||||||
const targetField = items.find((item) => item.fieldName === field);
|
const targetField = items.find((item) => item.fieldName === field);
|
||||||
return targetField?.items || [];
|
return targetField?.items || [];
|
||||||
|
@ -32,6 +34,7 @@
|
||||||
$: places = getFieldItems(data.items, Field.CITY);
|
$: places = getFieldItems(data.items, Field.CITY);
|
||||||
$: people = data.response.people.slice(0, MAX_ITEMS);
|
$: people = data.response.people.slice(0, MAX_ITEMS);
|
||||||
$: hasPeople = data.response.total > 0;
|
$: hasPeople = data.response.total > 0;
|
||||||
|
$: MAX_ITEMS = innerWidth ? Math.floor(innerWidth / 112) : MAX_ITEMS;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<UserPageLayout user={data.user} title={data.meta.title}>
|
<UserPageLayout user={data.user} title={data.meta.title}>
|
||||||
|
@ -45,19 +48,21 @@
|
||||||
draggable="false">View All</a
|
draggable="false">View All</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row flex-wrap gap-4">
|
<div class="flex flex-row {MAX_ITEMS < 5 ? 'justify-center' : ''} flex-wrap gap-4" bind:offsetWidth={innerWidth}>
|
||||||
{#each people as person (person.id)}
|
{#if innerWidth}
|
||||||
<a href="/people/{person.id}" class="w-24 text-center">
|
{#each people as person (person.id)}
|
||||||
<ImageThumbnail
|
<a href="/people/{person.id}" class="w-24 text-center">
|
||||||
circle
|
<ImageThumbnail
|
||||||
shadow
|
circle
|
||||||
url={api.getPeopleThumbnailUrl(person.id)}
|
shadow
|
||||||
altText={person.name}
|
url={api.getPeopleThumbnailUrl(person.id)}
|
||||||
widthStyle="100%"
|
altText={person.name}
|
||||||
/>
|
widthStyle="100%"
|
||||||
<p class="mt-2 text-ellipsis text-sm font-medium dark:text-white">{person.name}</p>
|
/>
|
||||||
</a>
|
<p class="mt-2 text-ellipsis text-sm font-medium dark:text-white">{person.name}</p>
|
||||||
{/each}
|
</a>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
import { AssetResponseDto, PersonResponseDto, TimeBucketSize, api } from '@api';
|
import { AssetResponseDto, PersonResponseDto, TimeBucketSize, api } from '@api';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
import UnmergeFaceSelector from '$lib/components/faces-page/unmerge-face-selector.svelte';
|
||||||
import { clickOutside } from '$lib/utils/click-outside';
|
import { clickOutside } from '$lib/utils/click-outside';
|
||||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||||
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
||||||
|
@ -46,6 +47,7 @@
|
||||||
MERGE_FACES = 'merge-faces',
|
MERGE_FACES = 'merge-faces',
|
||||||
SUGGEST_MERGE = 'suggest-merge',
|
SUGGEST_MERGE = 'suggest-merge',
|
||||||
BIRTH_DATE = 'birth-date',
|
BIRTH_DATE = 'birth-date',
|
||||||
|
UNASSIGN_ASSETS = 'unassign-faces',
|
||||||
}
|
}
|
||||||
|
|
||||||
let assetStore = new AssetStore({
|
let assetStore = new AssetStore({
|
||||||
|
@ -88,7 +90,7 @@
|
||||||
if ((people.length < 20 && name.startsWith(searchWord)) || name === '') {
|
if ((people.length < 20 && name.startsWith(searchWord)) || name === '') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const timeout = setTimeout(() => (isSearchingPeople = true), 300);
|
const timeout = setTimeout(() => (isSearchingPeople = true), 100);
|
||||||
try {
|
try {
|
||||||
const { data } = await api.searchApi.searchPerson({ name });
|
const { data } = await api.searchApi.searchPerson({ name });
|
||||||
people = data;
|
people = data;
|
||||||
|
@ -158,6 +160,7 @@
|
||||||
personId: data.person.id,
|
personId: data.person.id,
|
||||||
});
|
});
|
||||||
previousPersonId = data.person.id;
|
previousPersonId = data.person.id;
|
||||||
|
name = data.person.name;
|
||||||
refreshAssetGrid = !refreshAssetGrid;
|
refreshAssetGrid = !refreshAssetGrid;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -198,6 +201,10 @@
|
||||||
viewMode = ViewMode.VIEW_ASSETS;
|
viewMode = ViewMode.VIEW_ASSETS;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleReassignAssets = () => {
|
||||||
|
viewMode = ViewMode.UNASSIGN_ASSETS;
|
||||||
|
};
|
||||||
|
|
||||||
const updateAssetCount = async () => {
|
const updateAssetCount = async () => {
|
||||||
try {
|
try {
|
||||||
const { data: statistics } = await api.personApi.getPersonStatistics({
|
const { data: statistics } = await api.personApi.getPersonStatistics({
|
||||||
|
@ -209,6 +216,12 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleUnmerge = () => {
|
||||||
|
$assetStore.removeAssets(Array.from($selectedAssets).map((a) => a.id));
|
||||||
|
assetInteractionStore.clearMultiselect();
|
||||||
|
viewMode = ViewMode.VIEW_ASSETS;
|
||||||
|
};
|
||||||
|
|
||||||
const handleMergeSameFace = async (response: [PersonResponseDto, PersonResponseDto]) => {
|
const handleMergeSameFace = async (response: [PersonResponseDto, PersonResponseDto]) => {
|
||||||
const [personToMerge, personToBeMergedIn] = response;
|
const [personToMerge, personToBeMergedIn] = response;
|
||||||
viewMode = ViewMode.VIEW_ASSETS;
|
viewMode = ViewMode.VIEW_ASSETS;
|
||||||
|
@ -267,7 +280,7 @@
|
||||||
if (viewMode === ViewMode.SUGGEST_MERGE) {
|
if (viewMode === ViewMode.SUGGEST_MERGE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
isSearchingPeople = false;
|
||||||
isEditingName = false;
|
isEditingName = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -351,6 +364,15 @@
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if viewMode === ViewMode.UNASSIGN_ASSETS}
|
||||||
|
<UnmergeFaceSelector
|
||||||
|
assetIds={Array.from($selectedAssets).map((a) => a.id)}
|
||||||
|
personId={data.person.id}
|
||||||
|
on:close={() => (viewMode = ViewMode.VIEW_ASSETS)}
|
||||||
|
on:confirm={handleUnmerge}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if viewMode === ViewMode.BIRTH_DATE}
|
{#if viewMode === ViewMode.BIRTH_DATE}
|
||||||
<SetBirthDateModal
|
<SetBirthDateModal
|
||||||
birthDate={data.person.birthDate ?? ''}
|
birthDate={data.person.birthDate ?? ''}
|
||||||
|
@ -377,6 +399,7 @@
|
||||||
<DownloadAction menuItem filename="{data.person.name || 'immich'}.zip" />
|
<DownloadAction menuItem filename="{data.person.name || 'immich'}.zip" />
|
||||||
<FavoriteAction menuItem removeFavorite={isAllFavorite} />
|
<FavoriteAction menuItem removeFavorite={isAllFavorite} />
|
||||||
<ArchiveAction menuItem unarchive={isAllArchive} onArchive={(ids) => $assetStore.removeAssets(ids)} />
|
<ArchiveAction menuItem unarchive={isAllArchive} onArchive={(ids) => $assetStore.removeAssets(ids)} />
|
||||||
|
<MenuOption text="Unmerge assets" on:click={handleReassignAssets} />
|
||||||
</AssetSelectContextMenu>
|
</AssetSelectContextMenu>
|
||||||
</AssetSelectControlBar>
|
</AssetSelectControlBar>
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -465,7 +488,7 @@
|
||||||
<div class="absolute z-[999] w-64 sm:w-96">
|
<div class="absolute z-[999] w-64 sm:w-96">
|
||||||
{#if isSearchingPeople}
|
{#if isSearchingPeople}
|
||||||
<div
|
<div
|
||||||
class="flex rounded-b-lg dark:border-immich-dark-gray place-items-center bg-gray-100 p-2 dark:bg-gray-700"
|
class="flex border h-14 rounded-b-lg border-gray-400 dark:border-immich-dark-gray place-items-center bg-gray-200 p-2 dark:bg-gray-700"
|
||||||
>
|
>
|
||||||
<div class="flex w-full place-items-center">
|
<div class="flex w-full place-items-center">
|
||||||
<LoadingSpinner />
|
<LoadingSpinner />
|
||||||
|
@ -474,8 +497,10 @@
|
||||||
{:else}
|
{:else}
|
||||||
{#each suggestedPeople as person, index (person.id)}
|
{#each suggestedPeople as person, index (person.id)}
|
||||||
<div
|
<div
|
||||||
class="flex border-t dark:border-immich-dark-gray place-items-center bg-gray-100 p-2 dark:bg-gray-700 {index ===
|
class="flex border-t border-x border-gray-400 dark:border-immich-dark-gray h-14 place-items-center bg-gray-200 p-2 dark:bg-gray-700 hover:bg-gray-300 hover:dark:bg-[#232932] {index ===
|
||||||
suggestedPeople.length - 1 && 'rounded-b-lg'}"
|
suggestedPeople.length - 1
|
||||||
|
? 'rounded-b-lg border-b'
|
||||||
|
: ''}"
|
||||||
>
|
>
|
||||||
<button class="flex w-full place-items-center" on:click={() => handleSuggestPeople(person)}>
|
<button class="flex w-full place-items-center" on:click={() => handleSuggestPeople(person)}>
|
||||||
<ImageThumbnail
|
<ImageThumbnail
|
||||||
|
|
Loading…
Reference in a new issue