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
}