Compare commits

...

16 Commits

Author SHA1 Message Date
b7a94a9dd5 working view 2018-01-18 12:11:54 -08:00
2b11b8d63c create activity capability and resource 2018-01-16 15:35:13 -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
12 changed files with 376 additions and 22 deletions

View File

@ -68,6 +68,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

@ -7,6 +7,7 @@
"d3-axis": "^1.0.4",
"d3-collection": "^1.0.2",
"d3-color": "^1.0.2",
"d3-dsv": "^1.0.8",
"d3-format": "^1.0.2",
"d3-interpolate": "^1.1.3",
"d3-scale": "^1.0.4",

View File

@ -32,6 +32,7 @@ define([
"./src/controllers/TimelineTOIController",
"./src/controllers/ActivityModeValuesController",
"./src/capabilities/ActivityTimespanCapability",
"./src/capabilities/ActivityValueCapability",
"./src/capabilities/TimelineTimespanCapability",
"./src/capabilities/UtilizationCapability",
"./src/capabilities/GraphCapability",
@ -42,6 +43,7 @@ define([
"./src/services/ObjectLoader",
"./src/chart/MCTTimelineChart",
"text!./res/templates/values.html",
"text!./res/templates/activity-view.html",
"text!./res/templates/timeline.html",
"text!./res/templates/activity-gantt.html",
"text!./res/templates/tabular-swimlane-cols-tree.html",
@ -64,6 +66,7 @@ define([
TimelineTOIController,
ActivityModeValuesController,
ActivityTimespanCapability,
ActivityValueCapability,
TimelineTimespanCapability,
UtilizationCapability,
GraphCapability,
@ -74,6 +77,7 @@ define([
ObjectLoader,
MCTTimelineChart,
valuesTemplate,
activityTemplate,
timelineTemplate,
activityGanttTemplate,
tabularSwimlaneColsTreeTemplate,
@ -204,7 +208,9 @@ define([
"composition": [],
"start": {
"timestamp": 0
}
},
"activityStart": {},
"activityDuration": {}
}
},
{
@ -304,6 +310,17 @@ define([
],
"editable": false
},
{
"key": "activityValues",
"name": "Activity Values",
"cssClass": "icon-activity",
"template": activityTemplate,
"type": "activity",
"uses": [
"activityValue"
],
"editable": false
},
{
"key": "timeline",
"name": "Timeline",
@ -555,6 +572,10 @@ define([
{
"key": "cost",
"implementation": CostCapability
},
{
"key": "activityValue",
"implementation": ActivityValueCapability
}
],
"directives": [

View File

@ -0,0 +1,27 @@
<!--
Open MCT, Copyright (c) 2009-2016, 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.
-->
<ul ng-controller="ActivityModeValuesController as controller" class="cols cols-2-ff properties">
<li ng-repeat="(key, value) in activityValue" class="l-row s-row">
<span class="col col-100px s-title"></span>
<span class="col s-value">{{value}}</span>
</li>
</ul>

View File

@ -21,27 +21,48 @@
*****************************************************************************/
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, parentTimeline) {
var parentTimelineModel = parentTimeline.getModel(),
parentMutation = parentTimeline.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;
}
}
// 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;
var start = getTimelineActivityStart(parentTimelineModel),
duration = getTimelineActivityDuration(parentTimelineModel);
return start + duration;
}
// Get the duration of this timeline
function getDuration() {
return model.duration.timestamp;
return getTimelineActivityDuration(parentTimelineModel);
}
// Get the epoch used by this timeline
@ -52,26 +73,41 @@ 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) {
m.activityStart[model.id] = Math.max(value,0);
m.activityDuration[model.id] = Math.max(end - value, 0);
});
// 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);
}
// 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) {
m.activityDuration[model.id] = Math.max(value, 0);
});
// mutation.mutate(function (m) {
// m.duration.timestamp = Math.max(value, 0);
// }, model.modified);
}
// 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) {
m.activityDuration[model.id] = Math.max(value - start, 0);
});
// mutation.mutate(function (m) {
// m.duration.timestamp = Math.max(value - start, 0);
// }, model.modified);
}
return {

View File

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

View File

@ -0,0 +1,75 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2009-2016, 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 () {
/**
* Exposes costs associated with a subsystem mode.
* @constructor
*/
function ActivityValueCapability(domainObject) {
var model = domainObject.getModel();
return {
/**
* Get a list of resource types which have associated
* costs for this object. Returned values are machine-readable
* keys, and should be paired with external metadata for
* presentation (see category of extension `resources`).
* @returns {string[]} resource types
*/
resources: function () {
return Object.keys(model.resources || {}).sort();
},
/**
* Get the cost associated with a resource of an identified
* type (typically, one of the types reported from a
* `resources` call.)
* @param {string} key the resource type
* @returns {number} the associated cost
*/
cost: function (key) {
return (model.resources || {})[key] || 0;
},
/**
* Get an object containing key-value pairs describing
* resource utilization as described by this object.
* Keys are resource types; values are levels of associated
* resource utilization.
* @returns {object} resource utilizations
*/
invoke: function () {
return {key: 'deep is the best'};
}
};
}
// Only applies to subsystem modes.
ActivityValueCapability.appliesTo = function (model) {
return (model || {}).type === 'activity';
};
return ActivityValueCapability;
}
);

View File

@ -30,7 +30,7 @@ define(
*/
function CostCapability(domainObject) {
var model = domainObject.getModel();
return {
/**
* Get a list of resource types which have associated

View File

@ -0,0 +1,47 @@
define(['./src/actions/activityModesImportAction'], function (ActivityModes) {
function plugin() {
return function install(openmct) {
openmct.legacyRegistry.register("src/plugins/activityModes", {
"name": "Activity Import",
"description": "Defines a root named My Items",
"extensions": {
"roots": [
{
"id": "activity-import"
}
],
"models": [
{
"id": "activity-import",
"model": {
"name": "Activity Import",
"type": "folder",
"composition": [],
"location": "ROOT"
}
}
]
}
});
openmct.legacyRegistry.enable("src/plugins/activityModes");
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"
]
});
};
}
return plugin;
});

View File

@ -0,0 +1,127 @@
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.instantiateActivities = this.instantiateActivities.bind(this);
}
ActivityModesImportAction.prototype.perform = function () {
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.instantiateActivities);
}.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.instantiateActivities = function (csvObjects) {
var parent = this.context.domainObject,
parentId = parent.getId(),
parentComposition = parent.getCapability("composition"),
activitiesObjects = [],
activityModesObjects = [];
csvObjects.forEach(function (activity) {
var newActivity = {},
newActivityMode = {};
newActivity.name = activity.name;
newActivity.start = {timestamp: 0, epoch: "SET"};
newActivity.duration = {timestamp: Number(activity.duration), epoch: "SET"};
newActivity.type = "activity";
newActivity.relationships = {modes: []};
activitiesObjects.push(newActivity);
newActivityMode.name = activity.name + ' Resources';
newActivityMode.resources = {comms: Number(activity.comms), power: Number(activity.power)};
newActivityMode.type = 'mode';
activityModesObjects.push(newActivityMode);
});
var folderComposition = this.createActivityModesFolder().getCapability('composition');
activityModesObjects.forEach(function (activityMode, index) {
var newActivityModeInstance = this.instantiate(activityMode, 'activity-mode-' + index);
newActivityModeInstance.getCapability('location').setPrimaryLocation('activity-modes-folder');
folderComposition.add(newActivityModeInstance);
}.bind(this));
activitiesObjects.forEach(function (activity, index) {
activity.relationships.modes.push('activity-mode-' + index);
activity.id = 'activity-' + index;
var newActivityInstance = this.instantiate(activity, 'activity-' + index);
newActivityInstance.getCapability('location').setPrimaryLocation(parentId);
parentComposition.add(newActivityInstance);
}.bind(this));
};
ActivityModesImportAction.prototype.createActivityModesFolder = function () {
var folderInstance = this.instantiate({name: 'Activity-Modes', type: 'folder', composition: []}, 'activity-modes-folder');
folderInstance.getCapability('location').setPrimaryLocation(this.parent.getId());
this.parent.getCapability('composition').add(folderInstance);
return folderInstance;
};
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

@ -30,6 +30,7 @@ define([
'../../platform/import-export/bundle',
'./summaryWidget/plugin',
'./URLIndicatorPlugin/URLIndicatorPlugin',
'./activityModes/plugin',
'./telemetryMean/plugin'
], function (
_,
@ -41,6 +42,7 @@ define([
ImportExport,
SummaryWidget,
URLIndicatorPlugin,
ActivityModes,
TelemetryMean
) {
var bundleMap = {
@ -129,6 +131,7 @@ define([
plugins.SummaryWidget = SummaryWidget;
plugins.TelemetryMean = TelemetryMean;
plugins.URLIndicatorPlugin = URLIndicatorPlugin;
plugins.ActivityModes = ActivityModes;
return plugins;
});