diff --git a/lib/api.ts b/lib/api.ts index bf181c265b..1810f4589a 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -2,6 +2,7 @@ import { makeField } from './field' import { makeFieldLocale } from './field-locale' import createWindow from './window' import createEntry from './entry' +import createAsset from './asset' import createSpace from './space' import createDialogs from './dialogs' import createEditor from './editor' @@ -38,6 +39,7 @@ const LOCATION_TO_API_PRODUCERS: { [location: string]: ProducerFunc[] } = { [locations.LOCATION_ENTRY_FIELD]: DEFAULT_API_PRODUCERS, [locations.LOCATION_ENTRY_FIELD_SIDEBAR]: DEFAULT_API_PRODUCERS, [locations.LOCATION_ENTRY_SIDEBAR]: [makeSharedAPI, makeEntryAPI, makeEditorAPI, makeWindowAPI], + [locations.LOCATION_ASSET_SIDEBAR]: [makeSharedAPI, makeAssetAPI, makeWindowAPI], [locations.LOCATION_ENTRY_EDITOR]: [makeSharedAPI, makeEntryAPI, makeEditorAPI], [locations.LOCATION_DIALOG]: [makeSharedAPI, makeDialogAPI, makeWindowAPI], [locations.LOCATION_PAGE]: [makeSharedAPI], @@ -151,6 +153,12 @@ function makeDialogAPI(channel: Channel) { } } +function makeAssetAPI(channel: Channel, { asset }: ConnectMessage) { + return { + asset: createAsset(channel, asset), + } +} + function makeAppAPI(channel: Channel) { const app = createApp(channel) diff --git a/lib/asset.ts b/lib/asset.ts new file mode 100644 index 0000000000..ec800adb79 --- /dev/null +++ b/lib/asset.ts @@ -0,0 +1,53 @@ +import { Channel } from './channel' +import { MemoizedSignal } from './signal' +import { ConnectMessage, Metadata } from './types' +import { AssetAPI } from './types/asset.types' +import { AssetSys } from './types/utils' + +export default function createAsset( + channel: Channel, + assetData: ConnectMessage['asset'], +): AssetAPI { + if (!assetData) { + throw new Error('Asset data is required') + } + + let sys: AssetSys = assetData.sys + const sysChanged = new MemoizedSignal<[AssetSys]>(sys) + let metadata = assetData.metadata + const metadataChanged = new MemoizedSignal<[Metadata | undefined]>(metadata) + + channel.addHandler('sysChanged', (newSys: AssetSys) => { + sys = newSys + sysChanged.dispatch(sys) + }) + + channel.addHandler('metadataChanged', (newMetadata: Metadata) => { + metadata = newMetadata + metadataChanged.dispatch(metadata) + }) + + return { + getSys() { + return sys + }, + publish(options?: { skipUiValidation?: boolean }) { + return channel.call('callAssetMethod', 'publish', [options]) + }, + unpublish() { + return channel.call('callAssetMethod', 'unpublish') + }, + save() { + return channel.call('callAssetMethod', 'save') + }, + onSysChanged(handler: (sys: AssetSys) => void) { + return sysChanged.attach(handler) + }, + getMetadata() { + return metadata + }, + onMetadataChanged(handler: VoidFunction) { + return metadataChanged.attach(handler) + }, + } +} diff --git a/lib/locations.ts b/lib/locations.ts index 0f5d601194..23e604cb42 100644 --- a/lib/locations.ts +++ b/lib/locations.ts @@ -4,6 +4,7 @@ const locations: Locations = { LOCATION_ENTRY_FIELD: 'entry-field', LOCATION_ENTRY_FIELD_SIDEBAR: 'entry-field-sidebar', LOCATION_ENTRY_SIDEBAR: 'entry-sidebar', + LOCATION_ASSET_SIDEBAR: 'asset-sidebar', LOCATION_DIALOG: 'dialog', LOCATION_ENTRY_EDITOR: 'entry-editor', LOCATION_PAGE: 'page', diff --git a/lib/types/api.types.ts b/lib/types/api.types.ts index 7694fed922..168a0834db 100644 --- a/lib/types/api.types.ts +++ b/lib/types/api.types.ts @@ -14,7 +14,7 @@ import { import { EntryAPI } from './entry.types' import { SpaceAPI } from './space.types' import { WindowAPI } from './window.types' -import { EntrySys, Link, SerializedJSONValue } from './utils' +import { EntrySys, AssetSys, Link, SerializedJSONValue } from './utils' import { FieldAPI } from './field-locale.types' import { DialogsAPI } from './dialogs.types' import { AppConfigAPI } from './app.types' @@ -386,6 +386,7 @@ export interface Locations { LOCATION_ENTRY_FIELD: 'entry-field' LOCATION_ENTRY_FIELD_SIDEBAR: 'entry-field-sidebar' LOCATION_ENTRY_SIDEBAR: 'entry-sidebar' + LOCATION_ASSET_SIDEBAR: 'asset-sidebar' LOCATION_DIALOG: 'dialog' LOCATION_ENTRY_EDITOR: 'entry-editor' LOCATION_PAGE: 'page' @@ -411,6 +412,10 @@ export interface ConnectMessage { sys: EntrySys metadata?: Metadata } + asset?: { + sys: AssetSys + metadata?: Metadata + } fieldInfo: EntryFieldInfo[] field?: FieldInfo hostnames: HostnamesAPI diff --git a/lib/types/asset.types.ts b/lib/types/asset.types.ts new file mode 100644 index 0000000000..3c4bbd5ea2 --- /dev/null +++ b/lib/types/asset.types.ts @@ -0,0 +1,17 @@ +import { Metadata } from './entities' +import { AssetSys } from './utils' + +export interface AssetAPI { + /** Returns sys for an asset. */ + getSys: () => AssetSys + /** Publish the asset */ + publish: (options?: { skipUiValidation?: boolean }) => Promise + /** Unpublish the asset */ + unpublish: () => Promise + /** Saves the current changes of the asset */ + save: () => Promise + /** Calls the callback with sys every time that sys changes. */ + onSysChanged: (callback: (sys: AssetSys) => void) => () => void + getMetadata: () => Metadata | undefined + onMetadataChanged: (callback: (metadata?: Metadata) => void) => VoidFunction +} diff --git a/lib/types/utils.ts b/lib/types/utils.ts index e326941cb7..2e557273e7 100644 --- a/lib/types/utils.ts +++ b/lib/types/utils.ts @@ -70,6 +70,10 @@ export interface EntrySys extends ContentEntitySys { automationTags: Link<'Tag'>[] } +export interface AssetSys extends ContentEntitySys { + type: 'Asset' +} + export type FieldType = | 'Symbol' | 'Text'