mirror of
https://github.com/nasa/openmct.git
synced 2024-12-20 05:37:53 +00:00
Replace angular route with custom router
This commit is contained in:
parent
63f22c3f21
commit
4203dbf8e1
@ -43,6 +43,7 @@
|
|||||||
"karma-html-reporter": "^0.2.7",
|
"karma-html-reporter": "^0.2.7",
|
||||||
"karma-jasmine": "^1.1.2",
|
"karma-jasmine": "^1.1.2",
|
||||||
"karma-webpack": "^3.0.0",
|
"karma-webpack": "^3.0.0",
|
||||||
|
"location-bar": "^3.0.1",
|
||||||
"lodash": "^3.10.1",
|
"lodash": "^3.10.1",
|
||||||
"markdown-toc": "^0.11.7",
|
"markdown-toc": "^0.11.7",
|
||||||
"marked": "^0.3.5",
|
"marked": "^0.3.5",
|
||||||
|
@ -73,15 +73,6 @@ define([
|
|||||||
legacyRegistry.register("platform/commonUI/browse", {
|
legacyRegistry.register("platform/commonUI/browse", {
|
||||||
"extensions": {
|
"extensions": {
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
|
||||||
"when": "/browse/:ids*?",
|
|
||||||
"template": browseTemplate,
|
|
||||||
"reloadOnSearch": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": "",
|
|
||||||
"redirectTo": "/browse/"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"constants": [
|
"constants": [
|
||||||
{
|
{
|
||||||
|
@ -55,16 +55,16 @@ define(
|
|||||||
navigatedObject = this.navigationService.getNavigation(),
|
navigatedObject = this.navigationService.getNavigation(),
|
||||||
actionMetadata = action.getMetadata ? action.getMetadata() : {};
|
actionMetadata = action.getMetadata ? action.getMetadata() : {};
|
||||||
|
|
||||||
if (navigatedObject.hasCapability("editor") && navigatedObject.getCapability("editor").isEditContextRoot()) {
|
// if (navigatedObject.hasCapability("editor") && navigatedObject.getCapability("editor").isEditContextRoot()) {
|
||||||
if (selectedObject.hasCapability("editor") && selectedObject.getCapability("editor").inEditContext()) {
|
if (selectedObject.hasCapability("editor") && selectedObject.getCapability("editor").inEditContext()) {
|
||||||
return this.editModeBlacklist.indexOf(actionMetadata.key) === -1;
|
return this.editModeBlacklist.indexOf(actionMetadata.key) === -1;
|
||||||
} else {
|
} else {
|
||||||
//Target is in the context menu
|
//Target is in the context menu
|
||||||
return this.nonEditContextBlacklist.indexOf(actionMetadata.key) === -1;
|
return this.nonEditContextBlacklist.indexOf(actionMetadata.key) === -1;
|
||||||
}
|
}
|
||||||
} else {
|
// } else {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
return EditContextualActionPolicy;
|
return EditContextualActionPolicy;
|
||||||
|
10
src/MCT.js
10
src/MCT.js
@ -35,6 +35,7 @@ define([
|
|||||||
'./ui/registries/ViewRegistry',
|
'./ui/registries/ViewRegistry',
|
||||||
'./ui/registries/InspectorViewRegistry',
|
'./ui/registries/InspectorViewRegistry',
|
||||||
'./ui/registries/ToolbarRegistry',
|
'./ui/registries/ToolbarRegistry',
|
||||||
|
'./ui/router/ApplicationRouter',
|
||||||
'../platform/framework/src/Main',
|
'../platform/framework/src/Main',
|
||||||
'./styles-new/core.scss',
|
'./styles-new/core.scss',
|
||||||
'./ui/components/layout/Layout.vue',
|
'./ui/components/layout/Layout.vue',
|
||||||
@ -54,6 +55,7 @@ define([
|
|||||||
ViewRegistry,
|
ViewRegistry,
|
||||||
InspectorViewRegistry,
|
InspectorViewRegistry,
|
||||||
ToolbarRegistry,
|
ToolbarRegistry,
|
||||||
|
ApplicationRouter,
|
||||||
Main,
|
Main,
|
||||||
coreStyles,
|
coreStyles,
|
||||||
Layout,
|
Layout,
|
||||||
@ -296,6 +298,12 @@ define([
|
|||||||
|
|
||||||
this.install(LegacyIndicatorsPlugin());
|
this.install(LegacyIndicatorsPlugin());
|
||||||
|
|
||||||
|
this.router = new ApplicationRouter();
|
||||||
|
|
||||||
|
this.router.route(/^\/$/, () => {
|
||||||
|
this.router.setPath('/browse/mine');
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired by [MCT]{@link module:openmct.MCT} when the application
|
* Fired by [MCT]{@link module:openmct.MCT} when the application
|
||||||
* is started.
|
* is started.
|
||||||
@ -312,11 +320,11 @@ define([
|
|||||||
console.log('Attaching adapter');
|
console.log('Attaching adapter');
|
||||||
installVueAdapter(appLayout, this);
|
installVueAdapter(appLayout, this);
|
||||||
|
|
||||||
|
this.router.start();
|
||||||
this.emit('start');
|
this.emit('start');
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a plugin in MCT.
|
* Install a plugin in MCT.
|
||||||
*
|
*
|
||||||
|
@ -14,6 +14,27 @@ define([
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// recursively locate and return an object inside of a container
|
||||||
|
// via a path. If at any point in the recursion it fails to find
|
||||||
|
// the next object, it will return the parent.
|
||||||
|
function findViaComposition(containerObject, path) {
|
||||||
|
var nextId = path.shift();
|
||||||
|
if (!nextId) {
|
||||||
|
return containerObject;
|
||||||
|
}
|
||||||
|
return containerObject.useCapability('composition')
|
||||||
|
.then(function (composees) {
|
||||||
|
var nextObject = findObject(composees, nextId);
|
||||||
|
if (!nextObject) {
|
||||||
|
return containerObject;
|
||||||
|
}
|
||||||
|
if (!nextObject.hasCapability('composition')) {
|
||||||
|
return nextObject;
|
||||||
|
}
|
||||||
|
return findViaComposition(nextObject, path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getLastChildIfRoot(object) {
|
function getLastChildIfRoot(object) {
|
||||||
if (object.getId() !== 'ROOT') {
|
if (object.getId() !== 'ROOT') {
|
||||||
return object;
|
return object;
|
||||||
@ -24,6 +45,15 @@ define([
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pathForObject(domainObject) {
|
||||||
|
var context = domainObject.getCapability('context'),
|
||||||
|
objectPath = context ? context.getPath() : [],
|
||||||
|
ids = objectPath.map(function (domainObj) {
|
||||||
|
return domainObj.getId();
|
||||||
|
});
|
||||||
|
return "/browse/" + ids.slice(1).join("/");
|
||||||
|
}
|
||||||
|
|
||||||
class MainAdapter {
|
class MainAdapter {
|
||||||
constructor(layout, openmct) {
|
constructor(layout, openmct) {
|
||||||
this.openmct = openmct;
|
this.openmct = openmct;
|
||||||
@ -36,12 +66,6 @@ define([
|
|||||||
this.navigationService = this.$injector.get('navigationService');
|
this.navigationService = this.$injector.get('navigationService');
|
||||||
this.$timeout = this.$injector.get('$timeout');
|
this.$timeout = this.$injector.get('$timeout');
|
||||||
|
|
||||||
// this.urlService = this.$injector.get('urlService');
|
|
||||||
// this.$route = this.$injector.get('$route');
|
|
||||||
// this.defaultPath = this.$injector.get('DEFAULT_PATH');
|
|
||||||
// this.initialPath = (this.$route.current.params.ids || defaultPath).split("/"),
|
|
||||||
// console.log('Initial path!', initialPath);
|
|
||||||
|
|
||||||
this.templateMap = {};
|
this.templateMap = {};
|
||||||
this.$injector.get('templates[]').forEach((t) => {
|
this.$injector.get('templates[]').forEach((t) => {
|
||||||
this.templateMap[t.key] = this.templateMap[t.key] || t;
|
this.templateMap[t.key] = this.templateMap[t.key] || t;
|
||||||
@ -49,50 +73,34 @@ define([
|
|||||||
|
|
||||||
var $rootScope = this.$injector.get('$rootScope');
|
var $rootScope = this.$injector.get('$rootScope');
|
||||||
this.scope = $rootScope.$new();
|
this.scope = $rootScope.$new();
|
||||||
|
this.scope.representation = {};
|
||||||
|
|
||||||
|
openmct.router.route(/^\/browse\/(.*)$/, (path, results) => {
|
||||||
this.run();
|
let navigatePath = results[1];
|
||||||
|
if (!navigatePath) {
|
||||||
this.templateLinker.link(
|
navigatePath = 'mine';
|
||||||
this.scope,
|
}
|
||||||
angular.element(layout.$refs.mainContainer),
|
this.navigateToPath(navigatePath);
|
||||||
this.templateMap["browseObject"]
|
});
|
||||||
);
|
|
||||||
|
|
||||||
this.navigationService.addListener(o => this.navigateToObject(o));
|
this.navigationService.addListener(o => this.navigateToObject(o));
|
||||||
this.getObject('ROOT')
|
}
|
||||||
.then(rootObject => {
|
|
||||||
this.rootObject = rootObject;
|
navigateToPath(path) {
|
||||||
return getLastChildIfRoot(rootObject);
|
if (!Array.isArray(path)) {
|
||||||
|
path = path.split('/');
|
||||||
|
}
|
||||||
|
return this.getObject('ROOT')
|
||||||
|
.then(root => {
|
||||||
|
return findViaComposition(root, path);
|
||||||
})
|
})
|
||||||
.then(o => {
|
.then(getLastChildIfRoot)
|
||||||
this.navigationService.setNavigation(o, true);
|
.then(object => {
|
||||||
|
this.setMainViewObject(object);
|
||||||
});
|
});
|
||||||
// this.navigateToRoot();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run() {
|
setMainViewObject(object) {
|
||||||
// TODO: navigate to default path.
|
|
||||||
// TODO: listen to route service and navigate on route changes?
|
|
||||||
// TODO: handle change to/from ?
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// idsForObject(domainObject) {
|
|
||||||
// return this.urlService
|
|
||||||
// .urlForLocation("", domainObject)
|
|
||||||
// .replace('/', '');
|
|
||||||
// }
|
|
||||||
|
|
||||||
navigateToObject(object) {
|
|
||||||
this.scope.representation = {
|
|
||||||
selected: {
|
|
||||||
key: 'items'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// this.scope.domainObject = this.rootObject
|
|
||||||
this.scope.domainObject = object;
|
this.scope.domainObject = object;
|
||||||
this.scope.navigatedObject = object;
|
this.scope.navigatedObject = object;
|
||||||
this.templateLinker.link(
|
this.templateLinker.link(
|
||||||
@ -100,84 +108,39 @@ define([
|
|||||||
angular.element(this.layout.$refs.mainContainer),
|
angular.element(this.layout.$refs.mainContainer),
|
||||||
this.templateMap["browseObject"]
|
this.templateMap["browseObject"]
|
||||||
);
|
);
|
||||||
// this.scope.navigatedObject = object;
|
|
||||||
this.scheduleDigest();
|
this.scheduleDigest();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
idsForObject(domainObject) {
|
||||||
|
return this.urlService
|
||||||
|
.urlForLocation("", domainObject)
|
||||||
|
.replace('/', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToObject(object) {
|
||||||
|
let path = pathForObject(object);
|
||||||
|
let views = object.useCapability('view');
|
||||||
|
let params = this.openmct.router.getParams();
|
||||||
|
let currentViewIsValid = views.some(v => v.key === params['view']);
|
||||||
|
if (!currentViewIsValid) {
|
||||||
|
this.scope.representation = {
|
||||||
|
selected: views[0]
|
||||||
|
}
|
||||||
|
this.openmct.router.update(path, {
|
||||||
|
view: views[0].key
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.openmct.router.setPath(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scheduleDigest() {
|
scheduleDigest() {
|
||||||
this.$timeout(function () {
|
this.$timeout(function () {
|
||||||
// digest done!
|
// digest done!
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// navigateToObject(desiredObject) {
|
|
||||||
// this.ngEl = angular.element(this.layout.$refs.mainContainer);
|
|
||||||
// this.scope.navigatedObject = desiredObject;
|
|
||||||
// this.templateLinker.link(
|
|
||||||
// this.scope,
|
|
||||||
// this.ngEl,
|
|
||||||
// this.templateMap["browse-object"]
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// // $scope.navigatedObject = desiredObject;
|
|
||||||
// // $scope.treeModel.selectedObject = desiredObject;
|
|
||||||
// // currentIds = idsForObject(desiredObject);
|
|
||||||
// // $route.current.pathParams.ids = currentIds;
|
|
||||||
// // $location.path('/browse/' + currentIds);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// navigateDirectlyToModel(domainObject) {
|
|
||||||
// var newIds = idsForObject(domainObject);
|
|
||||||
// if (currentIds !== newIds) {
|
|
||||||
// currentIds = newIds;
|
|
||||||
// navigateToObject(domainObject);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // recursively locate and return an object inside of a container
|
|
||||||
// // via a path. If at any point in the recursion it fails to find
|
|
||||||
// // the next object, it will return the parent.
|
|
||||||
// findViaComposition(containerObject, path) {
|
|
||||||
// var nextId = path.shift();
|
|
||||||
// if (!nextId) {
|
|
||||||
// return containerObject;
|
|
||||||
// }
|
|
||||||
// return containerObject.useCapability('composition')
|
|
||||||
// .then(function (composees) {
|
|
||||||
// var nextObject = findObject(composees, nextId);
|
|
||||||
// if (!nextObject) {
|
|
||||||
// return containerObject;
|
|
||||||
// }
|
|
||||||
// if (!nextObject.hasCapability('composition')) {
|
|
||||||
// return nextObject;
|
|
||||||
// }
|
|
||||||
// return findViaComposition(nextObject, path);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// navigateToRoot() {
|
|
||||||
// this.getObject('ROOT')
|
|
||||||
// .then(o => this.scope.domainObject = 0);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// navigateToPath(path) {
|
|
||||||
// return this.getObject('ROOT')
|
|
||||||
// .then(root => {
|
|
||||||
// return this.findViaComposition(root, path);
|
|
||||||
// })
|
|
||||||
// .then(getLastChildIfRoot)
|
|
||||||
// .then(object => {
|
|
||||||
// this.navigationService.setNavigation(object);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
getObject(id) {
|
getObject(id) {
|
||||||
return this.objectService.getObjects([id])
|
return this.objectService.getObjects([id])
|
||||||
.then(function (results) {
|
.then(function (results) {
|
||||||
|
172
src/ui/router/ApplicationRouter.js
Normal file
172
src/ui/router/ApplicationRouter.js
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
|
||||||
|
Application router -- must
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const LocationBar = require('location-bar');
|
||||||
|
const EventEmitter = require('EventEmitter');
|
||||||
|
|
||||||
|
function paramsToObject(searchParams) {
|
||||||
|
let params = {};
|
||||||
|
for ([key, value] of searchParams.entries()) {
|
||||||
|
if (params[key]) {
|
||||||
|
if (!Array.isArray(params[key])) {
|
||||||
|
params[key] = [params[key]];
|
||||||
|
}
|
||||||
|
params[key].push(value);
|
||||||
|
} else {
|
||||||
|
params[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ApplicationRouter extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* events
|
||||||
|
* change:params -> notify listeners w/ new, old, and changed.
|
||||||
|
* change:path -> notify listeners w/ new, old paths.
|
||||||
|
*
|
||||||
|
* methods:
|
||||||
|
* update(path, params) -> updates path and params at the same time. Only
|
||||||
|
* updates specified params, other params are not modified.
|
||||||
|
* updateParams(newParams) -> update only specified params, leaving rest
|
||||||
|
* intact. Does not modify path.
|
||||||
|
* updatePath(path);
|
||||||
|
|
||||||
|
* route(path, handler);
|
||||||
|
* start(); Start routing.
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.routes = [];
|
||||||
|
this.started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start application routing, should be done after handlers are registered.
|
||||||
|
*/
|
||||||
|
start() {
|
||||||
|
if (this.started) {
|
||||||
|
throw new Error('Router already started!');
|
||||||
|
}
|
||||||
|
this.started = true;
|
||||||
|
let locationBar = new LocationBar();
|
||||||
|
locationBar.onChange(p => this.handleLocationChange(p));
|
||||||
|
locationBar.start({
|
||||||
|
root: location.pathname
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLocationChange(pathString) {
|
||||||
|
let url = new URL(
|
||||||
|
pathString,
|
||||||
|
`${location.protocol}//${location.host}${location.pathname}`
|
||||||
|
)
|
||||||
|
|
||||||
|
let oldLocation = this.currentLocation;
|
||||||
|
|
||||||
|
let newLocation = {
|
||||||
|
url: url,
|
||||||
|
path: url.pathname,
|
||||||
|
queryString: url.search.replace(/^\?/, ''),
|
||||||
|
params: paramsToObject(url.searchParams)
|
||||||
|
};
|
||||||
|
|
||||||
|
this.currentLocation = newLocation;
|
||||||
|
|
||||||
|
if (!oldLocation) {
|
||||||
|
this.doPathChange(newLocation.path, null, newLocation);
|
||||||
|
this.doParamsChange(newLocation.params, {}, newLocation);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldLocation.path !== newLocation.path) {
|
||||||
|
this.doPathChange(
|
||||||
|
newLocation.path,
|
||||||
|
oldLocation.path,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!_.isEqual(oldLocation.params, newLocation.params)) {
|
||||||
|
this.doParamsChange(
|
||||||
|
newLocation.params,
|
||||||
|
oldLocation.params,
|
||||||
|
newLocation
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doPathChange(newPath, oldPath, newLocation) {
|
||||||
|
let route = this.routes.filter(r => r.matcher.test(newPath))[0];
|
||||||
|
if (route) {
|
||||||
|
route.callback(newPath, route.matcher.exec(newPath));
|
||||||
|
}
|
||||||
|
this.emit('change:path', newPath, oldPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
doParamsChange(newParams, oldParams, newLocation) {
|
||||||
|
let changedParams = {};
|
||||||
|
for (let [key, value] of Object.entries(newParams)) {
|
||||||
|
if (value !== oldParams[key]) {
|
||||||
|
changedParams[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let [key, value] of Object.entries(oldParams)) {
|
||||||
|
if (!newParams.hasOwnProperty(key)) {
|
||||||
|
changedParams[key] = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.emit('change:params', newParams, oldParams, changedParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update route params. Takes an object of updates. New parameters
|
||||||
|
*/
|
||||||
|
updateParams(updateParams) {
|
||||||
|
let searchParams = this.currentLocation.url.searchParams;
|
||||||
|
for (let [key, value] of Object.entries(updateParams)) {
|
||||||
|
if (typeof value === 'undefined') {
|
||||||
|
searchParams.delete(key);
|
||||||
|
} else {
|
||||||
|
searchParams.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setQueryString(searchParams.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
getParams() {
|
||||||
|
return this.currentLocation.params;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(path, params) {
|
||||||
|
let searchParams = this.currentLocation.url.searchParams;
|
||||||
|
for (let [key, value] of Object.entries(params)) {
|
||||||
|
if (typeof value === 'undefined') {
|
||||||
|
searchParams.delete(key);
|
||||||
|
} else {
|
||||||
|
searchParams.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.set(path, searchParams.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
set(path, queryString) {
|
||||||
|
location.hash = `${path}?${queryString}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
setQueryString(queryString) {
|
||||||
|
this.set(this.currentLocation.path, queryString);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPath(path) {
|
||||||
|
this.set(path, this.currentLocation.queryString);
|
||||||
|
}
|
||||||
|
|
||||||
|
route(matcher, callback) {
|
||||||
|
this.routes.push({matcher, callback});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ApplicationRouter;
|
Loading…
Reference in New Issue
Block a user