LT-275: Creating measure flow component common section
This commit is contained in:
parent
9a8eaff560
commit
bbb7dad905
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
@ -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;
|
||||
|
||||
6
Packages/ohif-core/client/index.js
Normal file
6
Packages/ohif-core/client/index.js
Normal file
@ -0,0 +1,6 @@
|
||||
import './lib';
|
||||
import './components';
|
||||
import './helpers';
|
||||
import './ui';
|
||||
|
||||
import './routes.js';
|
||||
@ -1,2 +1,3 @@
|
||||
import './blaze.js';
|
||||
import './string.js';
|
||||
import './user.js';
|
||||
32
Packages/ohif-core/client/lib/user.js
Normal file
32
Packages/ohif-core/client/lib/user.js
Normal file
@ -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);
|
||||
};
|
||||
5
Packages/ohif-core/client/routes.js
Normal file
5
Packages/ohif-core/client/routes.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { Router } from 'meteor/clinical:router';
|
||||
|
||||
Router.route('/playground', function() {
|
||||
this.render('componentPlayground');
|
||||
});
|
||||
@ -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');
|
||||
|
||||
});
|
||||
|
||||
2
Packages/ohif-core/server/index.js
Normal file
2
Packages/ohif-core/server/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
import './mongo.js';
|
||||
import './user.js';
|
||||
26
Packages/ohif-core/server/mongo.js
Normal file
26
Packages/ohif-core/server/mongo.js
Normal file
@ -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;
|
||||
54
Packages/ohif-core/server/user.js
Normal file
54
Packages/ohif-core/server/user.js
Normal file
@ -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;
|
||||
Loading…
Reference in New Issue
Block a user