[Import/Export] Adds Import and Export functionality
Added context actions for importing and exporting JSON representations of domain objects. Added FileInputService for triggering file picker and retrieving uploaded data. Also added a File Input form control for integration with MCTForms.
This commit is contained in:
@@ -24,6 +24,8 @@ define([
|
||||
"./src/MCTForm",
|
||||
"./src/MCTToolbar",
|
||||
"./src/MCTControl",
|
||||
"./src/MCTFileInput",
|
||||
"./src/FileInputService",
|
||||
"./src/controllers/AutocompleteController",
|
||||
"./src/controllers/DateTimeController",
|
||||
"./src/controllers/CompositeController",
|
||||
@@ -42,11 +44,14 @@ define([
|
||||
"text!./res/templates/controls/menu-button.html",
|
||||
"text!./res/templates/controls/dialog.html",
|
||||
"text!./res/templates/controls/radio.html",
|
||||
"text!./res/templates/controls/file-input.html",
|
||||
'legacyRegistry'
|
||||
], function (
|
||||
MCTForm,
|
||||
MCTToolbar,
|
||||
MCTControl,
|
||||
MCTFileInput,
|
||||
FileInputService,
|
||||
AutocompleteController,
|
||||
DateTimeController,
|
||||
CompositeController,
|
||||
@@ -65,6 +70,7 @@ define([
|
||||
menuButtonTemplate,
|
||||
dialogTemplate,
|
||||
radioTemplate,
|
||||
fileInputTemplate,
|
||||
legacyRegistry
|
||||
) {
|
||||
|
||||
@@ -88,6 +94,13 @@ define([
|
||||
"templateLinker",
|
||||
"controls[]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "mctFileInput",
|
||||
"implementation": MCTFileInput,
|
||||
"depends": [
|
||||
"fileInputService"
|
||||
]
|
||||
}
|
||||
],
|
||||
"controls": [
|
||||
@@ -142,6 +155,10 @@ define([
|
||||
{
|
||||
"key": "dialog-button",
|
||||
"template": dialogTemplate
|
||||
},
|
||||
{
|
||||
"key": "file-input",
|
||||
"template": fileInputTemplate
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
@@ -176,6 +193,14 @@ define([
|
||||
"dialogService"
|
||||
]
|
||||
}
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"provides": "fileInputService",
|
||||
"type": "provider",
|
||||
"implementation": FileInputService
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
30
platform/forms/res/templates/controls/file-input.html
Normal file
30
platform/forms/res/templates/controls/file-input.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2017, 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.
|
||||
-->
|
||||
|
||||
<a class="s-button {{structure.cssClass}}"
|
||||
ng-model="ngModel[field]"
|
||||
ng-class="{ labeled: structure.text }"
|
||||
mct-file-input>
|
||||
<span class="title-label" ng-if="structure.text">
|
||||
{{structure.text}}
|
||||
</span>
|
||||
</a>
|
||||
90
platform/forms/src/FileInputService.js
Normal file
90
platform/forms/src/FileInputService.js
Normal file
@@ -0,0 +1,90 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, 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(["zepto"], function ($) {
|
||||
|
||||
/**
|
||||
* The FileInputService provides an interface for triggering a file input.
|
||||
*
|
||||
* @constructor
|
||||
* @memberof platform/forms
|
||||
*/
|
||||
function FileInputService() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates, triggers, and destroys a file picker element and returns a
|
||||
* promise for an object containing the chosen file's name and contents.
|
||||
*
|
||||
* @returns {Promise} promise for an object containing file meta-data
|
||||
*/
|
||||
FileInputService.prototype.getInput = function () {
|
||||
var input = this.newInput();
|
||||
var read = this.readFile;
|
||||
var fileInfo = {};
|
||||
var file;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
input.trigger("click");
|
||||
input.on('change', function (event) {
|
||||
file = this.files[0];
|
||||
input.remove();
|
||||
if (file) {
|
||||
read(file)
|
||||
.then(function (contents) {
|
||||
fileInfo.name = file.name;
|
||||
fileInfo.body = contents;
|
||||
resolve(fileInfo);
|
||||
}, function () {
|
||||
reject("File read error");
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
FileInputService.prototype.readFile = function (file) {
|
||||
var fileReader = new FileReader();
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
fileReader.onload = function (event) {
|
||||
resolve(event.target.result);
|
||||
};
|
||||
|
||||
fileReader.onerror = function () {
|
||||
return reject(event.target.result);
|
||||
};
|
||||
fileReader.readAsText(file);
|
||||
});
|
||||
};
|
||||
|
||||
FileInputService.prototype.newInput = function () {
|
||||
var input = $(document.createElement('input'));
|
||||
input.attr("type", "file");
|
||||
input.css("display", "none");
|
||||
$('body').append(input);
|
||||
return input;
|
||||
};
|
||||
|
||||
return FileInputService;
|
||||
});
|
||||
66
platform/forms/src/MCTFileInput.js
Normal file
66
platform/forms/src/MCTFileInput.js
Normal file
@@ -0,0 +1,66 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, 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(
|
||||
['zepto'],
|
||||
function ($) {
|
||||
|
||||
/**
|
||||
* The mct-file-input handles behavior of the file input form control.
|
||||
* @constructor
|
||||
* @memberof platform/forms
|
||||
*/
|
||||
function MCTFileInput(fileInputService) {
|
||||
|
||||
function link(scope, element, attrs, control) {
|
||||
|
||||
function setText(fileName) {
|
||||
scope.structure.text = fileName.length > 20 ?
|
||||
fileName.substr(0, 20) + "..." :
|
||||
fileName;
|
||||
}
|
||||
|
||||
function handleClick() {
|
||||
fileInputService.getInput().then(function (result) {
|
||||
setText(result.name);
|
||||
scope.ngModel[scope.field] = result;
|
||||
control.$setValidity("file-input", true);
|
||||
}, function () {
|
||||
setText('Select File');
|
||||
control.$setValidity("file-input", false);
|
||||
});
|
||||
}
|
||||
|
||||
control.$setValidity("file-input", false);
|
||||
element.on('click', handleClick);
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: "A",
|
||||
require: "^form",
|
||||
link: link
|
||||
};
|
||||
}
|
||||
|
||||
return MCTFileInput;
|
||||
}
|
||||
);
|
||||
74
platform/forms/test/FileInputServiceSpec.js
Normal file
74
platform/forms/test/FileInputServiceSpec.js
Normal file
@@ -0,0 +1,74 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, 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(
|
||||
["../src/FileInputService"],
|
||||
function (FileInputService) {
|
||||
|
||||
describe("The FileInputService", function () {
|
||||
var fileInputService,
|
||||
mockInput;
|
||||
|
||||
beforeEach(function () {
|
||||
fileInputService = new FileInputService();
|
||||
mockInput = jasmine.createSpyObj('input',
|
||||
[
|
||||
'on',
|
||||
'trigger',
|
||||
'remove'
|
||||
]
|
||||
);
|
||||
mockInput.on.andCallFake(function (event, changeHandler) {
|
||||
changeHandler.apply(mockInput);
|
||||
});
|
||||
spyOn(fileInputService, "newInput").andReturn(
|
||||
mockInput
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
it("can read a file", function () {
|
||||
mockInput.files = [new File(["file content"], "file name")];
|
||||
fileInputService.getInput().then(function (result) {
|
||||
expect(result.name).toBe("file name");
|
||||
expect(result.body).toBe("file content");
|
||||
});
|
||||
|
||||
expect(mockInput.trigger).toHaveBeenCalledWith('click');
|
||||
expect(mockInput.remove).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("catches file read errors", function () {
|
||||
mockInput.files = ["GARBAGE"];
|
||||
fileInputService.getInput().then(
|
||||
function (result) {},
|
||||
function (err) {
|
||||
expect(err).toBe("File read error");
|
||||
}
|
||||
);
|
||||
|
||||
expect(mockInput.trigger).toHaveBeenCalledWith('click');
|
||||
expect(mockInput.remove).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
98
platform/forms/test/MCTFileInputSpec.js
Normal file
98
platform/forms/test/MCTFileInputSpec.js
Normal file
@@ -0,0 +1,98 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, 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(
|
||||
["../src/MCTFileInput"],
|
||||
function (MCTFileInput) {
|
||||
|
||||
describe("The mct-file-input directive", function () {
|
||||
|
||||
var mockScope,
|
||||
mockFileInputService,
|
||||
mctFileInput,
|
||||
element,
|
||||
attrs,
|
||||
control;
|
||||
|
||||
beforeEach(function () {
|
||||
attrs = [];
|
||||
control = jasmine.createSpyObj('control', ['$setValidity']);
|
||||
element = jasmine.createSpyObj('element', ['on', 'trigger']);
|
||||
mockFileInputService = jasmine.createSpyObj('fileInputService',
|
||||
['getInput']
|
||||
);
|
||||
mockScope = jasmine.createSpyObj(
|
||||
'$scope',
|
||||
['$watch']
|
||||
);
|
||||
|
||||
mockScope.structure = {text: 'Select File'};
|
||||
mockScope.field = "file-input";
|
||||
mockScope.ngModel = {"file-input" : undefined};
|
||||
|
||||
element.on.andCallFake(function (event, clickHandler) {
|
||||
clickHandler();
|
||||
});
|
||||
mockFileInputService.getInput.andReturn(
|
||||
Promise.resolve({name: "file-name", body: "file-body"})
|
||||
);
|
||||
|
||||
mctFileInput = new MCTFileInput(mockFileInputService);
|
||||
|
||||
// Need to wait for mock promise
|
||||
var init = false;
|
||||
runs(function () {
|
||||
mctFileInput.link(mockScope, element, attrs, control);
|
||||
setTimeout(function () {
|
||||
init = true;
|
||||
}, 100);
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return init;
|
||||
}, "File selection should have beeen simulated");
|
||||
});
|
||||
|
||||
it("is restricted to attributes", function () {
|
||||
expect(mctFileInput.restrict).toEqual("A");
|
||||
});
|
||||
|
||||
it("changes button text to match file name", function () {
|
||||
expect(element.on).toHaveBeenCalledWith(
|
||||
'click',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
expect(mockScope.structure.text).toEqual("file-name");
|
||||
});
|
||||
|
||||
it("validates control on file selection", function () {
|
||||
expect(control.$setValidity.callCount).toBe(2);
|
||||
expect(control.$setValidity.argsForCall[0]).toEqual(
|
||||
['file-input', false]
|
||||
);
|
||||
expect(control.$setValidity.argsForCall[1]).toEqual(
|
||||
['file-input', true]
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user