diff --git a/apps/Info.html b/apps/Info.html
index 03a3a0655..a47693a49 100644
--- a/apps/Info.html
+++ b/apps/Info.html
@@ -87,7 +87,7 @@
diff --git a/apps/dev-workbench/workbench.html b/apps/dev-workbench/workbench.html
index 99bc341c9..055f74c95 100644
--- a/apps/dev-workbench/workbench.html
+++ b/apps/dev-workbench/workbench.html
@@ -121,6 +121,7 @@
href="#"
data-toggle="modal"
data-target="#helpModal"
+ onClick="displayUserGuide()"
>
res.blob()).then((blob) => {
let f = new FileReader();
f.onload = function(e) {
- $('#helpModal .modal-body').html(marked(e.target.result));
+ $('#helpModal .modal-body').html(marked.marked(e.target.result));
$('#helpModal .modal-body td, #helpModal .modal-body th')
.css('border', '2px solid #dddddd').css('padding', '5px');
};
f.readAsText(blob);
});
-});
+}
diff --git a/apps/heatmap/init.js b/apps/heatmap/init.js
index 3298967ee..ea25a642c 100644
--- a/apps/heatmap/init.js
+++ b/apps/heatmap/init.js
@@ -60,6 +60,10 @@ function initCore() {
$CAMIC.loadImg(async function(e) {
Loading.open(document.body, `Loading Data ...`);
+ $CAMIC.viewer.addHandler('open-failed', function(e) {
+ console.error(e.message, e);
+ redirect($D.pages.table, e.message, 5);
+ });
// image loaded
if (e.hasError) {
$UI.message.addError(e.message);
@@ -355,7 +359,7 @@ function initUIcomponents() {
value: 'bugs',
type: 'btn',
callback: ()=>{
- window.open('https://goo.gl/forms/mgyhx4ADH0UuEQJ53', '_blank').focus();
+ window.open('https://github.com/camicroscope/caMicroscope/issues', '_blank').focus();
},
},
diff --git a/apps/labeling/labeling.js b/apps/labeling/labeling.js
index 67ef30f6a..50899f0bc 100644
--- a/apps/labeling/labeling.js
+++ b/apps/labeling/labeling.js
@@ -77,6 +77,10 @@ function initCore() {
defaultText: `Slide: ${$D.params.data.name}`,
});
}
+ $CAMIC.viewer.addHandler('open-failed', function(e) {
+ console.error(e.message, e);
+ redirect($D.pages.table, e.message, 5);
+ });
});
$CAMIC.viewer.addHandler('open', function() {
@@ -146,7 +150,7 @@ function initCore() {
value: 'bugs',
type: 'btn',
callback: ()=>{
- window.open('https://goo.gl/forms/mgyhx4ADH0UuEQJ53', '_blank').focus();
+ window.open('https://github.com/camicroscope/caMicroscope/issues', '_blank').focus();
},
},
],
diff --git a/apps/landing/landing.html b/apps/landing/landing.html
index 0c61f2ad2..9732fc7f7 100644
--- a/apps/landing/landing.html
+++ b/apps/landing/landing.html
@@ -39,7 +39,7 @@
Signup
- Feedback
+ Feedback
diff --git a/apps/landing/main.css b/apps/landing/main.css
index 0fe5b3598..03c28a7fe 100644
--- a/apps/landing/main.css
+++ b/apps/landing/main.css
@@ -2429,6 +2429,12 @@
display: -webkit-flex;
display: -ms-flex;
display: flex;
+ transition: background-color 0.3s ease, transform 0.3s ease;
+ }
+
+ .posts .post:hover {
+ background-color: #f0f0f0;
+ transform: translateY(-10px);
}
.posts .post .image {
diff --git a/apps/mini/dataloaders.js b/apps/mini/dataloaders.js
new file mode 100644
index 000000000..de65438f5
--- /dev/null
+++ b/apps/mini/dataloaders.js
@@ -0,0 +1,111 @@
+
+
+function FormTempaltesLoader() {
+ function loadingFormTemplates() {
+ $CAMIC.store.findTemplate()
+ //
+ .then(function(temps) {
+ // get templates data
+ $D.templates = temps;
+ })
+ //
+ .catch(function(error) {
+ // templates schema
+
+ console.error(error);
+ })
+ //
+ .finally(function() {
+ if ($D.templates) {
+ // load UI
+ } else {
+ // set message
+ $UI.message.addError('Loading Templates is Error');
+ }
+ });
+ }
+
+ var checkCoreIsReady = setInterval(function() {
+ if ($CAMIC) {
+ clearInterval(checkCoreIsReady);
+ // load data
+ loadingFormTemplates();
+ }
+ }, 500);
+}
+
+function layersLoader() {
+ // human
+ function loadingHumanOverlayers() {
+ $CAMIC.store.findMarkTypes($D.params.slideId, 'human').then(function(layers) {
+ // convert part not nesscary
+ $D.humanlayers = [...layers.map(covertToHumanLayer)];
+
+ // add data and create ui item
+ addHumanLayerItems();
+ }).catch(function(error) {
+ // overlayers schema
+ $UI.message.addError('Loading Human Layers is Error');
+ console.error(error);
+ });
+ }
+ // ruler
+ function loadingRulerOverlayers() {
+ $CAMIC.store.findMarkTypes($D.params.slideId, 'ruler').then(function(layers) {
+ // convert part not nesscary
+ $D.rulerlayers = [...layers.map(covertToRulerLayer)];
+
+ // add data and create ui item
+ addRulerLayerItems();
+ }).catch(function(error) {
+ // overlayers schema
+ $UI.message.addError('Loading Ruler Layers is Error');
+ console.error(error);
+ });
+ }
+ // heatmap
+ function loadingHeatmapOverlayers() {
+ $CAMIC.store.findHeatmapType($D.params.slideId).then(function(layers) {
+ $D.heatmaplayers = [];
+ // convert and load heatmap layer
+ for (let i = 0; i < layers.length; i++) {
+ const item = layers[i].provenance.analysis;
+ $D.heatmaplayers.push({id: item.execution_id,
+ name: item.execution_id,
+ typeId: 'heatmap',
+ typeName: 'heatmap',
+ });
+ }
+ // add data and create ui item
+ addHeatmapLayerItems();
+ }).catch(function(error) {
+ // overlayers schema
+ $UI.message.addError('Loading heatmap Overlayers is Error');
+ console.error(error);
+ });
+ }
+
+ // segmentation
+ function loadingComputerOverlayers() {
+ $CAMIC.store.findMarkTypes($D.params.slideId, 'computer').then(function(layers) {
+ // convert part not nesscary
+ $D.computerlayers=[...layers.map(covertToCumputerLayer)];
+ // add data and create ui item
+ addComputerLayerItems();
+ }).catch(function(error) {
+ $UI.message.addError('Loading Computer Layers is Error');
+ console.error(error);
+ });
+ }
+ var checkCoreIsReady = setInterval(function() {
+ if ($UI.layersViewer && $UI.layersViewerMinor) {
+ clearInterval(checkCoreIsReady);
+ loadingHumanOverlayers();
+ loadingRulerOverlayers();
+ loadingHeatmapOverlayers();
+ loadingComputerOverlayers();
+ }
+ }, 500);
+}
+
+
diff --git a/apps/mini/init.js b/apps/mini/init.js
new file mode 100644
index 000000000..7dbd46172
--- /dev/null
+++ b/apps/mini/init.js
@@ -0,0 +1,959 @@
+// CAMIC is an instance of camicroscope core
+// $CAMIC in there
+let $CAMIC = null;
+let tracker;
+let $minorCAMIC = null;
+// for all instances of UI components
+const $UI = new Map();
+
+const $D = {
+ pages: {
+ home: '../table.html',
+ table: '../table.html',
+ },
+ params: null, // parameter from url - slide Id and status in it (object).
+ overlayers: null, // array for each layers
+ templates: null, // json schema for prue-form
+ segments: [],
+};
+
+window.addEventListener('keydown', (e) => {
+ if (!$CAMIC || !$CAMIC.viewer) return;
+ const key = e.key;
+ // escape key to close all operations
+ if ('escape' == key.toLocaleLowerCase()) {
+ magnifierOff();
+ measurementOff();
+ annotationOff();
+ presetLabelOff();
+ }
+
+ // open annotation (ctrl + a)
+ if (e.ctrlKey && 'a' == key.toLocaleLowerCase() && $CAMIC.viewer.canvasDrawInstance) {
+ const li = $UI.toolbar.getSubTool('annotation');
+ eventFire(li, 'click');
+ return;
+ }
+ // open magnifier (ctrl + m)
+ if (e.ctrlKey && 'm' == key.toLocaleLowerCase() && $UI.spyglass) {
+ const li = $UI.toolbar.getSubTool('magnifier');
+ const chk = li.querySelector('input[type=checkbox]');
+ chk.checked = !chk.checked;
+ eventFire(chk, 'change');
+ return;
+ }
+ // open measurement (ctrl + r)
+ if (e.ctrlKey && 'r' == key.toLocaleLowerCase() && $CAMIC.viewer.measureInstance) {
+ e.preventDefault();
+ const li = $UI.toolbar.getSubTool('measurement');
+ const chk = li.querySelector('input[type=checkbox]');
+ chk.checked = !chk.checked;
+ eventFire(chk, 'change');
+ return;
+ }
+ // open side-by-side (ctrl + s)
+ if (e.ctrlKey && 's' == key.toLocaleLowerCase()) {
+ e.preventDefault();
+ const li = $UI.toolbar.getSubTool('sbsviewer');
+ const chk = li.querySelector('input[type=checkbox]');
+ chk.checked = !chk.checked;
+ eventFire(chk, 'click');
+ return;
+ }
+ // open side-by-side (ctrl + l)
+ if (e.ctrlKey && 'l' == key.toLocaleLowerCase()) {
+ e.preventDefault();
+ const li = $UI.toolbar.getSubTool('preset_label');
+ const chk = li.querySelector('input[type=checkbox]');
+ chk.checked = !chk.checked;
+ eventFire(chk, 'click');
+ return;
+ }
+
+ // shortcuts for preset labels
+ if ($D.labels &&
+ $D.labels.configuration &&
+ Array.isArray($D.labels.configuration) &&
+ $D.labels.configuration.length > 0 &&
+ e.ctrlKey) {
+ e.key;
+ const elt = $UI.labelsViewer.allLabels.find((l)=>l.dataset.key&&l.dataset.key.toLowerCase()==e.key.toLowerCase());
+ if (elt) {
+ $UI.toolbar
+ .getSubTool('preset_label')
+ .querySelector('input[type=checkbox]').checked = true;
+ $UI.labelsViewer.selectLabel(elt);
+ }
+ }
+});
+
+// initialize viewer page
+function initialize() {
+ var checkPackageIsReady = setInterval(function() {
+ if (IsPackageLoading) {
+ clearInterval(checkPackageIsReady);
+ // create a viewer and set up
+ initCore();
+
+ // loading the form template data
+ FormTempaltesLoader();
+
+ // loading the overlayers data
+ layersLoader();
+ }
+ }, 100);
+}
+
+// setting core functionalities
+function initCore() {
+ // start initial
+
+ // create the message queue
+ $UI.message = new MessageQueue({position: 'bottom-left'});
+
+ // zoom info and mmp
+ const opt = {
+ draw: {
+ // extend context menu btn group
+ btns: [
+ {
+ // annotation
+ type: 'btn',
+ title: 'Annotation',
+ class: 'material-icons',
+ text: 'description',
+ callback: saveAnnotation,
+ },
+ {
+ // analytics
+ type: 'btn',
+ title: 'Analytics',
+ class: 'material-icons',
+ text: 'settings_backup_restore',
+ callback: saveAnalytics,
+ },
+ ],
+ },
+ };
+ // set states if exist
+ if ($D.params.states) {
+ opt.states = $D.params.states;
+ }
+ // pathdb home directly
+ if ($D.params.mode == 'pathdb') {
+ $D.pages.home = '../../../';
+ $D.pages.table = '../../../';
+ }
+
+ try {
+ const slideQuery = {};
+ slideQuery.id = $D.params.slideId;
+ slideQuery.name = $D.params.slide;
+ slideQuery.location = $D.params.location;
+ opt.addRulerCallback = onAddRuler;
+ opt.deleteRulerCallback = onDeleteRuler;
+ $CAMIC = new CaMic('main_viewer', slideQuery, opt);
+ } catch (error) {
+ Loading.close();
+ $UI.message.addError('Core Initialization Failed');
+ console.error(error);
+ return;
+ }
+
+ $CAMIC.loadImg(function(e) {
+ $CAMIC.viewer.addHandler('open-failed', function(e){
+ console.error(e.message, e)
+ redirect($D.pages.table, e.message, 5);
+ })
+ // image loaded
+ if (e.hasError) {
+ // if this is a retry, assume normal behavior (one retry per slide)
+ if ($D.params.retry) {
+ $UI.message.addError(e.message);
+ // can't reach Slide and return to home page
+ if (e.isServiceError) redirect($D.pages.table, e.message, 1);
+ } else {
+ // If this is our first attempt, try one more time.
+ let params = new URLSearchParams(window.location.search);
+ params.set('retry', '1');
+ window.location.search = params.toString();
+ }
+ } else {
+ $D.params.data = e;
+ // popup panel
+ $CAMIC.viewer.addHandler('canvas-lay-click', function(e) {
+ if (!e.data) {
+ $UI.annotPopup.close();
+ return;
+ }
+ // for support QUIP 2.0
+ const data = Array.isArray(e.data) ? e.data[e.data.selected] : e.data;
+
+ const type = data.provenance.analysis.source;
+ let body;
+ let attributes;
+ let warning = null;
+ switch (type) {
+ case 'human':
+ let area;
+ let circumference;
+ if (data.geometries) {
+ if (
+ (data.selected != null || data.selected != undefined) &&
+ data.geometries.features[data.selected] &&
+ data.geometries.features[data.selected].properties.area
+ ) {
+ area = `${Math.round(
+ data.geometries.features[data.selected].properties.area,
+ )} μm²`;
+ }
+ if (
+ (data.selected != null || data.selected != undefined) &&
+ data.geometries.features[data.selected] &&
+ data.geometries.features[data.selected].properties.circumference
+ ) {
+ circumference = `${Math.round(
+ data.geometries.features[data.selected].properties
+ .circumference,
+ )} μm`;
+ }
+ } // othereise, don't try to calculate area and circumference
+ // human
+
+ attributes = data.properties.annotations;
+ if (area) attributes.area = area;
+ if (circumference) attributes.circumference = circumference;
+ body = convertHumanAnnotationToPopupBody(attributes);
+ if (
+ data.geometries &&
+ data.geometries.features[data.selected].properties.isIntersect
+ ) {
+ warning = `