Creating a generic UI error handling mechanism
This commit is contained in:
parent
3c1e4c51cd
commit
798b197d4a
@ -55,3 +55,7 @@ Template.section.onCreated(() => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Template.registerHelper('hasSection', sectionName => {
|
||||||
|
return !!OHIF.blaze.getSectionContent(Template.instance().view, sectionName);
|
||||||
|
});
|
||||||
|
|||||||
@ -4,9 +4,23 @@
|
|||||||
{{#form class=(concat 'modal-content ' this.formClass) hideValidationBox=true
|
{{#form class=(concat 'modal-content ' this.formClass) hideValidationBox=true
|
||||||
api=(extend instance.api instance.data.api) schema=this.schema
|
api=(extend instance.api instance.data.api) schema=this.schema
|
||||||
}}
|
}}
|
||||||
|
{{#if or this.title (hasSection 'dialogHeader')}}
|
||||||
{{>dialogHeader this}}
|
{{>dialogHeader this}}
|
||||||
|
{{/if}}
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
{{this.bodyText}}
|
<div class="messages">
|
||||||
|
{{#each message in this.messages}}
|
||||||
|
<div class="message">{{{message}}}</div>
|
||||||
|
{{else}}
|
||||||
|
{{#if isError}}
|
||||||
|
{{>pageError (extend this error=this.details)}}
|
||||||
|
{{else}}
|
||||||
|
{{#let message=(choose this.bodyText this.reason this.message 'An error has ocurred.')}}
|
||||||
|
<div class="message">{{message}}</div>
|
||||||
|
{{/let}}
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
{{>UI.contentBlock}}
|
{{>UI.contentBlock}}
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|||||||
@ -105,3 +105,10 @@ Template.dialogForm.events({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Template.dialogForm.helpers({
|
||||||
|
isError() {
|
||||||
|
const data = Template.instance().data;
|
||||||
|
return data instanceof Error || (data && data.error instanceof Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template name="dialogHeader">
|
<template name="dialogHeader">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
{{>section 'dialogHeader'}}
|
{{>section 'dialogHeader'}}
|
||||||
{{#if this.title}}
|
{{#if or this.title (hasSection 'dialogHeader')}}
|
||||||
{{#button class='close' action='cancel'
|
{{#button class='close' action='cancel'
|
||||||
tagAttributes=(extend this.tagAttributes
|
tagAttributes=(extend this.tagAttributes
|
||||||
data-dismiss='modal' aria-label='Close'
|
data-dismiss='modal' aria-label='Close'
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
{{#each message in this.messages}}
|
{{#each message in this.messages}}
|
||||||
<div class="message">{{{message}}}</div>
|
<div class="message">{{{message}}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if eq this.errorType 'Meteor.Error'}}
|
{{#if isError}}
|
||||||
{{>pageError (extend this error=this.details)}}
|
{{>pageError (extend this error=this.details)}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#let message=(choose this.reason this.message 'An error has ocurred.')}}
|
{{#let message=(choose this.reason this.message 'An error has ocurred.')}}
|
||||||
|
|||||||
@ -7,3 +7,10 @@ Template.dialogInfo.onRendered(() => {
|
|||||||
|
|
||||||
$modal.one('hidden.bs.modal', () => instance.data.promiseResolve());
|
$modal.one('hidden.bs.modal', () => instance.data.promiseResolve());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Template.dialogInfo.helpers({
|
||||||
|
isError() {
|
||||||
|
const data = Template.instance().data;
|
||||||
|
return data instanceof Error || (data && data.error instanceof Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
33
Packages/ohif-core/client/ui/handleError.js
Normal file
33
Packages/ohif-core/client/ui/handleError.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
OHIF.ui.handleError = error => {
|
||||||
|
let { title, message } = error;
|
||||||
|
|
||||||
|
if (!title) {
|
||||||
|
if (error instanceof Meteor.Error) {
|
||||||
|
title = error.error;
|
||||||
|
} else if (error instanceof Error) {
|
||||||
|
title = error.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!message) {
|
||||||
|
if (error instanceof Meteor.Error) {
|
||||||
|
message = error.reason;
|
||||||
|
} else if (error instanceof Error) {
|
||||||
|
message = error.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = Object.assign({
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
class: 'themed',
|
||||||
|
hideConfirm: true,
|
||||||
|
cancelLabel: 'Dismiss',
|
||||||
|
cancelClass: 'btn-secondary'
|
||||||
|
}, error || {});
|
||||||
|
|
||||||
|
OHIF.ui.showDialog('dialogForm', data);
|
||||||
|
};
|
||||||
@ -10,4 +10,5 @@ import './notifications/notifications.js';
|
|||||||
import './popover/display.js';
|
import './popover/display.js';
|
||||||
import './resizable/resizable.js';
|
import './resizable/resizable.js';
|
||||||
import './unsavedChanges/unsavedChanges.js';
|
import './unsavedChanges/unsavedChanges.js';
|
||||||
|
import './handleError.js';
|
||||||
import './styleProperty.js';
|
import './styleProperty.js';
|
||||||
|
|||||||
@ -81,7 +81,7 @@ export class HotkeysManager {
|
|||||||
load(contextName) {
|
load(contextName) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const context = this.getContext(contextName);
|
const context = this.getContext(contextName);
|
||||||
if (!context) return;
|
if (!context) return reject();
|
||||||
this.retrieve(contextName).then(defs => {
|
this.retrieve(contextName).then(defs => {
|
||||||
const definitions = defs || this.defaults[contextName];
|
const definitions = defs || this.defaults[contextName];
|
||||||
if (!definitions) {
|
if (!definitions) {
|
||||||
@ -151,6 +151,6 @@ export class HotkeysManager {
|
|||||||
|
|
||||||
this.currentContextName = contextName;
|
this.currentContextName = contextName;
|
||||||
newContext.initialize();
|
newContext.initialize();
|
||||||
this.load(contextName);
|
this.load(contextName).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,8 @@ $circleSize = 26px
|
|||||||
.radialProgress
|
.radialProgress
|
||||||
border-radius: 100%
|
border-radius: 100%
|
||||||
height: $circleSize
|
height: $circleSize
|
||||||
margin-top: 8px
|
margin-top: 3px
|
||||||
|
margin-right: 4px
|
||||||
position: relative
|
position: relative
|
||||||
vendorize(box-shadow, 0 0 1em black)
|
vendorize(box-shadow, 0 0 1em black)
|
||||||
width: $circleSize
|
width: $circleSize
|
||||||
|
|||||||
@ -6,5 +6,6 @@ import './longitudinalStudyListStudy/longitudinalStudyListStudy.js';
|
|||||||
import './longitudinalViewportOverlay/imageViewportIcons.html';
|
import './longitudinalViewportOverlay/imageViewportIcons.html';
|
||||||
import './longitudinalViewportOverlay/longitudinalViewportOverlay.html';
|
import './longitudinalViewportOverlay/longitudinalViewportOverlay.html';
|
||||||
import './longitudinalViewportOverlay/longitudinalViewportOverlay.js';
|
import './longitudinalViewportOverlay/longitudinalViewportOverlay.js';
|
||||||
|
import './longitudinalViewportOverlay/longitudinalViewportOverlay.styl';
|
||||||
|
|
||||||
import './dropdown.js';
|
import './dropdown.js';
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<div>{{getGenderAndAge}}</div>
|
<div>{{getGenderAndAge}}</div>
|
||||||
<div class="icons-section">
|
<div class="icons-section">
|
||||||
{{#if linked}}
|
{{#if linked}}
|
||||||
<svg>
|
<svg class="icon-link">
|
||||||
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href={{absoluteUrl "packages/ohif_viewerbase/assets/icons.svg#icon-viewport-link"}}></use>
|
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href={{absoluteUrl "packages/ohif_viewerbase/assets/icons.svg#icon-viewport-link"}}></use>
|
||||||
</svg>
|
</svg>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -18,7 +18,7 @@
|
|||||||
<div>{{seriesDescription}}</div>
|
<div>{{seriesDescription}}</div>
|
||||||
<div>{{studyInfo 'AccessionNumber'}}</div>
|
<div>{{studyInfo 'AccessionNumber'}}</div>
|
||||||
<div>{{formatDA (studyInfo 'AcquisitionDate')}} {{formatTM (studyInfo 'AcquisitionTime')}}</div>
|
<div>{{formatDA (studyInfo 'AcquisitionDate')}} {{formatTM (studyInfo 'AcquisitionTime')}}</div>
|
||||||
<div>{{#if seriesNumber}}S: {{seriesNumber}}{{#if gt numImages 1}},{{/if}} {{/if}}{{#if gt instanceNumber 0}}I: {{instanceNumber}} {{/if}}{{#if gt numImages 1}}({{imageIndex}}/{{numImages}}){{/if}}</div>
|
<div>{{#if seriesNumber}}S: {{seriesNumber}}{{#if gt numImages 1}},{{/if}} {{/if}}{{#if gt numImages 1}}I: {{imageIndex}}/{{numImages}}{{/if}}</div>
|
||||||
<div class='timepointName'>{{timepointName}}</div>
|
<div class='timepointName'>{{timepointName}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottomright dicomTag">
|
<div class="bottomright dicomTag">
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
@require '{ohif:design}/app'
|
||||||
|
|
||||||
|
.imageViewerViewportOverlay .icons-section .icon-link
|
||||||
|
transform(translateY(3px))
|
||||||
Loading…
Reference in New Issue
Block a user