Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add image url utilities #597

Merged
merged 1 commit into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { ImageType } from './generated-client/models/image-type';
import type { ClientInfo, DeviceInfo } from './models';
import type { ImageRequestParameters } from './models/api/image-request-parameters';
import { getAuthorizationHeader } from './utils';
import { getImageApi } from './utils/api/image-api';
// NOTE: This import is used for TSDoc
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type { ImageUrlsApi } from './utils/api/image-urls-api';
import { getSessionApi } from './utils/api/session-api';
import { getUserApi } from './utils/api/user-api';

Expand Down Expand Up @@ -78,6 +82,7 @@ export class Api {

/**
* Get an item image URL.
* @deprecated Use {@link ImageUrlsApi.getItemImageUrlById} instead.
* @param itemId The Item ID.
* @param imageType An optional Image Type (Primary by default).
* @param params Additional request parameters.
Expand All @@ -88,10 +93,12 @@ export class Api {
imageType: ImageType = ImageType.Primary,
params: ImageRequestParameters = {}
): string | undefined {
// TODO: We could probably use ImageApiAxiosParamCreator to make this more robust
return globalInstance.create({
baseURL: this.basePath
}).getUri({ url: `/Items/${itemId}/Images/${imageType}`, params });
return getImageApi(this)
.getItemImageUrlById(
itemId,
imageType,
params
);
}

get authorizationHeader(): string {
Expand Down
114 changes: 114 additions & 0 deletions src/utils/api/__tests__/image-urls-api.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Configuration } from '../../../generated-client/configuration';
import { ImageType } from '../../../generated-client/models/image-type';
import { ImageUrlsApi } from '../image-urls-api';

const IMAGE_API = new ImageUrlsApi(new Configuration({ basePath: 'https://example.com' }));

/**
* ImageUrlsApi class tests.
*
* @group unit
*/
describe('ImageUrlsApi', () => {
it('`getItemImageUrlById` should return an item image url', () => {
// Id only
expect(IMAGE_API.getItemImageUrlById('TEST')).toBe('https://example.com/Items/TEST/Images/Primary');
// Id, ImageType, and Params
expect(IMAGE_API.getItemImageUrlById('TEST', ImageType.Backdrop, { fillWidth: 100, fillHeight: 100 }))
.toBe('https://example.com/Items/TEST/Images/Backdrop?fillWidth=100&fillHeight=100');
});

it('`getItemImageUrl` should return an item image url', () => {
// Empty item
expect(IMAGE_API.getItemImageUrl()).toBeUndefined();
expect(IMAGE_API.getItemImageUrl({})).toBeUndefined();
// Item with Id only
expect(IMAGE_API.getItemImageUrl({ Id: 'TEST' })).toBe('https://example.com/Items/TEST/Images/Primary');
// Item with Id and Tag
expect(IMAGE_API.getItemImageUrl({ Id: 'TEST', ImageTags: { [ImageType.Primary]: 'foo' } }))
.toBe('https://example.com/Items/TEST/Images/Primary?tag=foo');
// Item with Id, ImageType, and Params
expect(IMAGE_API.getItemImageUrl(
{ Id: 'TEST' },
ImageType.Backdrop,
{ fillWidth: 100, fillHeight: 100, tag: 'foo' })
).toBe('https://example.com/Items/TEST/Images/Backdrop?fillWidth=100&fillHeight=100&tag=foo');
});

it('`getItemBackdropImageUrls` should return an array of image urls', () => {
// No Item
expect(IMAGE_API.getItemBackdropImageUrls()).toHaveLength(0);
// Item with Id only
expect(IMAGE_API.getItemBackdropImageUrls({ Id: 'TEST' })).toHaveLength(0);
// Item with Id and ParentBackdropItemId
expect(IMAGE_API.getItemBackdropImageUrls({
Id: 'TEST',
ParentBackdropItemId: 'PARENT'
})).toHaveLength(0);
// Item with Id and BackdropImageTags
let backdropUrls = IMAGE_API.getItemBackdropImageUrls({
Id: 'TEST',
BackdropImageTags: [ 'tag1', 'tag2' ]
});
expect(backdropUrls).toHaveLength(2);
expect(backdropUrls[0]).toBe('https://example.com/Items/TEST/Images/Backdrop?tag=tag1');
expect(backdropUrls[1]).toBe('https://example.com/Items/TEST/Images/Backdrop?tag=tag2');
// TODO: Item with Id, ParentBackdropItemId, and ParentBackdropImageTags
backdropUrls = IMAGE_API.getItemBackdropImageUrls({
Id: 'TEST',
ParentBackdropItemId: 'PARENT',
ParentBackdropImageTags: [ 'parent1', 'parent2', 'parent3' ]
});
expect(backdropUrls).toHaveLength(3);
expect(backdropUrls[0]).toBe('https://example.com/Items/PARENT/Images/Backdrop?tag=parent1');
expect(backdropUrls[1]).toBe('https://example.com/Items/PARENT/Images/Backdrop?tag=parent2');
expect(backdropUrls[1]).toBe('https://example.com/Items/PARENT/Images/Backdrop?tag=parent2');
});

it('`getSplashscreenImageUrl` should return an image url', () => {
// No Params
expect(IMAGE_API.getSplashscreenImageUrl()).toBe('https://example.com/Branding/Splashscreen');
// Params
expect(IMAGE_API.getSplashscreenImageUrl({ fillWidth: 100, fillHeight: 100 }))
.toBe('https://example.com/Branding/Splashscreen?fillWidth=100&fillHeight=100');
});

it('`getUserImageUrl` should return a user image url', () => {
// No User
expect(IMAGE_API.getUserImageUrl()).toBeUndefined();
// User with Id
expect(IMAGE_API.getUserImageUrl({ Id: 'TEST' })).toBe('https://example.com/Users/TEST/Images/Primary');
// User with Id and Tag
expect(IMAGE_API.getUserImageUrl({ Id: 'TEST', PrimaryImageTag: 'foo' }))
.toBe('https://example.com/Users/TEST/Images/Primary?tag=foo');
// User with Id and Tag and Params
expect(IMAGE_API.getUserImageUrl({ Id: 'TEST', PrimaryImageTag: 'foo' }, { fillWidth: 100, fillHeight: 100 }))
.toBe('https://example.com/Users/TEST/Images/Primary?fillWidth=100&fillHeight=100&tag=foo');
});

it('should return relative paths when no basePath is configured', () => {
const relativeImageApi = new ImageUrlsApi();
// getItemImageUrlById
expect(relativeImageApi.getItemImageUrlById('TEST')).toBe('/Items/TEST/Images/Primary');
// getItemImageUrl
expect(relativeImageApi.getItemImageUrl({ Id: 'TEST' })).toBe('/Items/TEST/Images/Primary');
// getItemBackdropImageUrls
const backdropUrls = relativeImageApi.getItemBackdropImageUrls({
Id: 'TEST',
BackdropImageTags: [ 'tag1', 'tag2' ]
});
expect(backdropUrls).toHaveLength(2);
expect(backdropUrls[0]).toBe('/Items/TEST/Images/Backdrop?tag=tag1');
expect(backdropUrls[1]).toBe('/Items/TEST/Images/Backdrop?tag=tag2');
// getSplashscreenImageUrl
expect(relativeImageApi.getSplashscreenImageUrl()).toBe('/Branding/Splashscreen');
// getUserImageUrl
expect(relativeImageApi.getUserImageUrl({ Id: 'TEST' })).toBe('/Users/TEST/Images/Primary');
});
});
7 changes: 4 additions & 3 deletions src/utils/api/image-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
*/

import type { Api } from '../../api';
import { ImageApi } from '../../generated-client/api/image-api';

export function getImageApi(api: Api): ImageApi {
return new ImageApi(api.configuration, undefined, api.axiosInstance);
import { ImageUrlsApi } from './image-urls-api';

export function getImageApi(api: Api): ImageUrlsApi {
return new ImageUrlsApi(api.configuration, undefined, api.axiosInstance);
}
138 changes: 138 additions & 0 deletions src/utils/api/image-urls-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import type { ImageApiGetSplashscreenRequest } from '../../generated-client/api/image-api';
import { ImageApi } from '../../generated-client/api/image-api';
import type { BaseItemDto } from '../../generated-client/models/base-item-dto';
import { ImageType } from '../../generated-client/models/image-type';
import type { UserDto } from '../../generated-client/models/user-dto';
import type { ImageRequestParameters } from '../../models/api/image-request-parameters';

/**
* ImageUrlsApi - ImageApi with URL utility methods
* @export
* @class ImageUrlsApi
* @extends {ImageApi}
*/
export class ImageUrlsApi extends ImageApi {
/**
* Get an Item image URL for a given Item ID.
* @param itemId The Item ID.
* @param [imageType=ImageType.Primary] An optional Image Type.
* @param [params={}] Additional request parameters.
* @returns The image URL.
*/
public getItemImageUrlById(
itemId: string,
imageType: ImageType = ImageType.Primary,
params: ImageRequestParameters = {}
): string {
// TODO: We could probably use ImageApiAxiosParamCreator to make this more robust
return this.axios.getUri({
baseURL: this.configuration?.basePath,
url: `/Items/${itemId}/Images/${imageType}`,
params
});
}

/**
* Get an Item image URL with automatic `tag` param handling.
* @param item The Item.
* @param [imageType] An optional Image Type (Primary by default).
* @param [params={}] Additional request parameters.
* @returns The Item image URL.
*/
public getItemImageUrl(item?: BaseItemDto, imageType: ImageType = ImageType.Primary, params: ImageRequestParameters = {}): string | undefined {
if (!item?.Id) return;

return this.getItemImageUrlById(
item.Id,
imageType,
{
...params,
tag: params.tag ?? item.ImageTags?.[imageType]
}
);
}

/**
* Get an Item's backdrop image URLs.
* @param item The Item.
* @param [params={}] Additional request parameters.
* @returns An array of backdrop image URLs.
*/
public getItemBackdropImageUrls(item?: BaseItemDto, params: ImageRequestParameters = {}): string[] {
const urls: string[] = [];
const id = item?.Id;

if (!id) return urls;

item.BackdropImageTags?.forEach(tag => {
const url = this.getItemImageUrlById(
id,
ImageType.Backdrop,
{
...params,
tag
}
);

urls.push(url);
});

if (urls.length > 0) return urls;

const parentId = item.ParentBackdropItemId;
if (parentId) {
item.ParentBackdropImageTags?.forEach(tag => {
const url = this.getItemImageUrlById(
parentId,
ImageType.Backdrop,
{
...params,
tag
}
);

urls.push(url);
});
}

return urls;
}

/**
* Get the splash screen image URL.
* @param [params={}] Additional request parameters.
* @returns The splash screen image URL.
*/
public getSplashscreenImageUrl(params: ImageApiGetSplashscreenRequest = {}): string {
return this.axios.getUri({
baseURL: this.configuration?.basePath,
url: '/Branding/Splashscreen',
params
});
}

/**
* Get a User's primary image URL.
* @param user The User.
* @param [params={}] Additional request parameters.
* @returns The User's primary image URL.
*/
public getUserImageUrl(user?: UserDto, params: ImageRequestParameters = {}): string | undefined {
if (!user?.Id) return;

return this.axios.getUri({
baseURL: this.configuration?.basePath,
url: `/Users/${user.Id}/Images/Primary`,
params: {
...params,
tag: user.PrimaryImageTag
}
});
}
}
2 changes: 1 addition & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@

export * from './address-candidates';
export * from './authentication';
export * from './url';
export * from './browser-profiles';
export * from './url';
export * from './versioning';