UNPKG

labo-components

Version:
282 lines (243 loc) 8.65 kB
import { ANNOTATION_TARGET, CUSTOM } from "../../util/AnnotationConstants"; import Strings from "./_Strings"; const SEGMENT_LAYERS = "segment-layers"; class SegmentLayers { constructor({ annotationClient }) { this.annotationClient = annotationClient; window.segmentLayers = this; } // Get an array of segments by given layer id getSegments(id) { const annotations = this.annotationClient.annotations; // All user segments return annotations ? annotations.filter( (annotation) => annotation.target.type === ANNOTATION_TARGET.SEGMENT && (annotation.target.layerId === id || // number corresponding with layerId (id === 0 && // add annotations with invalid layerId to layerId 0 (!annotation.target.layerId || // fallback for undefined !( typeof annotation.target.layerId == "number" )))) // fallback for non numbers ) : []; } // Get all unique layer ids from given annotations getLayerIds = () => { const annotations = this.annotationClient.annotations; const ids = {}; let id = ""; annotations.forEach((annotation) => { if ( annotation.target && annotation.target.type === ANNOTATION_TARGET.SEGMENT ) { id = annotation.target.layerId; // undefined -> 0 if (id == undefined) { id = 0; } // not a number -> Parse if (typeof id != "number") { id = parseInt(id); // NaN -> 0 if (isNaN(id)) { id = 0; } } ids[id] = true; } }); return Object.keys(ids) .map((id) => parseInt(id)) .sort(); }; getLayerConfigData() { const annotations = this.annotationClient.annotations; // get (first) media object annotation const annotation = annotations.find( (annotation) => annotation.target.type === ANNOTATION_TARGET.MEDIAOBJECT ); // Require an annotation with body if (!annotation || !annotation.body) { return null; } // Find the layer template return annotation.body.find((body) => { if (body.annotationType === CUSTOM && body.role == SEGMENT_LAYERS) { return true; } }); } // Get annotation layer config from MediaObject annotation getLayerConfig() { const data = this.getLayerConfigData(); return data && data.data ? data.data : {}; } // Get all layers getLayers() { // layer data from media object data annotation const layers = this.getLayerConfig(); // layer ids currently in use const layerIds = this.getLayerIds(); // merge layerIds.forEach((id) => { if (!(id in layers)) { layers[id] = "Layer " + id; } }); return layers; } getLayersSorted() { const layers = this.getLayers(); return Object.keys(layers) .sort((a, b) => { const titleA = layers[a].toLowerCase(); const titleB = layers[b].toLowerCase(); return titleA == titleB ? 0 : titleA > titleB ? 1 : -1; }) .map((id) => ({ id: parseInt(id), title: layers[id] })); } // Get first layer id available, default to 0 getFirstLayerId() { const layers = this.getLayers(); const keys = Object.keys(layers); return keys.length > 0 ? keys[0] : 0; } // Get current MediaObject target annotation, or create a new one if needed getOrCreateMediaObjectAnnotation = async () => { // Current let targetAnnotation = this.annotationClient.annotations.filter( (annotation) => // current mediaObject annotation.target && annotation.target.type === ANNOTATION_TARGET.MEDIAOBJECT ); if (targetAnnotation.length > 0) { return targetAnnotation[0]; } // create target annotation targetAnnotation = this.annotationClient.newAnnotation( ANNOTATION_TARGET.MEDIAOBJECT, false ); if (!targetAnnotation) { console.error("Could not create a target annotation"); return null; } this.annotationClient.edit(targetAnnotation); await this.annotationClient.save(true, false); return this.annotationClient.activeAnnotation; }; // Create a custom annotation for the layerconfig createLayerConfig = async () => { const targetAnnotation = await this.getOrCreateMediaObjectAnnotation(); if (!targetAnnotation) { console.error("Could not create layer config"); return; } const data = { annotationType: CUSTOM, role: SEGMENT_LAYERS, data: {}, // { 0: "My layer name" } }; await this.annotationClient.saveBodyElement( data, true, true, targetAnnotation ); }; // Save layer config to custom annotation saveLayerConfig = async (config) => { const targetAnnotation = await this.getOrCreateMediaObjectAnnotation(); if (!targetAnnotation) { console.error("Could not create layer config"); return; } let data = this.getLayerConfigData(); if (!data) { data = { annotationType: CUSTOM, role: SEGMENT_LAYERS, }; } data.data = config; await this.annotationClient.saveBodyElement( data, true, true, targetAnnotation ); }; // Get layer config; if no layer config has been created yet, add it to the annotation data getOrCreateLayerConfig = async () => { let config = this.getLayerConfig(); if (Object.keys(config).length > 0) { return config; } // create new await this.createLayerConfig(); return this.getLayerConfig(); }; // Add a new segment layer to the config/data // space in title intentional; puts the new layer first in sort order addLayer = async (title = " My segment layer") => { const config = await this.getLayerConfig(); let id = 0; // Check for id in config until there is an empty spot while (id in config) { id++; } config[id] = title; await this.saveLayerConfig(config); }; // Callable as callback, prevents using the event as layer title addEmptyLayer = async () => { this.addLayer(); }; // Rename a layer with given id, title renameLayer = async (id, title) => { const config = await this.getLayerConfig(); config[id] = title; await this.saveLayerConfig(config); }; getLayerTitle(id) { const config = this.getLayerConfig(); return id in config ? config[id] : "Layer " + id; } deleteLayer = async (id) => { // delete segments const segments = this.getSegments(id); for (let i = 0, len = segments.length; i < len; i++) { await this.annotationClient.delete(segments[i], true); // notify at last iteration i == len - 1 } // delete from config const config = await this.getLayerConfig(); if (id in config) { delete config[id]; await this.saveLayerConfig(config); } }; deleteLayerWithCheck = async (id) => { // Can not delete empty or static layer if (id == null || id < 0) { alert(Strings.BUTTON_DELETE_USER_LAYER_DENIED); return; } if ( confirm( Strings.BUTTON_DELETE_USER_LAYER_CONFIRM.replace( "%LAYER_NAME%", this.getLayerTitle(id) ) ) ) { this.annotationClient.segmentLayers.deleteLayer(id); } }; } export default SegmentLayers;