Compare commits

...

44 Commits

Author SHA1 Message Date
6da0044adf update description of resync action and reduce pixel contant for drag handler 2018-04-16 14:12:27 -07:00
76a88fc1e5 major performance update to import activities from csv 2018-04-12 15:20:24 -07:00
6901684124 add actionPolicy for import action, add resync button to timeline to resync duration of timespan with imported duration 2018-04-12 12:30:57 -07:00
dbb5b9bb4c change seconds to milliseconds when importing and creatin activities 2018-04-05 10:24:47 -07:00
dce20825ea pull most current master 2018-04-05 10:09:41 -07:00
5fa9925ea1 code cleanup activity import action 2018-03-12 15:10:05 -07:00
d774458b17 fixed issue of not linking right activity modes if user provides id 2018-03-12 11:50:16 -07:00
22f464e02b fix bug where activity modes arent being linked to their activities 2018-03-12 11:30:37 -07:00
ef8f52769e add imported id support for linked activity modes 2018-03-12 11:26:53 -07:00
f25987cfed add support for imported id's 2018-03-12 10:49:57 -07:00
684dd4ff8c fix persist issue with couch and make copies, make fragments 2018-02-22 10:44:36 -08:00
a36b86516f remove activity-modes folder to prevent couch error, for now activity modes dont have a location, but activities can still point to them 2018-02-21 15:54:30 -08:00
99e103fd9d allow multiple users to import their own activities based on new folders that they import into 2018-02-21 14:25:30 -08:00
2224fba618 clean code in activityModesImportAction 2018-02-12 15:34:10 -08:00
b3fcbddeb7 fix activity modes folder error for couch 2018-02-12 15:17:41 -08:00
b3ababd67e search for existing objects with same id, before instantiating, to prevent 409 error for couchDB 2018-02-12 13:58:00 -08:00
0e3c5e1199 store properties on parent (it can be either an activity or timeline) 2018-02-06 11:00:46 -08:00
d72db1ff8c fix finding parent timeline algorithm 2018-02-05 15:29:44 -08:00
bade2e1678 Merge branch 'master' of https://github.com/nasa/openmct into activity-import 2018-02-05 12:37:54 -08:00
4bd1a192ed fix checkstyle errors, and add d3-dsv to test-main 2018-02-01 15:41:10 -08:00
89ab47d835 fix duration bug by setting duration before start and end time 2018-02-01 13:24:50 -08:00
27dfb18991 fix older timelines in new model 2018-02-01 11:42:28 -08:00
9e57a661ea set duration on move 2018-01-29 12:46:10 -08:00
116e346aaf fix gantt move bug, frag number bug 2018-01-29 12:40:41 -08:00
78cfdd3942 fragment works need to add logic to remove start and end from timeline on destroy 2018-01-27 01:28:08 -08:00
a8ecdf98b5 fix checkstyle and lint errors 2018-01-25 15:37:50 -08:00
fee74883c6 add alias to vertical split pane to persist user width preference 2018-01-25 15:27:32 -08:00
2e8e6306ee change fragment to copy
copy button working as expected
2018-01-25 13:15:42 -08:00
7f2cc89f42 working action button - fragment 2018-01-25 10:54:34 -08:00
321271bd4d fix drag malfunction" 2018-01-23 15:18:09 -08:00
006e99fb07 keep durations specific to timelines 2018-01-11 13:15:27 -08:00
63dc4b6253 store start time on timeline and use from there if changed using drag component 2018-01-11 11:54:00 -08:00
85868f690e show blocking error if file type is not csv 2018-01-08 15:30:25 -08:00
b1f34f7cd7 fix checkstyle 2018-01-08 13:54:42 -08:00
8785d9a9d7 store imported activity-modes in a folder in the import location 2018-01-08 13:50:42 -08:00
3a6e1fd301 merge latest master 2017-12-19 13:48:59 -08:00
8161e4fc89 clean code 2017-12-18 15:16:30 -08:00
abf7654027 linking imported activity modes to activities working 2017-12-18 13:05:33 -08:00
8fba707321 link imported acitivity mode to correspoding activity 2017-12-18 12:44:17 -08:00
8ad5cca936 allow instantiation of activity modes from same csv file 2017-12-18 11:28:21 -08:00
754d484501 give imported actiivities predictable ids to prevent duplication when imported again 2017-12-18 10:31:42 -08:00
74717b59c3 working import, instantiate and provide propertiess to activities 2017-12-14 10:38:20 -08:00
ffdb19787b persist csv file objects to window local storage 2017-12-11 16:19:39 -08:00
5dc0d8c7f8 Create new Root Object, add provider and create new import action. Working import from CSV. CSV being parsed to array of objects 2017-12-11 14:29:29 -08:00
19 changed files with 478 additions and 42 deletions

View File

@ -37,7 +37,8 @@
openmct.legacyRegistry.enable.bind(openmct.legacyRegistry)
);
openmct.install(openmct.plugins.MyItems());
openmct.install(openmct.plugins.LocalStorage());
// openmct.install(openmct.plugins.LocalStorage());
openmct.install(openmct.plugins.CouchDB('http://127.0.0.1:5984/openmct'));
openmct.install(openmct.plugins.Espresso());
openmct.install(openmct.plugins.Generator());
openmct.install(openmct.plugins.ExampleImagery());
@ -68,6 +69,7 @@
]
}));
openmct.install(openmct.plugins.SummaryWidget());
openmct.install(openmct.plugins.ActivityModes());
openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
openmct.time.timeSystem('utc');
openmct.start();

View File

@ -49,7 +49,8 @@ requirejs.config({
"d3-format": "node_modules/d3-format/build/d3-format.min",
"d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
"d3-time": "node_modules/d3-time/build/d3-time.min",
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min"
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min",
"d3-dsv": "node_modules/d3-dsv/build/d3-dsv.min"
},
"shim": {
"angular": {

View File

@ -8,6 +8,7 @@
"d3-collection": "1.0.x",
"d3-color": "1.0.x",
"d3-format": "1.2.x",
"d3-dsv": "^1.0.8",
"d3-interpolate": "1.1.x",
"d3-scale": "1.0.x",
"d3-selection": "1.3.x",

View File

@ -204,7 +204,10 @@ define([
"composition": [],
"start": {
"timestamp": 0
}
},
"activityStart": {},
"activityDuration": {},
"activityEnd": {}
}
},
{
@ -341,7 +344,7 @@ define([
"cssClass": "icon-plot-resource",
"description": "Graph Resource Utilization",
"control": "button",
"method": "toggleGraph"
"method": "test"
},
{
"cssClass": "icon-activity-mode",
@ -374,7 +377,36 @@ define([
"description": "Edit Properties...",
"control": "button",
"method": "properties"
},
{
"cssClass": "icon-duplicate",
"description": "Make copies of activities",
"control": "dialog-button",
"dialog": {
"control": "textfield",
"name": "Number of copies (1 to 5)",
"cssClass": "l-input-sm numeric"
},
"property": "makeCopies"
},
{
"cssClass": "icon-layers",
"description": "Fragment Activity",
"control": "dialog-button",
"dialog": {
"control": "textfield",
"name": "Number of fragments (2 to 5)",
"cssClass": "l-input-sm numeric"
},
"property": "fragment"
},
{
"cssClass": "icon-resync",
"description": "Update Duration from imported activity",
"control": "button",
"method": "updateDuration"
}
]
},
{
@ -464,7 +496,8 @@ define([
"$scope",
"$q",
"objectLoader",
"TIMELINE_MINIMUM_DURATION"
"TIMELINE_MINIMUM_DURATION",
"openmct"
]
},
{

View File

@ -23,7 +23,7 @@
ng-click="$event.stopPropagation()"
ng-controller="TimelineController as timelineController">
<mct-split-pane anchor="left" class="abs" position="pane.x">
<mct-split-pane anchor="left" class="abs" position="pane.x" alias="timelineCenter">
<!-- LEFT PANE: TABULAR AND RESOURCE LEGEND AREAS -->
<mct-split-pane anchor="bottom"
position="pane.y"

View File

@ -25,7 +25,7 @@
*/
define({
// Pixel width of start/end handles
HANDLE_WIDTH: 32,
HANDLE_WIDTH: 16,
// Pixel tolerance for snapping behavior
SNAP_WIDTH: 16
});

View File

@ -21,27 +21,56 @@
*****************************************************************************/
define(
[],
function () {
['EventEmitter'],
function (EventEmitter) {
/**
* Describes the time span of an activity object.
* @param model the activity's object model
*/
function ActivityTimespan(model, mutation) {
function ActivityTimespan(model, mutation, parent) {
var parentTimelineModel = parent.getModel(),
parentMutation = parent.getCapability('mutation');
function getTimelineActivityStart(domainObjectModel) {
if (domainObjectModel.activityStart && domainObjectModel.activityStart[model.id]) {
return domainObjectModel.activityStart[model.id];
} else {
return model.start.timestamp;
}
}
function getTimelineActivityDuration(domainObjectModel) {
if (domainObjectModel.activityDuration && domainObjectModel.activityDuration[model.id]) {
return domainObjectModel.activityDuration[model.id];
} else {
return model.duration.timestamp;
}
}
function getTimelineActivityEnd(domainObjectModel) {
if (domainObjectModel.activityEnd && domainObjectModel.activityEnd[model.id]) {
return domainObjectModel.activityEnd[model.id];
} else {
return getTimelineActivityStart(parentTimelineModel) + getTimelineActivityDuration(parentTimelineModel);
}
}
// Get the start time for this timeline
function getStart() {
return model.start.timestamp;
return getTimelineActivityStart(parentTimelineModel);
}
// Get the end time for this timeline
function getEnd() {
return model.start.timestamp + model.duration.timestamp;
return getTimelineActivityEnd(parentTimelineModel);
}
// Get the duration of this timeline
function getDuration() {
return model.duration.timestamp;
function getDuration(flag) {
if (flag === 'model') {
return model.duration.timestamp;
}
return getTimelineActivityDuration(parentTimelineModel);
}
// Get the epoch used by this timeline
@ -51,27 +80,36 @@ define(
// Set the start time associated with this object
function setStart(value) {
var end = getEnd();
mutation.mutate(function (m) {
m.start.timestamp = Math.max(value, 0);
// Update duration to keep end time
m.duration.timestamp = Math.max(end - value, 0);
}, model.modified);
parentMutation.mutate(function (m) {
if (!m.activityStart) {
m.activityStart = {};
}
m.activityStart[model.id] = Math.max(value, 0);
});
}
// Set the duration associated with this object
function setDuration(value) {
mutation.mutate(function (m) {
m.duration.timestamp = Math.max(value, 0);
}, model.modified);
parentMutation.mutate(function (m) {
if (!m.activityDuration) {
m.activityDuration = {};
}
m.activityDuration[model.id] = Math.max(value, 0);
});
}
// Set the end time associated with this object
function setEnd(value) {
var start = getStart();
mutation.mutate(function (m) {
m.duration.timestamp = Math.max(value - start, 0);
}, model.modified);
parentMutation.mutate(function (m) {
if (!m.activityEnd) {
m.activityEnd = {};
}
m.activityEnd[model.id] = Math.max(value, 0);
});
}
return {
@ -110,7 +148,15 @@ define(
* start and end times.
* @returns {string} the epoch
*/
getEpoch: getEpoch
getEpoch: getEpoch,
getModel: function () {
return model;
},
getParent: function () {
return parent;
}
};
}

View File

@ -32,11 +32,15 @@ define(
* @param {DomainObject} domainObject the Activity
*/
function ActivityTimespanCapability($q, domainObject) {
var parent = domainObject.getCapability('context').parentObject;
// Promise time span
function promiseTimeSpan() {
return $q.when(new ActivityTimespan(
domainObject.getModel(),
domainObject.getCapability('mutation')
domainObject.getCapability('mutation'),
parent
));
}

View File

@ -36,11 +36,12 @@ define(
* Controller for the Timeline view.
* @constructor
*/
function TimelineController($scope, $q, objectLoader, MINIMUM_DURATION) {
function TimelineController($scope, $q, objectLoader, MINIMUM_DURATION, openmct) {
var swimlanePopulator = new TimelineSwimlanePopulator(
objectLoader,
$scope.configuration || {},
$scope.selection
$scope.selection,
openmct
),
graphPopulator = new TimelineGraphPopulator($q),
dragPopulator = new TimelineDragPopulator(objectLoader);

View File

@ -51,7 +51,6 @@ define(
handles: function (domainObject) {
var type = domainObject.getCapability('type'),
id = domainObject.getId();
// Instantiate a handle
function instantiate(Handle) {
return new Handle(

View File

@ -115,11 +115,13 @@ define(
var timespan = timespans[toId(id)];
// Use as setter if argument is present
if ((typeof value === 'number') && timespan) {
// Set the start (ensuring that it's non-negative,
// Set the start and duration(ensuring that it's non-negative,
// and not after the end time.)
timespan.setStart(
Math.min(Math.max(value, 0), timespan.getEnd())
);
timespan.setDuration(timespan.getEnd() - Math.min(Math.max(value, 0)));
// Mark as dirty for subsequent persistence
dirty[toId(id)] = true;
}
@ -140,10 +142,12 @@ define(
var timespan = timespans[toId(id)];
// Use as setter if argument is present
if ((typeof value === 'number') && timespan) {
// Set the end (ensuring it doesn't precede start)
// Set the end and duration (ensuring it doesn't precede start)
timespan.setEnd(
Math.max(value, timespan.getStart())
);
timespan.setDuration(Math.max(value, timespan.getStart()) - timespan.getStart());
// Mark as dirty for subsequent persistence
dirty[toId(id)] = true;
}
@ -198,9 +202,12 @@ define(
// own adjustments
start = timespan.getStart();
end = timespan.getEnd();
// Update start, then end
// Update duration, start, then end
timespan.setDuration(end - start);
timespan.setStart(start + delta);
timespan.setEnd(end + delta);
// Mark as dirty for subsequent persistence
dirty[toId(spanId)] = true;
}

View File

@ -68,7 +68,6 @@ define(
chooseEnd = diffEnd > 0;
}
// Start is chosen if diffEnd didn't snap, or nothing snapped
// Our delta is relative to our initial state, but
// dragHandler.move is relative to current state, so whichever
// end we're snapping to, we need to compute a delta

View File

@ -39,7 +39,7 @@ define(
* @param configuration the view's configuration object
* @param {TimelineSwimlane} parent the parent swim lane (if any)
*/
function TimelineSwimlane(domainObject, assigner, configuration, parent, index) {
function TimelineSwimlane(domainObject, assigner, configuration, parent, index, openmct) {
var id = domainObject.getId(),
highlight = false, // Drop highlight (middle)
highlightBottom = false, // Drop highlight (lower)
@ -47,13 +47,93 @@ define(
depth = parent ? (parent.depth + 1) : 0,
timespan,
path = (!parent || !parent.parent) ? "" : parent.path +
parent.domainObject.getModel().name + " > ";
parent.domainObject.getModel().name + " > ",
instantiate = openmct.$injector.get("instantiate"),
copy = 1;
// Look up timespan for this object
domainObject.useCapability('timespan').then(function (t) {
timespan = t;
});
function makeCopies(input) {
if (input !== undefined) {
var number = Number(input);
if (!isNaN(number)) {
if (number >= 1 && number <= 5) {
var parentComposition = timespan.getParent().getCapability('composition'),
timespanModel = timespan.getModel();
for (var i = 1; i <= number; i++) {
var activityId = timespanModel.id + '-copy-' + copy,
activityModel = {
name: timespanModel.name + ' Copy ' + copy,
start: {timestamp: timespan.getStart(), epoch: "SET"},
duration: {timestamp: timespan.getDuration(), epoch: "SET"},
type: 'activity',
relationships: timespanModel.relationships,
id: activityId
},
activityInstance = instantiate(activityModel);
activityInstance.getCapability('location').setPrimaryLocation(timespan.getParent().model.id);
parentComposition.add(activityInstance);
copy++;
}
} else {
window.alert("Please enter a Number between 1 and 5");
}
} else {
window.alert("Please enter a Number");
}
}
}
function fragment(input) {
if (input !== undefined) {
var number = Number(input),
frag = 1;
if (!isNaN(number)) {
if (number >= 2 && number <= 5) {
var parentComposition = timespan.getParent().getCapability('composition'),
timespanModel = timespan.getModel(),
duration = (timespan.getEnd() - timespan.getStart()) / number;
timespan.setDuration(duration);
timespan.setEnd(timespan.getStart() + duration);
for (var i = 1; i < number; i++) {
var activityId = timespanModel.id + '-fragment-' + frag,
activityModel = {
name: timespanModel.name + ' Fragment ' + frag,
start: {timestamp: timespan.getStart(), epoch: "SET"},
duration: {timestamp: duration, epoch: "SET"},
type: 'activity',
relationships: timespanModel.relationships,
id: activityId
},
activityInstance = instantiate(activityModel);
activityInstance.getCapability('location').setPrimaryLocation(timespan.getParent().model.id);
parentComposition.add(activityInstance);
frag++;
}
} else {
window.alert("Please enter a Number between 2 and 5");
}
} else {
window.alert("Please enter a Number");
}
}
}
return {
/**
* Check if this swimlane is currently visible. (That is,
@ -155,6 +235,15 @@ define(
timespan: function () {
return timespan;
},
updateDuration: function () {
var duration = timespan.getDuration('model'),
start = timespan.getStart();
timespan.setDuration(duration);
timespan.setEnd(start + duration);
},
makeCopies: makeCopies,
fragment: fragment,
// Expose domain object, expansion state, indentation depth
domainObject: domainObject,
expanded: true,

View File

@ -39,7 +39,7 @@ define(
* timeline view.
* @constructor
*/
function TimelineSwimlanePopulator(objectLoader, configuration, selection) {
function TimelineSwimlanePopulator(objectLoader, configuration, selection, openmct) {
var swimlanes = [],
start = Number.POSITIVE_INFINITY,
end = Number.NEGATIVE_INFINITY,
@ -72,7 +72,8 @@ define(
assigner,
configuration,
parent,
index || 0
index || 0,
openmct
), selection);
// Track start & end times of this domain object
domainObject.useCapability('timespan').then(trackStartEnd);

View File

@ -0,0 +1,31 @@
define([
'./src/actions/activityModesImportAction',
'./src/policies/ActionPolicy'
],
function (ActivityModes, ActionPolicy) {
function plugin() {
return function install(openmct) {
openmct.legacyExtension('actions', {
key: "import-csv",
category: ["contextual"],
implementation: ActivityModes,
cssClass: "major icon-import",
name: "Import Activity Definitions from CSV",
description: "Import activities from a CSV file",
depends: [
"dialogService",
"openmct"
]
});
openmct.legacyExtension('policies', {
category: 'action',
implementation: ActionPolicy
});
};
}
return plugin;
});

View File

@ -0,0 +1,172 @@
define(['d3-dsv'], function (d3Dsv) {
function ActivityModesImportAction(dialogService, openmct, context) {
this.dialogService = dialogService;
this.openmct = openmct;
this.context = context;
this.parent = this.context.domainObject;
this.instantiate = this.openmct.$injector.get("instantiate");
this.objectService = this.openmct.$injector.get("objectService").objectService;
this.populateActivities = this.populateActivities.bind(this);
}
ActivityModesImportAction.prototype.perform = function () {
this.parentId = this.parent.getId();
this.dialogService.getUserInput(this.getFormModel(), function () {})
.then(function (form) {
if (form.selectFile.name.slice(-3) !== 'csv') {
this.displayError();
}
this.csvParse(form.selectFile.body).then(this.populateActivities);
}.bind(this));
};
ActivityModesImportAction.prototype.csvParse = function (csvString) {
return new Promise(function (resolve, reject) {
var parsedObject = d3Dsv.csvParse(csvString);
return parsedObject ? resolve(parsedObject) : reject('Could not parse provided file');
});
};
ActivityModesImportAction.prototype.populateActivities = function (csvObjects) {
this.parentComposition = this.parent.getCapability("composition");
this.blockingDialog = this.showBlockingMessage();
var activitiesObjects = {},
activityModesObjects = {};
csvObjects.forEach(function (activity, index) {
var newActivity = {},
newActivityMode = {},
duration = !isNaN(Number(activity.duration)) ? 1000 * Number(activity.duration) : 0;
newActivity.name = activity.name;
newActivity.id = activity.id ? ('activity-' + activity.id) : ('activity-' + index + '-' + this.parentId);
newActivity.start = {timestamp: 0, epoch: "SET"};
newActivity.duration = {timestamp: duration, epoch: "SET"};
newActivity.type = "activity";
newActivity.composition = [];
newActivity.relationships = {modes: []};
newActivityMode.name = activity.name + ' Resources';
newActivityMode.id = activity.id ? ('activity-mode-' + activity.id) : ('activity-mode-' + index + '-' + this.parentId);
newActivityMode.resources = {comms: Number(activity.comms) || 0, power: Number(activity.power) || 0};
newActivityMode.type = 'mode';
newActivity.relationships.modes.push(newActivityMode.id);
activitiesObjects[newActivity.id] = newActivity;
activityModesObjects[newActivityMode.id] = newActivityMode;
}.bind(this));
this.instantiateActivityModes(activityModesObjects);
this.instantiateActivities(activitiesObjects);
};
ActivityModesImportAction.prototype.instantiateActivityModes = function (activityModesObjects) {
var activityModesArray = Object.keys(activityModesObjects);
this.objectService.getObjects(activityModesArray).then(
function (previousActivityModes) {
activityModesArray.forEach(function (activityModeId) {
previousActivityModes[activityModeId].getCapability('mutation').mutate(function (prev) {
var activityMode = activityModesObjects[activityModeId];
prev.name = activityMode.name;
prev.resources = activityMode.resources;
prev.type = activityMode.type;
prev.id = activityMode.id;
});
});
}
);
};
ActivityModesImportAction.prototype.instantiateActivities = function (activitiesObjects) {
var activityObjectArray = Object.keys(activitiesObjects);
this.objectService.getObjects(activityObjectArray).then(
function (objects) {
activityObjectArray.forEach(function (activityId, index) {
var activity = activitiesObjects[activityId];
objects[activityId].getCapability('mutation').mutate(function (prevActivity) {
prevActivity.name = activity.name;
prevActivity.start = activity.start;
prevActivity.duration = activity.duration;
prevActivity.type = activity.type;
prevActivity.composition = activity.composition;
prevActivity.relationships = activity.relationships;
prevActivity.id = activity.id;
});
objects[activityId].getCapability('location').setPrimaryLocation(this.parentId);
if ((index === (activityObjectArray.length - 1)) && this.blockingDialog) {
this.blockingDialog.dismiss();
}
}.bind(this));
this.parentComposition.domainObject.getCapability('mutation').mutate(function (parentComposition) {
parentComposition.composition = activityObjectArray;
});
}.bind(this)
);
};
ActivityModesImportAction.prototype.showBlockingMessage = function () {
var model = {
title: "Importing",
actionText: "Importing Activities from CSV",
severity: "info",
unknownProgress: true
};
return this.dialogService.showBlockingMessage(model);
};
ActivityModesImportAction.prototype.displayError = function () {
var dialog,
perform = this.perform.bind(this),
model = {
title: "Invalid File",
actionText: "The selected file was not a valid CSV file",
severity: "error",
options: [
{
label: "Ok",
callback: function () {
dialog.dismiss();
perform();
}
}
]
};
dialog = this.dialogService.showBlockingMessage(model);
};
ActivityModesImportAction.prototype.getFormModel = function () {
return {
name: 'Import activities from CSV',
sections: [
{
name: 'Import A File',
rows: [
{
name: 'Select File',
key: 'selectFile',
control: 'file-input',
required: true,
text: 'Select File'
}
]
}
]
};
};
return ActivityModesImportAction;
});

View File

@ -0,0 +1,46 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
function () {
function ActionPolicy() {
}
ActionPolicy.prototype.allow = function (action, context) {
var key = action.getMetadata().key,
domainObjectType =
context.domainObject ? context.domainObject.getModel().type : '';
if (key === 'import-csv') {
if (domainObjectType === 'folder') {
return true;
}
return false;
}
return true;
};
return ActionPolicy;
}
);

View File

@ -30,6 +30,7 @@ define([
'../../platform/import-export/bundle',
'./summaryWidget/plugin',
'./URLIndicatorPlugin/URLIndicatorPlugin',
'./activityModes/plugin',
'./telemetryMean/plugin',
'./plot/plugin',
'./staticRootPlugin/plugin'
@ -43,6 +44,7 @@ define([
ImportExport,
SummaryWidget,
URLIndicatorPlugin,
ActivityModes,
TelemetryMean,
PlotPlugin,
StaticRootPlugin
@ -137,6 +139,7 @@ define([
plugins.SummaryWidget = SummaryWidget;
plugins.TelemetryMean = TelemetryMean;
plugins.URLIndicatorPlugin = URLIndicatorPlugin;
plugins.ActivityModes = ActivityModes;
return plugins;
});

View File

@ -75,7 +75,8 @@ requirejs.config({
"d3-format": "node_modules/d3-format/build/d3-format.min",
"d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
"d3-time": "node_modules/d3-time/build/d3-time.min",
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min"
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min",
"d3-dsv": "node_modules/d3-dsv/build/d3-dsv.min"
},
"shim": {