Appearance
Available Interfaces
When a webpage is opened in the client it exposes some functions onto window.
TIP
The features thus exposed are typically handled by Aeppic, but in case of editing conflicts some functions might need to be called directly.
E.g file editing is exposed via Aeppic.editFile. See Aeppic File Handling
The entire interface is made available on the property `host``:
AeppicClientHostInterface (aeppic.ts)
ts
interface AeppicClientHostInterface {
type: string,
version: string,
matches: (semver: string) => boolean,
features: {
[featureGroupName: string]: {
[featureName: string]: boolean
}
},
files: {
openFile(
url: string,
fileName: string,
documentInformation: {
id: string,
v: string,
fieldName: string,
mimeType: string,
}): void,
editFile(
url: string,
fileName: string,
documentInformation: {
id: string,
v: string,
fieldName: string,
mimeType: string,
uploadFormFields?: {
[fieldName: string]: string
},
uploadFileFieldName?: string,
uploadUrl?: string,
}): void,
subscribeToEditEvents(callback: (editInfo: ClientEditInfo) => void): () => void,
}
}typescript
window.host = {
type: 'aeppic-client',
version: '1.3.7', // A semver compatible version
/// A simple match function to test
/// the expected semver e.g. '1.2.3' or '^1.2.3', or '^1.2'
/// against the actual version.
match(expectedSemVer: string) -> bool { ... },
...
// More see below
}Features
Flags on which features are supported can be checked. These are grouped by exposed group.
typescript
window.host.features = {
files: {
open: boolean
edit: boolean
}
}Files
typescript
window.host.files = {
/// Open a file in the local OS application associated with
/// the filetype.
///
/// url: Where to download from
/// When already downloaded before and ETag was returned it is used to NOT
/// download again. (Stored in etag.txt next to the downloaded file)
///
/// fileName: The name the file should get in the local filesystem
///
/// {
/// id: Id of the aeppic document the file is associated with
/// v: The version of the aeppic document (only for logging etc)
/// fieldName: The name of the field the file is store in
/// mimeType: The mime type of the file. If filename is not defined
/// this is used for a default extension if possible.
/// }
///
/// Note: The file is marked `readonly` when possible
///
async openFile(url, fileName, { id, v, fieldName, mimeType } = {}) {
// Get an access token for the current user to hand to the
const accessToken = await window.host.helpers.readAccessToken(['content.read'])
// Call the host
...
},
/// Open a file in the local OS application associated with
/// the filetype.
///
/// url: Where to download from
/// When already downloaded before and ETag was returned it is used to NOT
/// download again. (Stored in etag.txt next to the downloaded file)
///
/// fileName: The name the file should get in the local filesystem
///
/// {
/// id: Id of the aeppic document the file is associated with
/// v: The version of the aeppic document (only for logging etc)
/// fieldName: The name of the field the file is store in
/// mimeType: The mime type of the file. If filename is not defined
/// this is used for a default extension if possible.
/// dataUrl: The EXACT identify url identifying the content. Important
/// for collision control. When NOT defined any collisions
/// are ignored.
///
/// Optional: Fields to add to the form encoded upload body. A new and unique dataUrl
/// is auto included.
///
/// uploadFormFields: { <FIELD>:<CONTENT-STRING> }
///
/// uploadFileFieldName: The name the binary file content is expected in for the upload
/// uploadUrl: The url to upload the file to
/// }
///
/// Note: The file is marked as NOT `readonly` when possible
///
async editFile(url, fileName, { id, v, fieldName, dataUrl, mimeType, uploadFormFields = {}, uploadFileFieldName = 'file', uploadUrl = '/api/_upload' } = {}) {
// Get an access token for the current user to hand to the
const accessToken = await window.host.helpers.readAccessToken(['content.read', 'content.write'])
// Call the host
...
},
/// Events to inform what happens in the host. E.g change events, edit events etc.
subscribeToEditEvents(cb) {
// Start listening for events
... calling back whenever an edit events happens /..
cb(editInfo)
},
// Delete the locally downloaded document matching the document id with the binary
// stored in the specified field. The 'v' field is only used for logging purposes.
async delete({ id, v, fieldName }) {
...
},
// Delete all files downloaded longer than `maxAgeInSeconds` ago.
// NOTE: `Downloaded` NOT `modified`
async deleteOld(maxAgeInSeconds = 60 * 60 * 24 * 7) {
...
},
// Delete ALL locally downloaded content
async deleteAll() {
...
},
async listWatched() {
...
},
}Errors
openFile and editFile can throw an exception object.
The error objects thrown are all structured in a similar fashion.
They have ONE key which is named after the error type and then the data fields associated with it.
e.g
javascript
{
DataUrlOutOfSync: {
data_url_specified: "aeppic-local://client/98b70521-8617-4fcf-ab4b-97509f579013",
last_known_data_url: "aeppic-local://client/98b70521-8617-4fcf-ab4b-97509f579013dasdasd"
}
}DataUrlOutOfSync
When a document was locally edited this will happen. The client will have generated a new data url and thus detect a potential loss of data.
javascript
{
DataUrlOutOfSync: {
data_url_specified: "aeppic-local://client/98b70521-8617-4fcf-ab4b-97509f579013",
last_known_data_url: "aeppic-local://client/98b70521-8617-4fcf-ab4b-97509f579013dasdasd"
}
}FileAlreadyDownloading
Still downloading. Wait until finished
javascript
{
FileAlreadyDownloading: {
path: "/local/file/path.txt",
}
}WatchFile
Error trying to watch changes to the file
javascript
{
WatchFile: {
path: "/local/file/path.txt",
}
}CannotSendDownloadRequest
Could not connect to the server
javascript
{
CannotSendDownloadRequest: {
info: {
url: string,
dataUrl: string,
accessToken?: string,
explicitFileName: string,
mimeType: string,
document?: {
id: string,
v: string,
text?: string,
},
fieldName?: string,
makeEditable?: boolean
}
},
source: {
message: string
}
}CannotDownloadFile
Could not download the file successfully
javascript
{
CannotSendDownloadRequest: {
info: {
url: string,
dataUrl: string,
accessToken?: string,
explicitFileName: string,
mimeType: string,
document?: {
id: string,
v: string,
text?: string,
},
fieldName?: string,
makeEditable?: boolean
}
},
status_code: number
}CannotCreateLocalFile
Could not store the file locally successfully
javascript
{
CannotSendDownloadRequest: {
info: {
url: string,
dataUrl: string,
accessToken?: string,
explicitFileName: string,
mimeType: string,
document?: {
id: string,
v: string,
text?: string,
},
fieldName?: string,
makeEditable?: boolean
}
},
source: {
message: string
}
}CannotReadFromDownload
Could not read from the response stream
javascript
{
CannotReadFromDownload: {
info: {
url: string,
dataUrl: string,
accessToken?: string,
explicitFileName: string,
mimeType: string,
document?: {
id: string,
v: string,
text?: string,
},
fieldName?: string,
makeEditable?: boolean
}
},
source: {
message: string
}
}CannotWriteLocalFile
Could not write into the local file
javascript
{
CannotWriteLocalFile: {
info: {
url: string,
dataUrl: string,
accessToken?: string,
explicitFileName: string,
mimeType: string,
document?: {
id: string,
v: string,
text?: string,
},
fieldName?: string,
makeEditable?: boolean
}
},
source: {
message: string
}
}Events
The events raised:
Change
When a file change is detected
typescript
{
Changed: [
string, // The path of the file changed locally
{
url: string,
dataUrl: string,
explicitFileName: string,
document?: {
id: string,
v: string,
text?: string,
},
fieldName?: string,
}
]
}Upload
All upload events have the same data associated with them.
typescript
type UploadFileInfo = {
uploadKey: string,
filePath: string,
targetUrl: string,
document: {
id: string,
v: string,
text?: string,
},
fieldName: string // Name of the field the document stores this binary in
}So for Started it would look like this:
typescript
{
Upload: {
Started: UploadFileInfo
}
}All events:
| Event Name | Description |
|---|---|
| Started | The upload has begun |
| Canceling | The upload is currently being canceled |
| Canceled | The upload was canceleld |
| Finished | The upload was successfully uploaded |
| Failed | The upload failed to upload |
Viewer
This is an interface for multi-monitor support for specific use-cases. At the moment it is meant for hooking up a DICOM viewer, but will be made more generi over time.
typescript
window.host.viewer = {
isAvailable: false,
url: '',
numberOfMonitors: 0,
}If available (if compiled like that)
typescript
window.host.viewer = {
isAvailable: true,
getMonitors: async function() {
},
// Open all viewer windows (using the url as configured during compile time)
openWindows: function() {
},
// Close them
closeWindows: function() {
},
// Show the data on the monitor 0
showOnPrimary: function(args) {
},
// Show the data on the monitor 1
showOnSecondary: function(args) {
},
// Show the data on the monitor auxMonitorIndx
showOnAuxiliary: function(auxMonitorIndex, args) {
},
}Helpers (Internal)
typescript
window.host.helpers = {
// These are for internal use inside the previous modules and can be changed at any time between any versions
}