Celtra CA allows teams to build custom UI extensions to better connect with external tools and workflows. This project provides the documentation for setting up the extension, available API methods, as well as provide a template project you can use to get started with your own extension.
The extension template is in typescript. It uses Vue (Pinia) framework with Vuetify frontend components and a Vite build. The build packages all files into a single html which can then be served by either uploading it to your own sever or hosting it with Celtra.
As long as a single url can be provided, on which the extension is hosted, any technologies, languages, frameworks... can be used.
To work with this repository, you will need node and npm installed.
Fork this repository to change it and make it your own. Once you clone it, run npm ci for first package installation.
Create a Celtra API App to use basic auth.
Caution
For development and testing, a Celtra sandbox account should be used to avoid partially developed extensions to be visible to all users. If you do not have access to a Celtra sandbox account please contact your Account Manager.
npm cito install packagesnpm run lintto lint code andnpm run lint-fixto fix lint problemsnpm run buildto build a singleindex.htmlfile in the./distfoldernpm run devto build code and start development server.
-
Run
npm run buildto createdist/index.html -
You have two options to add extensions to the Celtra platform:
-
Self-hosted
index.html:Host the
index.htmlfile on your own server or hosting service. The html must be served withtext/htmlmime type and must not have headers preventing it from being served inside aniframe. You will need to pass the url where theindex.htmlis hosted in theindexHtmlUrlparameter. Example for adding an extension with a self-hostedindex.html:curl -X POST \ --location 'https://hub.celtra.io/api/uiExtensions' \ --user '<ApiAppId>:<ApiAppKey>' \ --header 'Content-Type: application/json;charset=UTF-8' \ --data '{ "accountId": "<your account id>", "name": "Example Extension", "isEnabled": true, "indexHtmlUrl": "<your hosting url>" }' -
Celtra-hosted
index.html:You can also use Celtra to host your extension's
index.htmlfile. Encode theindex.htmlfile usingbase64and pass it in thehtmlparameter. Example for adding an extension with a Celtra-hostedindex.html:# Base64 encode index.html. html_content=$(cat dist/index.html | base64 -w 0) # Or in some Mac shells # html_content=$(cat dist/index.html | base64 -b 0) # Construct JSON payload with Base64-encoded HTML. json_payload='{ "accountId": "<your account id>", "name": "Example Extension", "isEnabled": true, "html": "'"$html_content"'" }' # Send POST request with JSON payload using curl. curl -X POST \ --location 'https://hub.celtra.io/api/uiExtensions' \ --user '<ApiAppId>:<ApiAppKey>' \ -H 'Content-Type: application/json;charset=UTF-8' \ -d @- <<EOF $json_payload EOF
-
If successful, you will get an extensionEntityId back.
To view the extension in Celtra CA, open a Design File and go to Overview tab, click on Export button and you should see your extension as an option in Distribute list.
Note
If your extension contains errors or URL is not accessible, it might not appear in the list.
During development you can also use localhost URL you get when running npm run dev as indexHtmlUrl.
You can add new extensions to an account using the POST method.
Self-hosed index.html:
curl -X POST \
--location 'https://hub.celtra.io/api/uiExtensions' \
--user '<ApiAppId>:<ApiAppKey>' \
--header 'Content-Type: application/json;charset=UTF-8' \
--data '{
"accountId": "<your account id>",
"name": "Example Extension",
"isEnabled": true,
"indexHtmlUrl": "<your hosting url>"
}'
Celtra-hosed index.html:
# Base64 encode index.html.
html_content=$(cat /path/to/file | base64 -w 0)
# Or in some Mac shells
# html_content=$(cat /path/to/file | base64 -b 0)
# Construct JSON payload with Base64-encoded HTML.
json_payload='{
"accountId": "<your account id>",
"name": "Example Extension",
"isEnabled": true,
"html": "'"$html_content"'"
}'
curl -X POST \
--location 'https://hub.celtra.io/api/uiExtensions' \
--user '<ApiAppId>:<ApiAppKey>' \
-H 'Content-Type: application/json;charset=UTF-8' \
-d @- <<EOF
$json_payload
EOF
If successful, you will get an extensionEntityId back.
You can list all extensions in an account using the GET method:
curl -X GET \
--location 'https://hub.celtra.io/api/uiExtensions?accountId={accountId}' \
--user '<ApiAppId>:<ApiAppKey>'
You can edit name, isEnabled, indexHtmlUrl and html properties of existing extensions using the PUT method.
Note
The indexHtmlUrl and html cannot be set at the same time.
Self-hosed index.html:
curl -X PUT \
--location 'https://hub.celtra.io/api/uiExtensions/<extensionEntityId>' \
--user '<ApiAppId>:<ApiAppKey>' \
--header 'Content-Type: application/json;charset=UTF-8' \
--data '{
"name": "New Example Extension",
"isEnabled": false,
"indexHtmlUrl": "<your hosting url>"
}'
Celtra-hosed index.html:
# Base64 encode index.html.
html_content=$(cat /path/to/file | base64 -w 0)
# Or in some Mac shells
# html_content=$(cat /path/to/file | base64 -b 0)
# Construct JSON payload with Base64-encoded HTML.
json_payload='{
"accountId": "<your account id>",
"name": "Example Extension",
"isEnabled": true,
"html": "'"$html_content"'"
}'
curl -X PUT \
--location 'https://hub.celtra.io/api/uiExtensions' \
--user '<ApiAppId>:<ApiAppKey>' \
-H 'Content-Type: application/json;charset=UTF-8' \
-d @- <<EOF
$json_payload
EOF
You can delete a registered extension using the DELETE method:
curl -X DELETE
--location 'https://hub.celtra.io/api/uiExtensions/<extensionEntityId>' \
--user '<ApiAppId>:<ApiAppKey>' \
--header 'Content-Type: application/json;charset=UTF-8'
Celtra provides a public npm package @celtra/eagle-extensions-sdk published to GitHub packages. It provides predefined functions and data types (e.g. Export API output types and Custom Format Schema Definition) the extension can use to communicate with the Celtra CA platform.
export(request: Request): Promise<Response>
Request export as specified in request object. The request and response are the same as specified by the export API
setOnBeforeUnloadMessage(message: string | null): Promise<void>
If set to string, the extension window will require additional confirmation before closing.
registerFormat(formatRegistrationId: string, formatRegistrationOptions: FormatRegistrationOptions): Promise<void>
Register a new custom format using a schema. See FormatRegistrationOptions type for details on the schema structure.
registerDistributionWorkflow(distributionWorkflowRegistrationId: string, distributionWorkflowRegistrationOptions: DistributionWorkflowRegistrationOptions): Promise<void>
Register a distribution workflow. This allows the extension to be visible in export dialog and open inside an iframe. DistributionWorkflowRegistrationOptions can contain formats registered in other extensions in supportedFormats.
registerEditorWorkflow(editorWorkflowRegistrationId: string, editorWorkflowRegistrationOptions: EditorWorkflowRegistrationOptions): Promise<void>
Register an editor workflow. This allows the extension to be visible in design and content tabs inside an iframe.
registerOutputAttributes(outputAttributesRegistrationOptions: OutputAttributesRegistrationOptions): Promise<void>
Register output attributes with possible values on platform. Output attributes can be used to filter outputs.
setOutputAttributes(outputAttributes: OutputAttributes[]): Promise<void>
Set output attribute values on platform for specified outputs.
setExtensionStorage(data: unknown): Promise<void>
Use Celtra to store data for this extension remotely. For example, output attributes can be saved into extension storage - see src/stores/attributes/store for example.
getExtensionStorage<T>(): Promise<T>
Fetch the data stored by setExtensionStorage.
getOutputContentHashes(): Promise<OutputContentHashes[]>
Get a list of output id's with a hash representing the content of the output.
setDragAndDrop(event: DragEvent, payload: DragAndDropPayload[]): Promise<void>
This action is expected to be used on dragstart event with no propagation. It will initiate dragging the payload into the design file editor and will create a drop when mouseup event is received.
on(type: EventType, callback: VoidFunction): void
Register a callback function that is called when event of type occurs. See EventType for possible options. Multiple callbacks can be registered.
This function can be utilised to sync extension state with other simultaneous users through storage.
off(type: EventType, callback?: VoidFunction): void
Removes the callback for event of type. callback must be the same (=== comparison is used). If callback is not specified, all callbacks removed.
readonly launchOptions: LaunchOptions
Launch options contain the setting the extension is ran in and information extensions in that setting usually use. The extensions are first ran in headless mode when the design file is opened and the extension receives launchOptions.main. When used in the export dialog (see registerDistributionWorkflow), the extension receives launchOptions.distribution . When used in the editor (see registerEditorWorkflow), the extension receives launchOptions.editor .