mirror of
https://github.com/nasa/openmct.git
synced 2024-12-18 20:57: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-jasmine": "^1.1.2",
|
||||
"karma-webpack": "^3.0.0",
|
||||
"location-bar": "^3.0.1",
|
||||
"lodash": "^3.10.1",
|
||||
"markdown-toc": "^0.11.7",
|
||||
"marked": "^0.3.5",
|
||||
|
@ -73,15 +73,6 @@ define([
|
||||
legacyRegistry.register("platform/commonUI/browse", {
|
||||
"extensions": {
|
||||
"routes": [
|
||||
{
|
||||
"when": "/browse/:ids*?",
|
||||
"template": browseTemplate,
|
||||
"reloadOnSearch": false
|
||||
},
|
||||
{
|
||||
"when": "",
|
||||
"redirectTo": "/browse/"
|
||||
}
|
||||
],
|
||||
"constants": [
|
||||
{
|
||||
|
@ -55,16 +55,16 @@ define(
|
||||
navigatedObject = this.navigationService.getNavigation(),
|
||||
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()) {
|
||||
return this.editModeBlacklist.indexOf(actionMetadata.key) === -1;
|
||||
} else {
|
||||
//Target is in the context menu
|
||||
return this.nonEditContextBlacklist.indexOf(actionMetadata.key) === -1;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
// } else {
|
||||
// return true;
|
||||
// }
|
||||
};
|
||||
|
||||
return EditContextualActionPolicy;
|
||||
|
10
src/MCT.js
10
src/MCT.js
@ -35,6 +35,7 @@ define([
|
||||
'./ui/registries/ViewRegistry',
|
||||
'./ui/registries/InspectorViewRegistry',
|
||||
'./ui/registries/ToolbarRegistry',
|
||||
'./ui/router/ApplicationRouter',
|
||||
'../platform/framework/src/Main',
|
||||
'./styles-new/core.scss',
|
||||
'./ui/components/layout/Layout.vue',
|
||||
@ -54,6 +55,7 @@ define([
|
||||
ViewRegistry,
|
||||
InspectorViewRegistry,
|
||||
ToolbarRegistry,
|
||||
ApplicationRouter,
|
||||
Main,
|
||||
coreStyles,
|
||||
Layout,
|
||||
@ -296,6 +298,12 @@ define([
|
||||
|
||||
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
|
||||
* is started.
|
||||
@ -312,11 +320,11 @@ define([
|
||||
console.log('Attaching adapter');
|
||||
installVueAdapter(appLayout, this);
|
||||
|
||||
this.router.start();
|
||||
this.emit('start');
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (object.getId() !== 'ROOT') {
|
||||
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 {
|
||||
constructor(layout, openmct) {
|
||||
this.openmct = openmct;
|
||||
@ -36,12 +66,6 @@ define([
|
||||
this.navigationService = this.$injector.get('navigationService');
|
||||
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.$injector.get('templates[]').forEach((t) => {
|
||||
this.templateMap[t.key] = this.templateMap[t.key] || t;
|
||||
@ -49,50 +73,34 @@ define([
|
||||
|
||||
var $rootScope = this.$injector.get('$rootScope');
|
||||
this.scope = $rootScope.$new();
|
||||
this.scope.representation = {};
|
||||
|
||||
|
||||
this.run();
|
||||
|
||||
this.templateLinker.link(
|
||||
this.scope,
|
||||
angular.element(layout.$refs.mainContainer),
|
||||
this.templateMap["browseObject"]
|
||||
);
|
||||
openmct.router.route(/^\/browse\/(.*)$/, (path, results) => {
|
||||
let navigatePath = results[1];
|
||||
if (!navigatePath) {
|
||||
navigatePath = 'mine';
|
||||
}
|
||||
this.navigateToPath(navigatePath);
|
||||
});
|
||||
|
||||
this.navigationService.addListener(o => this.navigateToObject(o));
|
||||
this.getObject('ROOT')
|
||||
.then(rootObject => {
|
||||
this.rootObject = rootObject;
|
||||
return getLastChildIfRoot(rootObject);
|
||||
}
|
||||
|
||||
navigateToPath(path) {
|
||||
if (!Array.isArray(path)) {
|
||||
path = path.split('/');
|
||||
}
|
||||
return this.getObject('ROOT')
|
||||
.then(root => {
|
||||
return findViaComposition(root, path);
|
||||
})
|
||||
.then(o => {
|
||||
this.navigationService.setNavigation(o, true);
|
||||
.then(getLastChildIfRoot)
|
||||
.then(object => {
|
||||
this.setMainViewObject(object);
|
||||
});
|
||||
// this.navigateToRoot();
|
||||
}
|
||||
|
||||
run() {
|
||||
// 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
|
||||
setMainViewObject(object) {
|
||||
this.scope.domainObject = object;
|
||||
this.scope.navigatedObject = object;
|
||||
this.templateLinker.link(
|
||||
@ -100,84 +108,39 @@ define([
|
||||
angular.element(this.layout.$refs.mainContainer),
|
||||
this.templateMap["browseObject"]
|
||||
);
|
||||
// this.scope.navigatedObject = object;
|
||||
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() {
|
||||
this.$timeout(function () {
|
||||
// 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) {
|
||||
return this.objectService.getObjects([id])
|
||||
.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