import ApiClient from './ApiClient';
import * as P from './types/Presentation';
import urls from './urls';
import {
mapResourceResponse,
mapResourceV2Response,
mapCreateTag,
} from './ResourceClient';
import {
mapFileUploadResponse,
mapNewFileUploadsResponse,
} from './FileUploadUtils';
import { mapThemeResponse } from './ThemeClient';
export const mapPresentationResponse = (
p: P.PresentationResponse,
): P.Presentation => ({
id: p.id,
name: p.name,
applicationId: p.application_id,
appVersionId: p.application_deployment_id,
themeId: p.theme_id,
applicationThumbnailUrl: p.application_thumbnail_url,
thumbnailUrl: p.thumbnail_url,
iconUrl: p.icon_url,
applicationName: p.application_name,
presentationProperties: p.presentation_properties,
applicationVariables: p.application_vars,
hasDynamicThumbnails: p.has_dynamic_thumbnails,
duration: p.duration,
sourceUrl: p.source_url,
fileUploads: p.file_uploads
? p.file_uploads.map(mapFileUploadResponse)
: null,
resource: mapResourceResponse(p.resource),
theme:
p.theme_id && p.theme
? mapThemeResponse({
...p.theme,
resource: p.resource,
})
: undefined,
previewOrientation: p.preview_orientation,
previewResolution: p.preview_resolution,
});
export const mapPresentationV2Response = (
p: P.PresentationV2Response,
): P.PresentationV2 => ({
id: p.id,
name: p.name,
duration: p.duration,
applicationVariables: p.application_vars,
applicationDeploymentId: p.application_deployment_id,
themeId: p.theme_id,
token: p.token,
r: {
resource: mapResourceV2Response(p.r.resource),
presentationsPlaylists: (p.r.presentations_playlists || []).map((item) => ({
playlistId: item.playlist_id,
})),
},
previewOrientation: p.preview_orientation,
previewResolution: p.preview_resolution,
});
export const mapPresentationToV2 = (p: P.Presentation): P.PresentationV2 => ({
id: p.id,
name: p.name,
duration: p.duration ?? 30,
applicationVariables: p.applicationVariables,
applicationDeploymentId: p.appVersionId,
themeId: p.themeId ?? null,
token: p.token,
r: {
resource: {
id: p.resource.id,
profileId: p.resource.profile.id,
domainId: p.resource.domain?.id ?? null,
parentFolderId: p.resource.parentFolderId,
createdAt: p.resource.createdAt,
updatedAt: p.resource.updatedAt,
deletedAt: p.resource.deletedAt,
r: {
tags: p.resource.r.tags,
},
},
presentationsPlaylists: [],
},
});
export default class PresentationClient {
async getPresentations(
this: ApiClient,
filter?: { ids: string[] },
): Promise
{
const isValidQueryParams = filter && filter.ids.length > 0;
const filterQs = isValidQueryParams ? `?id=${filter?.ids.join(',')}` : '';
const data = await this.requestProtected<
P.GetPresentationsRequest,
P.GetPresentationsResponse
>({
method: 'GET',
url: `${urls.presentations()}${filterQs}`,
});
return data.map(mapPresentationResponse);
}
async deletePresentation(this: ApiClient, id: string): Promise {
await this.requestProtected<
P.DeletePresentationRequest,
P.DeletePresentationResponse
>({
method: 'DELETE',
url: urls.presentation(id),
});
}
async updatePresentation(
this: ApiClient,
id: string,
params: P.UpdatePresentation,
): Promise<[P.Presentation, P.NewFileUploads]> {
const {
presentation,
file_uploads: fileUploads,
} = await this.requestProtected<
P.UpdatePresentationRequest,
P.UpdatePresentationResponse
>({
method: 'PATCH',
url: urls.presentation(id),
body: {
name: params.name,
application_deployment_id: params.appVersionId,
theme_id: params.themeId,
application_vars: params.applicationVariables,
duration: params.duration,
resource: params.resource && {
r: params.resource?.r && {
tags: params.resource.r.tags?.map(mapCreateTag),
},
},
preview_orientation: params.previewOrientation,
preview_resolution: params.previewResolution,
},
});
return [
mapPresentationResponse(presentation),
mapNewFileUploadsResponse(fileUploads),
];
}
async createPresentation(
this: ApiClient,
params: P.CreatePresentation,
): Promise<[P.Presentation, P.NewFileUploads]> {
const {
presentation,
file_uploads: fileUploads,
} = await this.requestProtected<
P.CreatePresentationRequest,
P.CreatePresentationResponse
>({
method: 'POST',
url: urls.presentations(),
body: {
name: params.name,
application_deployment_id: params.appVersionId,
theme_id: params.themeId,
application_vars: params.applicationVariables,
duration: params.duration,
preview_orientation: params.previewOrientation,
preview_resolution: params.previewResolution,
},
});
return [
mapPresentationResponse(presentation),
mapNewFileUploadsResponse(fileUploads),
];
}
async movePresentationToFolder(
this: ApiClient,
presentationId: string,
folderId: string | null,
): Promise {
await this.requestProtected<{ folder_id: string | null }, void>({
method: 'POST',
url: urls.presentationMoveToFolder(presentationId),
body: {
folder_id: folderId,
},
});
}
async copyPresentation(
this: ApiClient,
presentationId: string,
params: {
name?: string;
targetFolderId?: string;
copyOutOfTreeUnowned?: boolean;
} = {},
): Promise {
const data = await this.requestProtected<
P.CopyPresentationRequest,
P.CopyPresentationResponse
>({
method: 'POST',
url: urls.presentationCopy(presentationId),
body: {
name: params.name,
...(params.targetFolderId
? { target_folder_id: params.targetFolderId }
: {}),
...(params.copyOutOfTreeUnowned !== undefined
? { copy_out_of_tree_unowned: params.copyOutOfTreeUnowned }
: {}),
},
});
// Preflight: when the server flags out-of-tree unowned content it copies
// nothing and returns only the flag (no presentation — so no `id` — to
// map), so short-circuit. A confirmed copy always returns the presentation
// (even if it echoes the flag), so the `'id' in data` guard keeps it on the
// real branch.
if (!('id' in data)) {
return {
hasOutOfTreeUnowned: true,
supportingContentFolderCreated: false,
};
}
return {
...mapPresentationResponse(data),
supportingContentFolderCreated: !!data.supporting_content_folder_created,
};
}
async getPresentationsList(
this: ApiClient,
query?: string,
): Promise {
const data = await this.requestProtected<
P.GetPresentationsRequest,
P.GetPresentationsListResponse
>({
method: 'GET',
url: urls.getPresentationsList(query),
});
return data;
}
}