LT-275: Creating measure flow component common section
This commit is contained in:
1 parent
9a8eaff560
commit
bbb7dad905
60 files changed
+391
-156
No files matched your search
@@ -8,50 +8,63 @@ $gray4 = #C0C0C0
|
||||
$gray5 = #9B9B9B
|
||||
$gray6 = #303030
|
||||
|
||||
.select-tree
|
||||
background-color: white
|
||||
.select-tree-root
|
||||
|
||||
&, a.tree-back, .tree-breadcrumb span, .tree-node, .tree-leaf
|
||||
transition(all 0.3s ease)
|
||||
.tree-content
|
||||
background-color: white
|
||||
position: relative
|
||||
|
||||
&
|
||||
.tree-search
|
||||
a.tree-back
|
||||
.tree-breadcrumb span
|
||||
.tree-node
|
||||
.tree-leaf
|
||||
transition(all 0.3s ease)
|
||||
|
||||
&.selected
|
||||
|
||||
label.tree-leaf.active
|
||||
box-shadow: 0 0 0 10px white, inset 0 0 0 200px white
|
||||
|
||||
.tree-content
|
||||
background-color: transparent
|
||||
|
||||
&>.tree-content
|
||||
border-color: transparent
|
||||
border-radius: 0
|
||||
|
||||
.tree-search
|
||||
opacity: 0
|
||||
|
||||
&, .select-tree
|
||||
|
||||
&:not(.open)>.tree-content
|
||||
|
||||
&>.tree-inputs
|
||||
&>.tree-breadcrumb
|
||||
display: none
|
||||
|
||||
&>.tree-content>.tree-options
|
||||
|
||||
&>.tree-inputs>label:not(.active)
|
||||
&>.tree-breadcrumb a
|
||||
&>.tree-breadcrumb span
|
||||
color: transparent
|
||||
|
||||
&>.tree-inputs>label.tree-node:not(.active)
|
||||
border-color: transparent
|
||||
|
||||
.select-tree-root
|
||||
&>*:first-child
|
||||
transition(all 0.3s ease)
|
||||
|
||||
.select-tree-root.selected
|
||||
border-color: transparent
|
||||
border-radius: 0
|
||||
// height: 26px
|
||||
|
||||
&, .select-tree
|
||||
background-color: transparent
|
||||
|
||||
&:not(.open)>.tree-options
|
||||
&>.tree-inputs, &>.tree-breadcrumb
|
||||
display: none
|
||||
|
||||
&.open>.tree-options
|
||||
&>.tree-inputs>label:not(.active), &>.tree-breadcrumb a, &>.tree-breadcrumb span
|
||||
color: transparent
|
||||
&>.tree-inputs>label.tree-node:not(.active)
|
||||
border-color: transparent
|
||||
|
||||
.tree-search
|
||||
opacity: 0
|
||||
|
||||
&>.tree-options
|
||||
background-color: transparent
|
||||
|
||||
label.tree-leaf.active
|
||||
box-shadow: 0 0 0 10px white, inset 0 0 0 200px white
|
||||
|
||||
.select-tree-root
|
||||
border: 1px solid $gray3
|
||||
border-radius: 5px
|
||||
display: inline-block
|
||||
overflow: hidden
|
||||
position: relative
|
||||
|
||||
&>.tree-options
|
||||
&>.tree-content
|
||||
border: 1px solid $gray3
|
||||
border-radius: 5px
|
||||
overflow: hidden
|
||||
|
||||
&>.tree-content>.tree-options
|
||||
transform(scale(1))
|
||||
transition(height 0.3s ease)
|
||||
|
||||
@@ -89,10 +102,16 @@ $gray6 = #303030
|
||||
|
||||
.select-tree-node
|
||||
left: 0
|
||||
overflow: hidden
|
||||
position: fixed
|
||||
width: 100%
|
||||
z-index: 2
|
||||
|
||||
&
|
||||
.tree-content
|
||||
.tree-inputs
|
||||
height: 100%
|
||||
|
||||
.tree-options
|
||||
overflow: hidden
|
||||
position: relative
|
||||
@@ -129,5 +148,87 @@ $gray6 = #303030
|
||||
transition(box-shadow 0.3s ease)
|
||||
z-index: 0
|
||||
|
||||
&:last-child:after
|
||||
display: block
|
||||
content: ''
|
||||
height: 10px
|
||||
|
||||
&.collapsed
|
||||
z-index: 2
|
||||
z-index: 1
|
||||
|
||||
.select-tree-common
|
||||
height: 100%
|
||||
overflow: hidden
|
||||
padding-left: 6px
|
||||
position: absolute
|
||||
right: -100%
|
||||
top: 0
|
||||
width: 100%
|
||||
|
||||
.content
|
||||
background-color: $gray6
|
||||
border: 1px solid $gray5
|
||||
border-radius: 5px
|
||||
color: white
|
||||
opacity: 0.9
|
||||
padding: 5px 12px 12px
|
||||
position: absolute
|
||||
top: 50%
|
||||
transform(translateY(-50%))
|
||||
width: calc(100% - 6px)
|
||||
|
||||
h5.title
|
||||
color: $gray5
|
||||
font-size: 12px
|
||||
font-weight: normal
|
||||
line-height: 20px
|
||||
margin: 0
|
||||
|
||||
.select-tree-root
|
||||
|
||||
&>.tree-content
|
||||
transform(scale(0))
|
||||
transform-origin(100% 50%)
|
||||
transition(all 0.3s ease)
|
||||
|
||||
.select-tree-common .content
|
||||
margin-left: calc(-100% - 6px)
|
||||
transition(all 0.3s ease 0.3s)
|
||||
|
||||
&.started
|
||||
|
||||
&>.tree-content
|
||||
transform(scale(1))
|
||||
|
||||
.select-tree-common .content
|
||||
margin-left: 0
|
||||
|
||||
&.interacted
|
||||
|
||||
.select-tree-common
|
||||
overflow: visible
|
||||
|
||||
.content
|
||||
animation-name: selectTreeCommonCloseLeft
|
||||
animation-duration: 0.3s
|
||||
animation-iteration-count: 1
|
||||
animation-direction: alternate
|
||||
animation-timing-function: ease-out
|
||||
animation-fill-mode: forwards
|
||||
|
||||
@keyframes selectTreeCommonCloseLeft {
|
||||
from {
|
||||
height: 37px
|
||||
display: table
|
||||
margin-left: 0
|
||||
opacity: 1
|
||||
visibility: visible
|
||||
}
|
||||
to {
|
||||
height: 100%
|
||||
margin-left: calc(-100% - 6px)
|
||||
opacity: 0
|
||||
visibility: hidden
|
||||
width: calc(100% - 6px)
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,93 @@
|
||||
<template name="selectTree">
|
||||
{{#group (extend this
|
||||
class=(concat
|
||||
'select-tree '
|
||||
(valueIf this.root '' 'select-tree-root ')
|
||||
this.class
|
||||
)
|
||||
mixins=(concat 'selectTree ' this.mixins)
|
||||
)}}
|
||||
{{>UI.contentBlock}}
|
||||
<div class="tree-content">
|
||||
{{#let currentNode=this.currentNode.get}}
|
||||
{{#if (and (not this.root) (ne this.search false))}}
|
||||
{{>inputText
|
||||
label=this.label
|
||||
labelClass='tree-search'
|
||||
placeholder=(choose this.searchPlaceholder 'Search')
|
||||
}}
|
||||
{{/if}}
|
||||
<div class="tree-options {{#if currentNode}}collapsed{{/if}}">
|
||||
{{#if this.root}}
|
||||
{{>selectTreeBreadcrumb component=this.component}}
|
||||
{{/if}}
|
||||
<div class="tree-inputs">
|
||||
{{#each item in (reactive this.items)}}
|
||||
{{>inputRadio
|
||||
class=this.radioClass
|
||||
name=this.key
|
||||
value=item.value
|
||||
label=item.label
|
||||
labelClass=(valueIf (isArray item.items) 'tree-node' 'tree-leaf')
|
||||
checked=(eq item.value (reactive this.value))
|
||||
}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#if (and currentNode (isArray currentNode.items))}}
|
||||
{{>selectTree (clone this
|
||||
items=currentNode.items
|
||||
root=(choose this.root this.component)
|
||||
class='select-tree-node'
|
||||
)}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/let}}
|
||||
</div>
|
||||
{{#unless this.root}}
|
||||
{{>selectTreeCommon this}}
|
||||
{{/unless}}
|
||||
{{/group}}
|
||||
</template>
|
||||
|
||||
<template name="selectTreeCommon">
|
||||
<div class="select-tree-common">
|
||||
<div class="content">
|
||||
<h5 class="title">Common</h5>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="selectTreeBreadcrumb">
|
||||
<div class="tree-breadcrumb clearfix">
|
||||
{{>selectTreeBreadcrumbParent
|
||||
component=this.component.parent
|
||||
index=1
|
||||
}}
|
||||
{{#let currentNode=this.component.parent.templateInstance.data.currentNode.get}}
|
||||
<span class="tree-current-node">{{currentNode.label}}</span>
|
||||
{{/let}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="selectTreeBreadcrumbParent">
|
||||
{{#let parent=this.component.parent}}
|
||||
{{#let parentNode=(reactive parent.templateInstance.data.currentNode)}}
|
||||
{{#if parentNode}}
|
||||
{{>selectTreeBreadcrumbParent
|
||||
component=parent
|
||||
index=(sum this.index 1)
|
||||
}}
|
||||
{{/if}}
|
||||
<span class="path-link">
|
||||
<a href="#" class="tree-back" data-index="{{this.index}}">
|
||||
{{#if parentNode}}
|
||||
<span>{{parentNode.label}}</span>
|
||||
{{else}}
|
||||
<i class="fa fa-fast-backward"></i>
|
||||
{{/if}}
|
||||
</a>
|
||||
{{#if parentNode}}<span>/</span>{{/if}}
|
||||
</span>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
</template>
|
||||
+13
-13
@@ -4,16 +4,20 @@ import { _ } from 'meteor/underscore';
|
||||
import { $ } from 'meteor/jquery';
|
||||
|
||||
// TODO: use npm dependency
|
||||
import transition from 'meteor/ohif:core/lib/third-party/transition-to-from-auto';
|
||||
import transition from 'meteor/ohif:core/client/lib/third-party/transition-to-from-auto';
|
||||
|
||||
Template.selectTree.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
const component = instance.$('.select-tree:first').data('component');
|
||||
const rootComponent = instance.data.root || component;
|
||||
const rootInstance = rootComponent.templateInstance;
|
||||
const $treeRoot = rootInstance.$('.select-tree-root:first').first();
|
||||
|
||||
instance.component = component;
|
||||
|
||||
// Start the component transitions
|
||||
$treeRoot.addClass('started');
|
||||
|
||||
// Update the component's viewport height
|
||||
instance.updateHeight = () => {
|
||||
const height = rootInstance.$('.tree-options:last').data('height');
|
||||
@@ -28,18 +32,9 @@ Template.selectTree.onRendered(() => {
|
||||
|
||||
// Put the component in selected state
|
||||
instance.setSelected = (flag) => {
|
||||
const $treeRoot = rootInstance.$('.select-tree-root:first').first();
|
||||
const $firstChild = $treeRoot.children().first();
|
||||
if (flag) {
|
||||
const search = rootInstance.$('.tree-search').outerHeight() | 0;
|
||||
const leaf = $treeRoot.find('.tree-leaf.active').position().top;
|
||||
const martinTop = search + leaf;
|
||||
// $firstChild.css('margin-top', -martinTop);
|
||||
// $treeRoot.css('margin-top', martinTop).addClass('selected');
|
||||
$treeRoot.addClass('selected');
|
||||
} else {
|
||||
// $treeRoot.removeClass('selected').css('margin-top', '');
|
||||
// $firstChild.css('margin-top', '');
|
||||
$treeRoot.removeClass('selected');
|
||||
}
|
||||
};
|
||||
@@ -60,7 +55,7 @@ Template.selectTree.onRendered(() => {
|
||||
});
|
||||
});
|
||||
|
||||
const selector = '.select-tree:first>.tree-options>.tree-breadcrumb .path-link';
|
||||
const selector = '.select-tree:first>.tree-content>.tree-options>.tree-breadcrumb .path-link';
|
||||
instance.$(selector).css('width', 0).each((index, element) => {
|
||||
transition({
|
||||
element: element,
|
||||
@@ -72,7 +67,12 @@ Template.selectTree.onRendered(() => {
|
||||
});
|
||||
|
||||
Template.selectTree.events({
|
||||
'change .select-tree:first>.tree-options>.tree-inputs>label>input'(event, instance) {
|
||||
'click .select-tree-root'(event, instance) {
|
||||
// Detect the first interaction with the component and do the animation
|
||||
$(event.currentTarget).addClass('interacted');
|
||||
},
|
||||
|
||||
'change .select-tree:first>.tree-content>.tree-options>.tree-inputs>label>input'(event, instance) {
|
||||
const component = instance.component;
|
||||
const $target = $(event.target);
|
||||
const $label = $target.closest('label');
|
||||
@@ -111,7 +111,7 @@ Template.selectTree.events({
|
||||
}
|
||||
},
|
||||
|
||||
'click .select-tree:first>.tree-options>.tree-breadcrumb .tree-back'(event, instance) {
|
||||
'click .select-tree:first>.tree-content>.tree-options>.tree-breadcrumb .tree-back'(event, instance) {
|
||||
const rootComponent = instance.data.root || instance.component;
|
||||
const rootInstance = rootComponent.templateInstance;
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,6 @@
|
||||
import './lib';
|
||||
import './components';
|
||||
import './helpers';
|
||||
import './ui';
|
||||
|
||||
import './routes.js';
|
||||
File renamed without changes.
@@ -1,2 +1,3 @@
|
||||
import './blaze.js';
|
||||
import './string.js';
|
||||
import './user.js';
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,32 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
OHIF.user = {};
|
||||
|
||||
// Throw error if there is no user logged in
|
||||
OHIF.user.validate = () => {
|
||||
if (!Meteor.userId()) {
|
||||
throw new Meteor.Error('not-authorized');
|
||||
}
|
||||
};
|
||||
|
||||
// Get the persistent data by key
|
||||
OHIF.user.getData = key => {
|
||||
// Check if there is an user logged in
|
||||
OHIF.user.validate();
|
||||
|
||||
// Get the user persistent data
|
||||
const data = Meteor.user().profile.persistent;
|
||||
|
||||
if (data) {
|
||||
return data[key];
|
||||
}
|
||||
};
|
||||
|
||||
// Store the persistent data by giving a key and a value to store
|
||||
OHIF.user.setData = (key, value) => {
|
||||
// Check if there is an user logged in
|
||||
OHIF.user.validate();
|
||||
|
||||
// Call the update method on server-side
|
||||
Meteor.call('userDataSet', key, value);
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Router } from 'meteor/clinical:router';
|
||||
|
||||
Router.route('/playground', function() {
|
||||
this.render('componentPlayground');
|
||||
});
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,80 +0,0 @@
|
||||
<template name="selectTree">
|
||||
{{#group (extend this
|
||||
class=(concat
|
||||
'select-tree '
|
||||
(valueIf this.root '' 'select-tree-root ')
|
||||
this.class
|
||||
)
|
||||
mixins=(concat 'selectTree ' this.mixins)
|
||||
)}}
|
||||
{{>UI.contentBlock}}
|
||||
{{#let currentNode=this.currentNode.get}}
|
||||
{{#if (and (not this.root) (ne this.search false))}}
|
||||
{{>inputText
|
||||
label=this.label
|
||||
labelClass='tree-search'
|
||||
placeholder=(choose this.searchPlaceholder 'Search')
|
||||
}}
|
||||
{{/if}}
|
||||
<div class="tree-options {{#if currentNode}}collapsed{{/if}}">
|
||||
{{#if this.root}}
|
||||
{{>selectTreeBreadcrumb component=this.component}}
|
||||
{{/if}}
|
||||
<div class="tree-inputs">
|
||||
{{#each item in (reactive this.items)}}
|
||||
{{>inputRadio
|
||||
class=this.radioClass
|
||||
name=this.key
|
||||
value=item.value
|
||||
label=item.label
|
||||
labelClass=(valueIf (isArray item.items) 'tree-node' 'tree-leaf')
|
||||
checked=(eq item.value (reactive this.value))
|
||||
}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#if (and currentNode (isArray currentNode.items))}}
|
||||
{{>selectTree (clone this
|
||||
items=currentNode.items
|
||||
root=(choose this.root this.component)
|
||||
class='select-tree-node'
|
||||
)}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/let}}
|
||||
{{/group}}
|
||||
</template>
|
||||
|
||||
<template name="selectTreeBreadcrumb">
|
||||
<div class="tree-breadcrumb clearfix">
|
||||
{{>selectTreeBreadcrumbParent
|
||||
component=this.component.parent
|
||||
index=1
|
||||
}}
|
||||
{{#let currentNode=this.component.parent.templateInstance.data.currentNode.get}}
|
||||
<span class="tree-current-node">{{currentNode.label}}</span>
|
||||
{{/let}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="selectTreeBreadcrumbParent">
|
||||
{{#let parent=this.component.parent}}
|
||||
{{#let parentNode=(reactive parent.templateInstance.data.currentNode)}}
|
||||
{{#if parentNode}}
|
||||
{{>selectTreeBreadcrumbParent
|
||||
component=parent
|
||||
index=(sum this.index 1)
|
||||
}}
|
||||
{{/if}}
|
||||
<span class="path-link">
|
||||
<a href="#" class="tree-back" data-index="{{this.index}}">
|
||||
{{#if parentNode}}
|
||||
<span>{{parentNode.label}}</span>
|
||||
{{else}}
|
||||
<i class="fa fa-fast-backward"></i>
|
||||
{{/if}}
|
||||
</a>
|
||||
{{#if parentNode}}<span>/</span>{{/if}}
|
||||
</span>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
</template>
|
||||
@@ -1,13 +1,12 @@
|
||||
export { OHIF } from './ohif.js';
|
||||
/*
|
||||
* Defines the base OHIF object
|
||||
*/
|
||||
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Router } from 'meteor/clinical:router';
|
||||
const OHIF = {};
|
||||
|
||||
import './lib';
|
||||
import './components';
|
||||
import './helpers';
|
||||
import './ui';
|
||||
// Expose the OHIF object to the client if it is on development mode
|
||||
if (Meteor.isDevelopment && Meteor.isClient) {
|
||||
window.OHIF = OHIF;
|
||||
}
|
||||
|
||||
Router.route('/playground', function() {
|
||||
this.render('componentPlayground');
|
||||
});
|
||||
export { OHIF };
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Defines the base OHIF object
|
||||
*/
|
||||
|
||||
const OHIF = {};
|
||||
|
||||
if (Meteor.isDevelopment) {
|
||||
window.OHIF = OHIF;
|
||||
}
|
||||
|
||||
export { OHIF };
|
||||
@@ -23,8 +23,15 @@ Package.onUse(function(api) {
|
||||
|
||||
// UI Styles
|
||||
api.addFiles([
|
||||
'ui/resizable/resizable.styl'
|
||||
'client/ui/resizable/resizable.styl'
|
||||
], 'client');
|
||||
|
||||
api.mainModule('main.js', 'client');
|
||||
api.mainModule('main.js', ['client', 'server']);
|
||||
|
||||
// Client imports and routes
|
||||
api.addFiles('client/index.js', 'client');
|
||||
|
||||
// Server imports and methods
|
||||
api.addFiles('server/index.js', 'server');
|
||||
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
import './mongo.js';
|
||||
import './user.js';
|
||||
@@ -0,0 +1,26 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
// Mongo data manipulation utilities
|
||||
class MongoUtils {
|
||||
|
||||
// Check if there is an user logged in
|
||||
static validateUser() {
|
||||
// Throw error if there is no user logged in
|
||||
if (!Meteor.userId()) {
|
||||
throw new Meteor.Error('not-authorized');
|
||||
}
|
||||
}
|
||||
|
||||
// Generic callback to MongoDB write operations
|
||||
static writeCallback(error, affected) {
|
||||
// Throw error if it was not possible to complete the write operation
|
||||
if (error) {
|
||||
throw new Meteor.Error('data-write', error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Expose the class in the OHIF object
|
||||
OHIF.MongoUtils = MongoUtils;
|
||||
@@ -0,0 +1,54 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
// Manipulate user's persistent data
|
||||
class UserData {
|
||||
|
||||
// Get the persistent data by key
|
||||
static get(key) {
|
||||
// Check if there is an user logged in
|
||||
OHIF.MongoUtils.validateUser();
|
||||
|
||||
// Get the user's profile data
|
||||
const profileData = Meteor.user().profile;
|
||||
|
||||
// Return the data if it is set
|
||||
if (profileData.persistent) {
|
||||
return profileData.persistent[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Store the persistent data by giving a key and a value to store
|
||||
static set(key, value) {
|
||||
// Check if there is an user logged in
|
||||
OHIF.MongoUtils.validateUser();
|
||||
|
||||
// Build the query to update only the current user's data
|
||||
var query = {
|
||||
_id: Meteor.userId()
|
||||
};
|
||||
|
||||
// Build the path to the persistent data with the given key
|
||||
const persistentPath = `profile.persistent.${key}`;
|
||||
|
||||
// Build the data to be updated
|
||||
var data = {
|
||||
$set: {
|
||||
[persistentPath]: value
|
||||
}
|
||||
};
|
||||
|
||||
// Update the user's profile data with the persistent information
|
||||
Accounts.users.update(query, data, OHIF.MongoUtils.writeCallback);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Register the methods
|
||||
Meteor.methods({
|
||||
userDataGet: key => UserData.get(key),
|
||||
userDataSet: (key, value) => UserData.set(key, value)
|
||||
});
|
||||
|
||||
// Expose the class in the OHIF object
|
||||
OHIF.UserData = UserData;
|
||||
Reference in new issue
Block a user