Compare commits
24 Commits
fix-fileSa
...
bugfix/iss
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
064e517031 | ||
|
|
7096710b1f | ||
|
|
ecfbabcfe3 | ||
|
|
a76b843fde | ||
|
|
7f0367b838 | ||
|
|
4e7debabb1 | ||
|
|
384e36920c | ||
|
|
d4429f9686 | ||
|
|
0b2d08078b | ||
|
|
3bbc9e1582 | ||
|
|
af0420361b | ||
|
|
896f0ca3f4 | ||
|
|
28c5405a01 | ||
|
|
d114353556 | ||
|
|
f40398807e | ||
|
|
81f440e1e6 | ||
|
|
c6d6400131 | ||
|
|
55828af1ec | ||
|
|
34b951f4c6 | ||
|
|
a7d4006fee | ||
|
|
a71485f820 | ||
|
|
04c3728eff | ||
|
|
afa89ae6b5 | ||
|
|
58844799be |
@@ -2,7 +2,7 @@ version: 2.1
|
||||
executors:
|
||||
pw-focal-development:
|
||||
docker:
|
||||
- image: mcr.microsoft.com/playwright:v1.18.1-focal
|
||||
- image: mcr.microsoft.com/playwright:v1.19.1-focal
|
||||
environment:
|
||||
NODE_ENV: development # Needed to ensure 'dist' folder created and devDependencies installed
|
||||
parameters:
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
node-version: <<parameters.node-version>>
|
||||
- run: npm audit --audit-level=low
|
||||
- generate_and_store_version_and_filesystem_artifacts
|
||||
node14-lint:
|
||||
lint:
|
||||
parameters:
|
||||
node-version:
|
||||
type: string
|
||||
@@ -141,8 +141,8 @@ jobs:
|
||||
workflows:
|
||||
overall-circleci-commit-status: #These jobs run on every commit
|
||||
jobs:
|
||||
- node14-lint:
|
||||
node-version: lts/fermium
|
||||
- lint:
|
||||
node-version: lts/gallium
|
||||
- unit-test:
|
||||
name: node12-chrome
|
||||
node-version: lts/erbium
|
||||
@@ -152,10 +152,14 @@ workflows:
|
||||
node-version: lts/fermium
|
||||
browser: ChromeHeadless
|
||||
post-steps:
|
||||
- upload_code_covio
|
||||
- upload_code_covio
|
||||
- unit-test:
|
||||
name: node16-chrome
|
||||
node-version: lts/gallium
|
||||
browser: ChromeHeadless
|
||||
- e2e-test:
|
||||
name: e2e-ci
|
||||
node-version: lts/fermium
|
||||
node-version: lts/gallium
|
||||
suite: ci
|
||||
the-nightly: #These jobs do not run on PRs, but against master at night
|
||||
jobs:
|
||||
@@ -175,11 +179,15 @@ workflows:
|
||||
name: node14-chrome-nightly
|
||||
node-version: lts/fermium
|
||||
browser: ChromeHeadless
|
||||
- unit-test:
|
||||
name: node16-chrome-nightly
|
||||
node-version: lts/gallium
|
||||
browser: ChromeHeadless
|
||||
- npm-audit:
|
||||
node-version: lts/fermium
|
||||
node-version: lts/gallium
|
||||
- e2e-test:
|
||||
name: e2e-full-nightly
|
||||
node-version: lts/fermium
|
||||
node-version: lts/gallium
|
||||
suite: full
|
||||
triggers:
|
||||
- schedule:
|
||||
|
||||
19
.github/ISSUE_TEMPLATE/bug_report.md
vendored
19
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -17,15 +17,6 @@ assignees: ''
|
||||
#### Expected vs Current Behavior
|
||||
<!--- Tell us what should have happened -->
|
||||
|
||||
#### Impact Check List
|
||||
<!--- Please select from the following options -->
|
||||
|
||||
- [ ] Data loss or misrepresented data?
|
||||
- [ ] Regression? Did this used to work or has it always been broken?
|
||||
- [ ] Is there a workaround available?
|
||||
- [ ] Does this impact a critical component?
|
||||
- [ ] Is this just a visual bug with no functional impact?
|
||||
|
||||
#### Steps to Reproduce
|
||||
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
|
||||
<!--- reproduce this bug. Include code to reproduce, if relevant -->
|
||||
@@ -35,10 +26,20 @@ assignees: ''
|
||||
4.
|
||||
|
||||
#### Environment
|
||||
<!--- If encountered on local machine, execute the following:
|
||||
<!--- npx envinfo --system --browsers --npmPackages --binaries --languages --markdown -->
|
||||
* Open MCT Version: <!--- date of build, version, or SHA -->
|
||||
* Deployment Type: <!--- npm dev? VIPER Dev? openmct-yamcs? -->
|
||||
* OS:
|
||||
* Browser:
|
||||
|
||||
#### Impact Check List
|
||||
<!--- Please select from the following options -->
|
||||
- [ ] Data loss or misrepresented data?
|
||||
- [ ] Regression? Did this used to work or has it always been broken?
|
||||
- [ ] Is there a workaround available?
|
||||
- [ ] Does this impact a critical component?
|
||||
- [ ] Is this just a visual bug with no functional impact?
|
||||
|
||||
#### Additional Information
|
||||
<!--- Include any screenshots, gifs, or logs which will expedite triage -->
|
||||
|
||||
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@@ -11,6 +11,8 @@ updates:
|
||||
- "dependencies"
|
||||
- "pr:e2e"
|
||||
- "pr:daveit"
|
||||
- "pr:visual"
|
||||
- "pr:platform"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
|
||||
19
.github/workflows/e2e-pr.yml
vendored
19
.github/workflows/e2e-pr.yml
vendored
@@ -2,15 +2,22 @@ name: "e2e-pr"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [ labeled ]
|
||||
types:
|
||||
- labeled
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
e2e-full:
|
||||
if: ${{ github.event.label.name == 'pr:e2e' }}
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
steps:
|
||||
- name: Trigger Success
|
||||
uses: actions/github-script@v5
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
@@ -22,7 +29,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '16'
|
||||
- run: npx playwright install-deps
|
||||
- run: npm install
|
||||
- run: npm run test:e2e:full
|
||||
@@ -32,7 +39,7 @@ jobs:
|
||||
path: test-results
|
||||
- name: Test success
|
||||
if: ${{ success() }}
|
||||
uses: actions/github-script@v5
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
@@ -43,7 +50,7 @@ jobs:
|
||||
})
|
||||
- name: Test failure
|
||||
if: ${{ failure() }}
|
||||
uses: actions/github-script@v5
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
|
||||
3
.github/workflows/e2e-visual.yml
vendored
3
.github/workflows/e2e-visual.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
pull_request:
|
||||
types:
|
||||
- labeled
|
||||
- opened
|
||||
schedule:
|
||||
- cron: '28 21 * * 1-5'
|
||||
|
||||
@@ -15,7 +16,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '16'
|
||||
- run: npx playwright install-deps
|
||||
- run: npm install
|
||||
- name: Run the e2e visual tests
|
||||
|
||||
2
.github/workflows/e2e.yml
vendored
2
.github/workflows/e2e.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
ref: ${{ github.event.inputs.version }}
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '16'
|
||||
- run: npm install
|
||||
- name: Run the e2e tests
|
||||
run: npm run test:e2e:ci
|
||||
|
||||
90
.github/workflows/lighthouse.yml
vendored
90
.github/workflows/lighthouse.yml
vendored
@@ -5,16 +5,96 @@ on:
|
||||
version:
|
||||
description: 'Which branch do you want to test?' # Limited to branch for now
|
||||
required: false
|
||||
default: 'master'
|
||||
default: 'master'
|
||||
pull_request:
|
||||
types:
|
||||
- labeled
|
||||
schedule:
|
||||
- cron: '28 21 * * 1-5'
|
||||
jobs:
|
||||
lighthouse:
|
||||
lighthouse-pr:
|
||||
if: ${{ github.event.label.name == 'pr:lighthouse' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Master for Baseline
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: master #explicitly checkout master for baseline
|
||||
- name: Install Node 14
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
|
||||
- name: npm install with lighthouse cli
|
||||
run: npm install && npm install -g @lhci/cli
|
||||
- name: Run lhci against master to generate baseline and ignore exit codes
|
||||
run: lhci autorun || true
|
||||
- name: Perform clean checkout of PR
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
clean: true
|
||||
- name: Install Node version which is compatible with PR
|
||||
uses: actions/setup-node@v2
|
||||
- name: npm install with lighthouse cli
|
||||
run: npm install && npm install -g @lhci/cli
|
||||
- name: Run lhci with PR
|
||||
run: lhci autorun
|
||||
env:
|
||||
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
|
||||
lighthouse-nightly:
|
||||
if: ${{ github.event.schedule }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Node 14
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
|
||||
- name: npm install with lighthouse cli
|
||||
run: npm install && npm install -g @lhci/cli
|
||||
- name: Run lhci against master to generate baseline
|
||||
run: lhci autorun
|
||||
env:
|
||||
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
|
||||
lighthouse-dispatch:
|
||||
if: ${{ github.event.workflow_dispatch }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.inputs.version }}
|
||||
- uses: actions/setup-node@v2
|
||||
- name: Install Node 14
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- run: npm install && npm install -g @lhci/cli #Don't want to include this in our deps
|
||||
- run: lhci autorun
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
|
||||
- name: npm install with lighthouse cli
|
||||
run: npm install && npm install -g @lhci/cli
|
||||
- name: Run lhci against master to generate baseline
|
||||
run: lhci autorun
|
||||
|
||||
4
.github/workflows/npm-prerelease.yml
vendored
4
.github/workflows/npm-prerelease.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
node-version: 16
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
node-version: 16
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm install
|
||||
- run: npm publish --access public --tag unstable
|
||||
|
||||
34
.github/workflows/pr-platform.yml
vendored
Normal file
34
.github/workflows/pr-platform.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: "pr-platform"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [ labeled ]
|
||||
|
||||
jobs:
|
||||
e2e-full:
|
||||
if: ${{ github.event.label.name == 'pr:platform' }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macos-latest
|
||||
- windows-latest
|
||||
node_version:
|
||||
- 12
|
||||
- 14
|
||||
- 16
|
||||
architecture:
|
||||
- x64
|
||||
name: Node ${{ matrix.node_version }} - ${{ matrix.architecture }} on ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
architecture: ${{ matrix.architecture }}
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
- run: npm run lint
|
||||
7
.github/workflows/prcop.yml
vendored
7
.github/workflows/prcop.yml
vendored
@@ -1,12 +1,15 @@
|
||||
name: PRcop
|
||||
name: PRCop
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- edited
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
- review_requested
|
||||
- review_request_removed
|
||||
pull_request_review_comment:
|
||||
types:
|
||||
- created
|
||||
@@ -14,7 +17,7 @@ on:
|
||||
jobs:
|
||||
prcop:
|
||||
runs-on: ubuntu-latest
|
||||
name: PRcop
|
||||
name: Template Check
|
||||
steps:
|
||||
- name: Linting Pull Request
|
||||
uses: makaroni4/prcop@v1.0.35
|
||||
|
||||
@@ -190,11 +190,12 @@
|
||||
openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay']));
|
||||
openmct.install(openmct.plugins.ObjectMigration());
|
||||
openmct.install(openmct.plugins.ClearData(
|
||||
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
|
||||
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked', 'example.imagery'],
|
||||
{indicator: true}
|
||||
));
|
||||
openmct.install(openmct.plugins.Clock({ enableClockIndicator: true }));
|
||||
openmct.install(openmct.plugins.Timer());
|
||||
openmct.install(openmct.plugins.StaticRootPlugin({ namespace: 'something', exportUrl: './dist/static-root.json' }));
|
||||
openmct.start();
|
||||
</script>
|
||||
</html>
|
||||
|
||||
24
package.json
24
package.json
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"name": "openmct",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1-SNAPSHOT",
|
||||
"description": "The Open MCT core platform",
|
||||
"devDependencies": {
|
||||
"@braintree/sanitize-url": "5.0.2",
|
||||
"@percy/cli": "1.0.0-beta.73",
|
||||
"@percy/cli": "1.0.0-beta.75",
|
||||
"@percy/playwright": "1.0.1",
|
||||
"@playwright/test": "1.18.1",
|
||||
"allure-playwright": "2.0.0-beta.14",
|
||||
"@playwright/test": "1.19.1",
|
||||
"allure-playwright": "2.0.0-beta.15",
|
||||
"babel-eslint": "10.1.0",
|
||||
"comma-separated-values": "3.6.4",
|
||||
"copy-webpack-plugin": "10.2.0",
|
||||
"core-js": "3.20.3",
|
||||
"cross-env": "6.0.3",
|
||||
"cross-env": "7.0.3",
|
||||
"css-loader": "4.0.0",
|
||||
"d3-axis": "1.0.x",
|
||||
"d3-scale": "1.0.x",
|
||||
@@ -25,7 +25,7 @@
|
||||
"exports-loader": "0.7.0",
|
||||
"express": "4.13.1",
|
||||
"file-loader": "6.1.0",
|
||||
"file-saver": "1.3.8",
|
||||
"file-saver": "2.0.5",
|
||||
"git-rev-sync": "1.4.0",
|
||||
"html-loader": "0.5.5",
|
||||
"html2canvas": "1.4.1",
|
||||
@@ -47,12 +47,11 @@
|
||||
"location-bar": "^3.0.1",
|
||||
"lodash": "^4.17.12",
|
||||
"mini-css-extract-plugin": "2.4.5",
|
||||
"moment": "2.25.3",
|
||||
"moment": "2.29.1",
|
||||
"moment-duration-format": "^2.2.2",
|
||||
"moment-timezone": "0.5.28",
|
||||
"node-bourbon": "^4.2.3",
|
||||
"painterro": "^1.2.56",
|
||||
"playwright": "^1.18.1",
|
||||
"plotly.js-basic-dist": "^2.5.0",
|
||||
"plotly.js-gl2d-dist": "^2.5.0",
|
||||
"printj": "^1.2.1",
|
||||
@@ -64,11 +63,11 @@
|
||||
"sinon": "13.0.1",
|
||||
"style-loader": "^1.0.1",
|
||||
"uuid": "^3.3.3",
|
||||
"vue": "2.5.6",
|
||||
"vue": "2.6.14",
|
||||
"vue-eslint-parser": "8.2.0",
|
||||
"vue-loader": "15.9.8",
|
||||
"vue-template-compiler": "2.5.6",
|
||||
"webpack": "5.67.0",
|
||||
"vue-template-compiler": "2.6.14",
|
||||
"webpack": "5.68.0",
|
||||
"webpack-cli": "4.9.2",
|
||||
"webpack-dev-middleware": "^3.1.3",
|
||||
"webpack-hot-middleware": "^2.22.3",
|
||||
@@ -84,6 +83,7 @@
|
||||
"build:prod": "cross-env webpack --config webpack.prod.js",
|
||||
"build:dev": "webpack --config webpack.dev.js",
|
||||
"build:watch": "webpack --config webpack.dev.js --watch",
|
||||
"info": "npx envinfo --system --browsers --npmPackages --binaries --languages --markdown",
|
||||
"test": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run",
|
||||
"test:debug": "cross-env NODE_ENV=debug karma start --no-single-run",
|
||||
"test:coverage": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" COVERAGE=true karma start --single-run",
|
||||
@@ -105,7 +105,7 @@
|
||||
"url": "https://github.com/nasa/openmct.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20.1 <15.0.0"
|
||||
"node": ">=12.22.0"
|
||||
},
|
||||
"author": "",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import CSV from 'comma-separated-values';
|
||||
import {saveAs} from 'saveAs/FileSaver';
|
||||
import {saveAs} from 'saveAs';
|
||||
|
||||
class CSVExporter {
|
||||
export(rows, options) {
|
||||
|
||||
@@ -31,7 +31,7 @@ function replaceDotsWithUnderscores(filename) {
|
||||
return filename.replace(regex, '_');
|
||||
}
|
||||
|
||||
import {saveAs} from 'saveAs/FileSaver';
|
||||
import {saveAs} from 'saveAs';
|
||||
import html2canvas from 'html2canvas';
|
||||
import uuid from 'uuid';
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import {saveAs} from 'saveAs/FileSaver';
|
||||
import {saveAs} from 'saveAs';
|
||||
|
||||
class JSONExporter {
|
||||
export(obj, options) {
|
||||
|
||||
@@ -185,10 +185,14 @@ describe('The Clear Data Plugin:', () => {
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
|
||||
clearDataPlugin = new ClearDataPlugin(
|
||||
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
|
||||
{indicator: true}
|
||||
);
|
||||
clearDataPlugin = new ClearDataPlugin([
|
||||
'table',
|
||||
'telemetry.plot.overlay',
|
||||
'telemetry.plot.stacked',
|
||||
'example.imagery'
|
||||
], {
|
||||
indicator: true
|
||||
});
|
||||
openmct.install(clearDataPlugin);
|
||||
appHolder = document.createElement('div');
|
||||
document.body.appendChild(appHolder);
|
||||
|
||||
@@ -30,6 +30,7 @@ export default {
|
||||
this.timeSystemChange = this.timeSystemChange.bind(this);
|
||||
this.setDataTimeContext = this.setDataTimeContext.bind(this);
|
||||
this.setDataTimeContext();
|
||||
this.openmct.objectViews.on('clearData', this.clearData);
|
||||
|
||||
// set
|
||||
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||
@@ -54,6 +55,7 @@ export default {
|
||||
}
|
||||
|
||||
this.stopFollowingDataTimeContext();
|
||||
this.openmct.objectViews.off('clearData', this.clearData);
|
||||
},
|
||||
methods: {
|
||||
setDataTimeContext() {
|
||||
@@ -151,6 +153,25 @@ export default {
|
||||
this.imageHistory = imagery;
|
||||
}
|
||||
},
|
||||
clearData(domainObjectToClear) {
|
||||
// global clearData button is accepted therefore no truthy check on inputted param
|
||||
const clearDataForObjectSelected = Boolean(domainObjectToClear);
|
||||
if (clearDataForObjectSelected) {
|
||||
const idsEqual = this.openmct.objects.areIdsEqual(
|
||||
domainObjectToClear.identifier,
|
||||
this.domainObject.identifier
|
||||
);
|
||||
if (!idsEqual) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// splice array to encourage garbage collection
|
||||
this.imageHistory.splice(0, this.imageHistory.length);
|
||||
|
||||
// requesting history effectively clears imageHistory array
|
||||
return this.requestHistory();
|
||||
},
|
||||
timeSystemChange() {
|
||||
this.timeSystem = this.timeContext.timeSystem();
|
||||
this.timeKey = this.timeSystem.key;
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
resetApplicationState,
|
||||
simulateKeyEvent
|
||||
} from 'utils/testing';
|
||||
import ClearDataPlugin from '../clearData/plugin';
|
||||
|
||||
const ONE_MINUTE = 1000 * 60;
|
||||
const TEN_MINUTES = ONE_MINUTE * 10;
|
||||
@@ -83,6 +84,7 @@ describe("The Imagery View Layouts", () => {
|
||||
let telemetryPromise;
|
||||
let telemetryPromiseResolve;
|
||||
let cleanupFirst;
|
||||
let isClearDataTriggered;
|
||||
|
||||
let openmct;
|
||||
let parent;
|
||||
@@ -201,6 +203,10 @@ describe("The Imagery View Layouts", () => {
|
||||
});
|
||||
|
||||
spyOn(openmct.telemetry, 'request').and.callFake(() => {
|
||||
if (isClearDataTriggered) {
|
||||
return [];
|
||||
}
|
||||
|
||||
telemetryPromiseResolve(imageTelemetry);
|
||||
|
||||
return telemetryPromise;
|
||||
@@ -323,6 +329,8 @@ describe("The Imagery View Layouts", () => {
|
||||
let applicableViews;
|
||||
let imageryViewProvider;
|
||||
let imageryView;
|
||||
let clearDataPlugin;
|
||||
let clearDataAction;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -330,16 +338,21 @@ describe("The Imagery View Layouts", () => {
|
||||
imageryViewProvider = applicableViews.find(viewProvider => viewProvider.key === imageryKey);
|
||||
imageryView = imageryViewProvider.view(imageryObject, [imageryObject]);
|
||||
imageryView.show(child);
|
||||
clearDataPlugin = new ClearDataPlugin(
|
||||
['example.imagery'],
|
||||
{indicator: true}
|
||||
);
|
||||
openmct.install(clearDataPlugin);
|
||||
clearDataAction = openmct.actions.getAction('clear-data-action');
|
||||
|
||||
return Vue.nextTick();
|
||||
});
|
||||
|
||||
// afterEach(() => {
|
||||
// openmct.time.stopClock();
|
||||
// openmct.router.removeListener('change:hash', resolveFunction);
|
||||
//
|
||||
// imageryView.destroy();
|
||||
// });
|
||||
afterEach(() => {
|
||||
isClearDataTriggered = false;
|
||||
// openmct.time.stopClock();
|
||||
// openmct.router.removeListener('change:hash', resolveFunction);
|
||||
// imageryView.destroy();
|
||||
});
|
||||
|
||||
it("on mount should show the the most recent image", (done) => {
|
||||
//Looks like we need Vue.nextTick here so that computed properties settle down
|
||||
@@ -470,6 +483,21 @@ describe("The Imagery View Layouts", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
it('clear data action is installed', () => {
|
||||
expect(clearDataAction).toBeDefined();
|
||||
});
|
||||
|
||||
it('on clearData action should clear data for object is selected', (done) => {
|
||||
expect(parent.querySelectorAll('.c-imagery__thumb').length).not.toBe(0);
|
||||
openmct.objectViews.on('clearData', async (_domainObject) => {
|
||||
await Vue.nextTick();
|
||||
expect(parent.querySelectorAll('.c-imagery__thumb').length).toBe(0);
|
||||
done();
|
||||
});
|
||||
// stubbed telemetry data will return empty array when true
|
||||
isClearDataTriggered = true;
|
||||
clearDataAction.invoke(imageryObject);
|
||||
});
|
||||
});
|
||||
|
||||
describe("imagery time strip view", () => {
|
||||
|
||||
@@ -596,8 +596,9 @@ export default {
|
||||
this.resetSearch();
|
||||
const notebookStorage = this.createNotebookStorageObject();
|
||||
this.updateDefaultNotebook(notebookStorage);
|
||||
const id = addNotebookEntry(this.openmct, this.domainObject, notebookStorage, embed);
|
||||
this.focusEntryId = id;
|
||||
addNotebookEntry(this.openmct, this.domainObject, notebookStorage, embed).then(id => {
|
||||
this.focusEntryId = id;
|
||||
});
|
||||
},
|
||||
orientationChange() {
|
||||
this.formatSidebar();
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
>
|
||||
<div class="c-ne__time-and-content">
|
||||
<div class="c-ne__time">
|
||||
<template v-if="entry.createdBy">
|
||||
<span class="c-icon icon-person">{{ entry.createdBy }}</span>
|
||||
</template>
|
||||
<span>{{ createdOnDate }}</span>
|
||||
<span>{{ createdOnTime }}</span>
|
||||
</div>
|
||||
@@ -182,7 +185,7 @@ export default {
|
||||
this.dropOnEntry = this.dropOnEntry.bind(this);
|
||||
},
|
||||
methods: {
|
||||
addNewEmbed(objectPath) {
|
||||
async addNewEmbed(objectPath) {
|
||||
const bounds = this.openmct.time.bounds();
|
||||
const snapshotMeta = {
|
||||
bounds,
|
||||
@@ -190,7 +193,7 @@ export default {
|
||||
objectPath,
|
||||
openmct: this.openmct
|
||||
};
|
||||
const newEmbed = createNewEmbed(snapshotMeta);
|
||||
const newEmbed = await createNewEmbed(snapshotMeta);
|
||||
this.entry.embeds.push(newEmbed);
|
||||
},
|
||||
cancelEditMode(event) {
|
||||
@@ -206,7 +209,7 @@ export default {
|
||||
deleteEntry() {
|
||||
this.$emit('deleteEntry', this.entry.id);
|
||||
},
|
||||
dropOnEntry($event) {
|
||||
async dropOnEntry($event) {
|
||||
event.stopImmediatePropagation();
|
||||
|
||||
const snapshotId = $event.dataTransfer.getData('openmct/snapshot/id');
|
||||
@@ -221,7 +224,7 @@ export default {
|
||||
} else {
|
||||
const data = $event.dataTransfer.getData('openmct/domain-object-path');
|
||||
const objectPath = JSON.parse(data);
|
||||
this.addNewEmbed(objectPath);
|
||||
await this.addNewEmbed(objectPath);
|
||||
}
|
||||
|
||||
this.$emit('updateEntry', this.entry);
|
||||
|
||||
@@ -41,16 +41,17 @@ export default class Snapshot {
|
||||
fullSizeImageObjectIdentifier: object.identifier,
|
||||
thumbnailImage
|
||||
};
|
||||
const embed = createNewEmbed(snapshotMeta, snapshot);
|
||||
if (notebookType === NOTEBOOK_DEFAULT) {
|
||||
const notebookStorage = getDefaultNotebook();
|
||||
createNewEmbed(snapshotMeta, snapshot).then(embed => {
|
||||
if (notebookType === NOTEBOOK_DEFAULT) {
|
||||
const notebookStorage = getDefaultNotebook();
|
||||
|
||||
this._saveToDefaultNoteBook(notebookStorage, embed);
|
||||
const notebookImageDomainObject = updateNamespaceOfDomainObject(object, notebookStorage.identifier.namespace);
|
||||
saveNotebookImageDomainObject(this.openmct, notebookImageDomainObject);
|
||||
} else {
|
||||
this._saveToNotebookSnapshots(object, embed);
|
||||
}
|
||||
this._saveToDefaultNoteBook(notebookStorage, embed);
|
||||
const notebookImageDomainObject = updateNamespaceOfDomainObject(object, notebookStorage.identifier.namespace);
|
||||
saveNotebookImageDomainObject(this.openmct, notebookImageDomainObject);
|
||||
} else {
|
||||
this._saveToNotebookSnapshots(object, embed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,26 +59,26 @@ export default class Snapshot {
|
||||
*/
|
||||
_saveToDefaultNoteBook(notebookStorage, embed) {
|
||||
this.openmct.objects.get(notebookStorage.identifier)
|
||||
.then(async (domainObject) => {
|
||||
addNotebookEntry(this.openmct, domainObject, notebookStorage, embed);
|
||||
.then((domainObject) => {
|
||||
return addNotebookEntry(this.openmct, domainObject, notebookStorage, embed).then(async () => {
|
||||
let link = notebookStorage.link;
|
||||
|
||||
let link = notebookStorage.link;
|
||||
// Backwards compatibility fix (old notebook model without link)
|
||||
if (!link) {
|
||||
link = await getDefaultNotebookLink(this.openmct, domainObject);
|
||||
notebookStorage.link = link;
|
||||
setDefaultNotebook(this.openmct, notebookStorage);
|
||||
}
|
||||
|
||||
// Backwards compatibility fix (old notebook model without link)
|
||||
if (!link) {
|
||||
link = await getDefaultNotebookLink(this.openmct, domainObject);
|
||||
notebookStorage.link = link;
|
||||
setDefaultNotebook(this.openmct, notebookStorage);
|
||||
}
|
||||
const { section, page } = getNotebookSectionAndPage(domainObject, notebookStorage.defaultSectionId, notebookStorage.defaultPageId);
|
||||
if (!section || !page) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { section, page } = getNotebookSectionAndPage(domainObject, notebookStorage.defaultSectionId, notebookStorage.defaultPageId);
|
||||
if (!section || !page) {
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultPath = `${domainObject.name} - ${section.name} - ${page.name}`;
|
||||
const msg = `Saved to Notebook ${defaultPath}`;
|
||||
this._showNotification(msg, link);
|
||||
const defaultPath = `${domainObject.name} - ${section.name} - ${page.name}`;
|
||||
const msg = `Saved to Notebook ${defaultPath}`;
|
||||
this._showNotification(msg, link);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
import objectLink from '../../../ui/mixins/object-link';
|
||||
|
||||
async function getUsername(openmct) {
|
||||
let username = '';
|
||||
|
||||
if (openmct.user.hasProvider()) {
|
||||
const user = await openmct.user.getCurrentUser();
|
||||
username = user.getName();
|
||||
}
|
||||
|
||||
return username;
|
||||
|
||||
}
|
||||
|
||||
export const DEFAULT_CLASS = 'notebook-default';
|
||||
const TIME_BOUNDS = {
|
||||
START_BOUND: 'tc.startBound',
|
||||
@@ -61,7 +73,7 @@ export function getHistoricLinkInFixedMode(openmct, bounds, historicLink) {
|
||||
return params.join('&');
|
||||
}
|
||||
|
||||
export function createNewEmbed(snapshotMeta, snapshot = '') {
|
||||
export async function createNewEmbed(snapshotMeta, snapshot = '') {
|
||||
const {
|
||||
bounds,
|
||||
link,
|
||||
@@ -83,10 +95,12 @@ export function createNewEmbed(snapshotMeta, snapshot = '') {
|
||||
});
|
||||
const name = domainObject.name;
|
||||
const type = domainObject.identifier.key;
|
||||
const createdBy = await getUsername(openmct);
|
||||
|
||||
return {
|
||||
bounds,
|
||||
createdOn: date,
|
||||
createdBy,
|
||||
cssClass,
|
||||
domainObject,
|
||||
historicLink,
|
||||
@@ -97,7 +111,7 @@ export function createNewEmbed(snapshotMeta, snapshot = '') {
|
||||
};
|
||||
}
|
||||
|
||||
export function addNotebookEntry(openmct, domainObject, notebookStorage, embed = null, entryText = '') {
|
||||
export async function addNotebookEntry(openmct, domainObject, notebookStorage, embed = null, entryText = '') {
|
||||
if (!openmct || !domainObject || !notebookStorage) {
|
||||
return;
|
||||
}
|
||||
@@ -109,10 +123,12 @@ export function addNotebookEntry(openmct, domainObject, notebookStorage, embed =
|
||||
? [embed]
|
||||
: [];
|
||||
|
||||
const createdBy = await getUsername(openmct);
|
||||
const id = `entry-${date}`;
|
||||
const entry = {
|
||||
id,
|
||||
createdOn: date,
|
||||
createdBy,
|
||||
text: entryText,
|
||||
embeds
|
||||
};
|
||||
|
||||
@@ -127,7 +127,7 @@ describe('Notebook Entries:', () => {
|
||||
expect(entries.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('addNotebookEntry adds entry', () => {
|
||||
it('addNotebookEntry adds entry', async () => {
|
||||
const unlisten = openmct.objects.observe(notebookDomainObject, '*', (object) => {
|
||||
const entries = NotebookEntries.getNotebookEntries(notebookDomainObject, selectedSection, selectedPage);
|
||||
|
||||
@@ -135,17 +135,38 @@ describe('Notebook Entries:', () => {
|
||||
unlisten();
|
||||
});
|
||||
|
||||
NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
await NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
});
|
||||
|
||||
it('getEntryPosById returns valid position', () => {
|
||||
const entryId1 = NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
it('addNotebookEntry adds active user to entry', async () => {
|
||||
const USER = 'Timmy';
|
||||
openmct.user.hasProvider = () => true;
|
||||
openmct.user.getCurrentUser = () => {
|
||||
return Promise.resolve({
|
||||
getName: () => {
|
||||
return USER;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const unlisten = openmct.objects.observe(notebookDomainObject, '*', (object) => {
|
||||
const entries = NotebookEntries.getNotebookEntries(notebookDomainObject, selectedSection, selectedPage);
|
||||
|
||||
expect(entries[0].createdBy).toEqual(USER);
|
||||
unlisten();
|
||||
});
|
||||
|
||||
await NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
});
|
||||
|
||||
it('getEntryPosById returns valid position', async () => {
|
||||
const entryId1 = await NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
const position1 = NotebookEntries.getEntryPosById(entryId1, notebookDomainObject, selectedSection, selectedPage);
|
||||
|
||||
const entryId2 = NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
const entryId2 = await NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
const position2 = NotebookEntries.getEntryPosById(entryId2, notebookDomainObject, selectedSection, selectedPage);
|
||||
|
||||
const entryId3 = NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
const entryId3 = await NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
const position3 = NotebookEntries.getEntryPosById(entryId3, notebookDomainObject, selectedSection, selectedPage);
|
||||
|
||||
const success = position1 === 0
|
||||
@@ -155,9 +176,9 @@ describe('Notebook Entries:', () => {
|
||||
expect(success).toBe(true);
|
||||
});
|
||||
|
||||
it('deleteNotebookEntries deletes correct page entries', () => {
|
||||
NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
it('deleteNotebookEntries deletes correct page entries', async () => {
|
||||
await NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
await NotebookEntries.addNotebookEntry(openmct, notebookDomainObject, notebookStorage);
|
||||
|
||||
NotebookEntries.deleteNotebookEntries(openmct, notebookDomainObject, selectedSection, selectedPage);
|
||||
const afterEntries = NotebookEntries.getNotebookEntries(notebookDomainObject, selectedSection, selectedPage);
|
||||
|
||||
@@ -151,7 +151,7 @@ define([
|
||||
|
||||
plugins.MyItems = MyItems.default;
|
||||
|
||||
plugins.StaticRootPlugin = StaticRootPlugin;
|
||||
plugins.StaticRootPlugin = StaticRootPlugin.default;
|
||||
|
||||
/**
|
||||
* A tabular view showing the latest values of multiple telemetry points at
|
||||
|
||||
@@ -1,45 +1,139 @@
|
||||
define([
|
||||
'objectUtils'
|
||||
], function (
|
||||
objectUtils
|
||||
) {
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2022, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Transforms an import json blob into a object map that can be used to
|
||||
* provide objects. Rewrites root identifier in import data with provided
|
||||
* rootIdentifier, and rewrites all child object identifiers so that they
|
||||
* exist in the same namespace as the rootIdentifier.
|
||||
*/
|
||||
import objectUtils from 'objectUtils';
|
||||
|
||||
class StaticModelProvider {
|
||||
constructor(importData, rootIdentifier) {
|
||||
this.objectMap = {};
|
||||
this.rewriteModel(importData, rootIdentifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an import json blob into a object map that can be used to
|
||||
* provide objects. Rewrites root identifier in import data with provided
|
||||
* rootIdentifier, and rewrites all child object identifiers so that they
|
||||
* exist in the same namespace as the rootIdentifier.
|
||||
* Standard "Get".
|
||||
*/
|
||||
function rewriteObjectIdentifiers(importData, rootIdentifier) {
|
||||
const rootId = importData.rootId;
|
||||
let objectString = JSON.stringify(importData.openmct);
|
||||
get(identifier) {
|
||||
const keyString = objectUtils.makeKeyString(identifier);
|
||||
if (this.objectMap[keyString]) {
|
||||
return this.objectMap[keyString];
|
||||
}
|
||||
|
||||
Object.keys(importData.openmct).forEach(function (originalId, i) {
|
||||
let newId;
|
||||
if (originalId === rootId) {
|
||||
newId = objectUtils.makeKeyString(rootIdentifier);
|
||||
} else {
|
||||
newId = objectUtils.makeKeyString({
|
||||
namespace: rootIdentifier.namespace,
|
||||
key: i
|
||||
throw new Error(keyString + ' not found in import models.');
|
||||
}
|
||||
|
||||
parseObjectLeaf(objectLeaf, idMap, namespace) {
|
||||
Object.keys(objectLeaf).forEach((nodeKey) => {
|
||||
if (idMap.get(nodeKey)) {
|
||||
const newIdentifier = objectUtils.makeKeyString({
|
||||
namespace,
|
||||
key: idMap.get(nodeKey)
|
||||
});
|
||||
}
|
||||
|
||||
while (objectString.indexOf(originalId) !== -1) {
|
||||
objectString = objectString.replace(
|
||||
'"' + originalId + '"',
|
||||
'"' + newId + '"'
|
||||
);
|
||||
objectLeaf[newIdentifier] = { ...objectLeaf[nodeKey] };
|
||||
delete objectLeaf[nodeKey];
|
||||
objectLeaf[newIdentifier] = this.parseTreeLeaf(newIdentifier, objectLeaf[newIdentifier], idMap, namespace);
|
||||
} else {
|
||||
objectLeaf[nodeKey] = this.parseTreeLeaf(nodeKey, objectLeaf[nodeKey], idMap, namespace);
|
||||
}
|
||||
});
|
||||
|
||||
return JSON.parse(objectString);
|
||||
return objectLeaf;
|
||||
}
|
||||
|
||||
parseArrayLeaf(arrayLeaf, idMap, namespace) {
|
||||
return arrayLeaf.map((leafValue, index) => this.parseTreeLeaf(
|
||||
null, leafValue, idMap, namespace));
|
||||
}
|
||||
|
||||
parseBranchedLeaf(branchedLeafValue, idMap, namespace) {
|
||||
if (Array.isArray(branchedLeafValue)) {
|
||||
return this.parseArrayLeaf(branchedLeafValue, idMap, namespace);
|
||||
} else {
|
||||
return this.parseObjectLeaf(branchedLeafValue, idMap, namespace);
|
||||
}
|
||||
}
|
||||
|
||||
parseTreeLeaf(leafKey, leafValue, idMap, namespace) {
|
||||
const hasChild = typeof leafValue === 'object';
|
||||
if (hasChild) {
|
||||
return this.parseBranchedLeaf(leafValue, idMap, namespace);
|
||||
}
|
||||
|
||||
if (leafKey === 'key') {
|
||||
return idMap.get(leafValue);
|
||||
} else if (leafKey === 'namespace') {
|
||||
return namespace;
|
||||
} else if (leafKey === 'location') {
|
||||
if (idMap.get(leafValue)) {
|
||||
const newLocationIdentifier = objectUtils.makeKeyString({
|
||||
namespace,
|
||||
key: idMap.get(leafValue)
|
||||
});
|
||||
|
||||
return newLocationIdentifier;
|
||||
}
|
||||
|
||||
return null;
|
||||
} else if (idMap.get(leafValue)) {
|
||||
const newIdentifier = objectUtils.makeKeyString({
|
||||
namespace,
|
||||
key: idMap.get(leafValue)
|
||||
});
|
||||
|
||||
return newIdentifier;
|
||||
} else {
|
||||
return leafValue;
|
||||
}
|
||||
}
|
||||
|
||||
rewriteObjectIdentifiers(importData, rootIdentifier) {
|
||||
const namespace = rootIdentifier.namespace;
|
||||
const idMap = new Map();
|
||||
const objectTree = importData.openmct;
|
||||
|
||||
Object.keys(objectTree).forEach((originalId, index) => {
|
||||
let newId = index.toString();
|
||||
if (originalId === importData.rootId) {
|
||||
newId = rootIdentifier.key;
|
||||
}
|
||||
|
||||
idMap.set(originalId, newId);
|
||||
});
|
||||
|
||||
const newTree = this.parseTreeLeaf(null, objectTree, idMap, namespace);
|
||||
|
||||
return newTree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all objects in an object make from old format objects to new
|
||||
* format objects.
|
||||
*/
|
||||
function convertToNewObjects(oldObjectMap) {
|
||||
convertToNewObjects(oldObjectMap) {
|
||||
return Object.keys(oldObjectMap)
|
||||
.reduce(function (newObjectMap, key) {
|
||||
newObjectMap[key] = objectUtils.toNewFormat(oldObjectMap[key], key);
|
||||
@@ -49,7 +143,7 @@ define([
|
||||
}
|
||||
|
||||
/* Set the root location correctly for a top-level object */
|
||||
function setRootLocation(objectMap, rootIdentifier) {
|
||||
setRootLocation(objectMap, rootIdentifier) {
|
||||
objectMap[objectUtils.makeKeyString(rootIdentifier)].location = 'ROOT';
|
||||
|
||||
return objectMap;
|
||||
@@ -59,24 +153,11 @@ define([
|
||||
* Takes importData (as provided by the ImportExport plugin) and exposes
|
||||
* an object provider to fetch those objects.
|
||||
*/
|
||||
function StaticModelProvider(importData, rootIdentifier) {
|
||||
const oldFormatObjectMap = rewriteObjectIdentifiers(importData, rootIdentifier);
|
||||
const newFormatObjectMap = convertToNewObjects(oldFormatObjectMap);
|
||||
this.objectMap = setRootLocation(newFormatObjectMap, rootIdentifier);
|
||||
rewriteModel(importData, rootIdentifier) {
|
||||
const oldFormatObjectMap = this.rewriteObjectIdentifiers(importData, rootIdentifier);
|
||||
const newFormatObjectMap = this.convertToNewObjects(oldFormatObjectMap);
|
||||
this.objectMap = this.setRootLocation(newFormatObjectMap, rootIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard "Get".
|
||||
*/
|
||||
StaticModelProvider.prototype.get = function (identifier) {
|
||||
const keyString = objectUtils.makeKeyString(identifier);
|
||||
if (this.objectMap[keyString]) {
|
||||
return this.objectMap[keyString];
|
||||
}
|
||||
|
||||
throw new Error(keyString + ' not found in import models.');
|
||||
};
|
||||
|
||||
return StaticModelProvider;
|
||||
|
||||
});
|
||||
export default StaticModelProvider;
|
||||
|
||||
@@ -1,133 +1,149 @@
|
||||
define([
|
||||
'./StaticModelProvider',
|
||||
'./static-provider-test.json'
|
||||
], function (
|
||||
StaticModelProvider,
|
||||
testStaticData
|
||||
) {
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2022, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
describe('StaticModelProvider', function () {
|
||||
import testStaticData from './static-provider-test.json';
|
||||
import StaticModelProvider from './StaticModelProvider';
|
||||
|
||||
let staticProvider;
|
||||
describe('StaticModelProvider', function () {
|
||||
|
||||
let staticProvider;
|
||||
|
||||
beforeEach(function () {
|
||||
const staticData = JSON.parse(JSON.stringify(testStaticData));
|
||||
staticProvider = new StaticModelProvider(staticData, {
|
||||
namespace: 'my-import',
|
||||
key: 'root'
|
||||
});
|
||||
});
|
||||
|
||||
describe('rootObject', function () {
|
||||
let rootModel;
|
||||
|
||||
beforeEach(function () {
|
||||
const staticData = JSON.parse(JSON.stringify(testStaticData));
|
||||
staticProvider = new StaticModelProvider(staticData, {
|
||||
rootModel = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: 'root'
|
||||
});
|
||||
});
|
||||
|
||||
describe('rootObject', function () {
|
||||
let rootModel;
|
||||
it('is located at top level', function () {
|
||||
expect(rootModel.location).toBe('ROOT');
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
rootModel = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: 'root'
|
||||
});
|
||||
});
|
||||
|
||||
it('is located at top level', function () {
|
||||
expect(rootModel.location).toBe('ROOT');
|
||||
});
|
||||
|
||||
it('has new-format identifier', function () {
|
||||
expect(rootModel.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: 'root'
|
||||
});
|
||||
});
|
||||
|
||||
it('has new-format composition', function () {
|
||||
expect(rootModel.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
expect(rootModel.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '2'
|
||||
});
|
||||
it('has new-format identifier', function () {
|
||||
expect(rootModel.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: 'root'
|
||||
});
|
||||
});
|
||||
|
||||
describe('childObjects', function () {
|
||||
let swg;
|
||||
let layout;
|
||||
let fixed;
|
||||
|
||||
beforeEach(function () {
|
||||
swg = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
layout = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: '2'
|
||||
});
|
||||
fixed = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: '3'
|
||||
});
|
||||
it('has new-format composition', function () {
|
||||
expect(rootModel.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
|
||||
it('match expected ordering', function () {
|
||||
// this is a sanity check to make sure the identifiers map in
|
||||
// the correct order.
|
||||
expect(swg.type).toBe('generator');
|
||||
expect(layout.type).toBe('layout');
|
||||
expect(fixed.type).toBe('telemetry.fixed');
|
||||
expect(rootModel.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '2'
|
||||
});
|
||||
|
||||
it('have new-style identifiers', function () {
|
||||
expect(swg.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
expect(layout.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: '2'
|
||||
});
|
||||
expect(fixed.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: '3'
|
||||
});
|
||||
});
|
||||
|
||||
it('have new-style composition', function () {
|
||||
expect(layout.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
expect(layout.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '3'
|
||||
});
|
||||
expect(fixed.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
});
|
||||
|
||||
it('rewrites locations', function () {
|
||||
expect(swg.location).toBe('my-import:root');
|
||||
expect(layout.location).toBe('my-import:root');
|
||||
expect(fixed.location).toBe('my-import:2');
|
||||
});
|
||||
|
||||
it('rewrites matched identifiers in objects', function () {
|
||||
expect(layout.configuration.layout.panels['my-import:1'])
|
||||
.toBeDefined();
|
||||
expect(layout.configuration.layout.panels['my-import:3'])
|
||||
.toBeDefined();
|
||||
expect(layout.configuration.layout.panels['483c00d4-bb1d-4b42-b29a-c58e06b322a0'])
|
||||
.not.toBeDefined();
|
||||
expect(layout.configuration.layout.panels['20273193-f069-49e9-b4f7-b97a87ed755d'])
|
||||
.not.toBeDefined();
|
||||
expect(fixed.configuration['fixed-display'].elements[0].id)
|
||||
.toBe('my-import:1');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('childObjects', function () {
|
||||
let swg;
|
||||
let layout;
|
||||
let fixed;
|
||||
|
||||
beforeEach(function () {
|
||||
swg = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
layout = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: '2'
|
||||
});
|
||||
fixed = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: '3'
|
||||
});
|
||||
});
|
||||
|
||||
it('match expected ordering', function () {
|
||||
// this is a sanity check to make sure the identifiers map in
|
||||
// the correct order.
|
||||
expect(swg.type).toBe('generator');
|
||||
expect(layout.type).toBe('layout');
|
||||
expect(fixed.type).toBe('telemetry.fixed');
|
||||
});
|
||||
|
||||
it('have new-style identifiers', function () {
|
||||
expect(swg.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
expect(layout.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: '2'
|
||||
});
|
||||
expect(fixed.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: '3'
|
||||
});
|
||||
});
|
||||
|
||||
it('have new-style composition', function () {
|
||||
expect(layout.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
expect(layout.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '3'
|
||||
});
|
||||
expect(fixed.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
});
|
||||
|
||||
it('rewrites locations', function () {
|
||||
expect(swg.location).toBe('my-import:root');
|
||||
expect(layout.location).toBe('my-import:root');
|
||||
expect(fixed.location).toBe('my-import:2');
|
||||
});
|
||||
|
||||
it('rewrites matched identifiers in objects', function () {
|
||||
expect(layout.configuration.layout.panels['my-import:1'])
|
||||
.toBeDefined();
|
||||
expect(layout.configuration.layout.panels['my-import:3'])
|
||||
.toBeDefined();
|
||||
expect(layout.configuration.layout.panels['483c00d4-bb1d-4b42-b29a-c58e06b322a0'])
|
||||
.not.toBeDefined();
|
||||
expect(layout.configuration.layout.panels['20273193-f069-49e9-b4f7-b97a87ed755d'])
|
||||
.not.toBeDefined();
|
||||
expect(fixed.configuration['fixed-display'].elements[0].id)
|
||||
.toBe('my-import:1');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,52 +1,63 @@
|
||||
define([
|
||||
'./StaticModelProvider'
|
||||
], function (
|
||||
StaticModelProvider
|
||||
) {
|
||||
/**
|
||||
* Static Root Plugin: takes an export file and exposes it as a new root
|
||||
* object.
|
||||
*/
|
||||
function StaticRootPlugin(namespace, exportUrl) {
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2022, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
const rootIdentifier = {
|
||||
namespace: namespace,
|
||||
key: 'root'
|
||||
};
|
||||
import StaticModelProvider from './StaticModelProvider';
|
||||
|
||||
let cachedProvider;
|
||||
export default function StaticRootPlugin(options) {
|
||||
const rootIdentifier = {
|
||||
namespace: options.namespace,
|
||||
key: 'root'
|
||||
};
|
||||
|
||||
function loadProvider() {
|
||||
return fetch(exportUrl)
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (importData) {
|
||||
cachedProvider = new StaticModelProvider(importData, rootIdentifier);
|
||||
let cachedProvider;
|
||||
|
||||
return cachedProvider;
|
||||
});
|
||||
}
|
||||
function loadProvider() {
|
||||
return fetch(options.exportUrl)
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (importData) {
|
||||
cachedProvider = new StaticModelProvider(importData, rootIdentifier);
|
||||
|
||||
function getProvider() {
|
||||
if (!cachedProvider) {
|
||||
cachedProvider = loadProvider();
|
||||
}
|
||||
|
||||
return Promise.resolve(cachedProvider);
|
||||
}
|
||||
|
||||
return function install(openmct) {
|
||||
openmct.objects.addRoot(rootIdentifier);
|
||||
openmct.objects.addProvider(namespace, {
|
||||
get: function (identifier) {
|
||||
return getProvider().then(function (provider) {
|
||||
return provider.get(identifier);
|
||||
});
|
||||
}
|
||||
return cachedProvider;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return StaticRootPlugin;
|
||||
});
|
||||
function getProvider() {
|
||||
if (!cachedProvider) {
|
||||
cachedProvider = loadProvider();
|
||||
}
|
||||
|
||||
return Promise.resolve(cachedProvider);
|
||||
}
|
||||
|
||||
return function install(openmct) {
|
||||
openmct.objects.addRoot(rootIdentifier);
|
||||
openmct.objects.addProvider(options.namespace, {
|
||||
get: function (identifier) {
|
||||
return getProvider().then(function (provider) {
|
||||
return provider.get(identifier);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
1
static-root.json
Normal file
1
static-root.json
Normal file
@@ -0,0 +1 @@
|
||||
{"openmct":{"a2de0f92-e1a9-4ab0-b815-8226eb016b33":{"identifier":{"key":"a2de0f92-e1a9-4ab0-b815-8226eb016b33","namespace":""},"name":"Parent Folder","type":"folder","composition":[{"key":"9cdda73d-9b0c-4b6d-8405-f90c33844e54","namespace":""},{"key":"d0ef5482-8bda-4082-b2e2-73807320d1d9","namespace":""},{"key":"97891e2c-6000-464f-a65d-e928fa0d172d","namespace":""}],"modified":1645824127466,"location":"mine","persisted":1645824127468},"9cdda73d-9b0c-4b6d-8405-f90c33844e54":{"identifier":{"key":"9cdda73d-9b0c-4b6d-8405-f90c33844e54","namespace":""},"name":"Child Folder","type":"folder","composition":[{"key":"aa6e8428-fe16-4033-9b04-8c63d559fe05","namespace":""},{"key":"f473b125-3aa3-419e-8fd9-004e08d42ba3","namespace":""}],"modified":1645824073376,"location":"a2de0f92-e1a9-4ab0-b815-8226eb016b33","persisted":1645824073378},"d0ef5482-8bda-4082-b2e2-73807320d1d9":{"identifier":{"key":"d0ef5482-8bda-4082-b2e2-73807320d1d9","namespace":""},"name":"Sibling Child Folder","type":"folder","composition":[{"key":"b9d53ee9-d5f0-404e-90c1-b0e4b30c3d54","namespace":""}],"modified":1645824073375,"location":"a2de0f92-e1a9-4ab0-b815-8226eb016b33","persisted":1645824073375},"97891e2c-6000-464f-a65d-e928fa0d172d":{"identifier":{"key":"97891e2c-6000-464f-a65d-e928fa0d172d","namespace":""},"name":"A Clock","type":"clock","configuration":{"baseFormat":"YYYY/MM/DD hh:mm:ss","use24":"clock12","timezone":"UTC"},"modified":1645824127465,"location":"a2de0f92-e1a9-4ab0-b815-8226eb016b33","persisted":1645824127465},"aa6e8428-fe16-4033-9b04-8c63d559fe05":{"identifier":{"key":"aa6e8428-fe16-4033-9b04-8c63d559fe05","namespace":""},"name":"Grandchild Folder","type":"folder","composition":[{"key":"f8f9dd1f-50fe-4bed-b0e4-dd85ce6d3498","namespace":""}],"modified":1645824155758,"location":"9cdda73d-9b0c-4b6d-8405-f90c33844e54","persisted":1645824155760},"f473b125-3aa3-419e-8fd9-004e08d42ba3":{"identifier":{"key":"f473b125-3aa3-419e-8fd9-004e08d42ba3","namespace":""},"name":"Secret Web Page","type":"webPage","url":"https://www.youtube.com/embed/dQw4w9WgXcQ","modified":1645823979349,"location":"9cdda73d-9b0c-4b6d-8405-f90c33844e54","persisted":1645823979349},"b9d53ee9-d5f0-404e-90c1-b0e4b30c3d54":{"identifier":{"key":"b9d53ee9-d5f0-404e-90c1-b0e4b30c3d54","namespace":""},"name":"Linky","type":"hyperlink","displayFormat":"link","linkTarget":"_self","url":"https://www.nasa.gov/viper/","displayText":"Viper Info","modified":1645824073374,"location":"d0ef5482-8bda-4082-b2e2-73807320d1d9","persisted":1645824073374},"f8f9dd1f-50fe-4bed-b0e4-dd85ce6d3498":{"identifier":{"key":"f8f9dd1f-50fe-4bed-b0e4-dd85ce6d3498","namespace":""},"name":"Display Layout","type":"layout","composition":[{"key":"f473b125-3aa3-419e-8fd9-004e08d42ba3","namespace":""},{"key":"b9d53ee9-d5f0-404e-90c1-b0e4b30c3d54","namespace":""},{"key":"97891e2c-6000-464f-a65d-e928fa0d172d","namespace":""}],"configuration":{"items":[{"width":58,"height":30,"x":1,"y":3,"identifier":{"key":"f473b125-3aa3-419e-8fd9-004e08d42ba3","namespace":""},"hasFrame":true,"fontSize":"default","font":"default","type":"subobject-view","id":"f7b49d10-d606-467f-bc08-5d660b8ae693"},{"width":11,"height":2,"x":60,"y":3,"identifier":{"key":"b9d53ee9-d5f0-404e-90c1-b0e4b30c3d54","namespace":""},"hasFrame":false,"fontSize":"default","font":"default","type":"subobject-view","id":"483b5762-455f-485e-a17d-24699dbcbe06"},{"width":31,"height":6,"x":60,"y":6,"identifier":{"key":"97891e2c-6000-464f-a65d-e928fa0d172d","namespace":""},"hasFrame":true,"fontSize":"default","font":"default","type":"subobject-view","id":"53026423-72c4-4b5f-9290-9c7abbd1bec7"}],"layoutGrid":[10,10]},"modified":1645824197324,"location":"aa6e8428-fe16-4033-9b04-8c63d559fe05","persisted":1645824201302}},"rootId":"a2de0f92-e1a9-4ab0-b815-8226eb016b33"}
|
||||
@@ -6,7 +6,7 @@ const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
|
||||
const VueLoaderPlugin = require('vue-loader/lib/plugin');
|
||||
const {VueLoaderPlugin} = require('vue-loader');
|
||||
const gitRevision = require('child_process')
|
||||
.execSync('git rev-parse HEAD')
|
||||
.toString().trim();
|
||||
@@ -37,7 +37,7 @@ const config = {
|
||||
alias: {
|
||||
"@": path.join(__dirname, "src"),
|
||||
"legacyRegistry": path.join(__dirname, "src/legacyRegistry"),
|
||||
"saveAs": "file-saver",
|
||||
"saveAs": "file-saver/src/FileSaver.js",
|
||||
"csv": "comma-separated-values",
|
||||
"EventEmitter": "eventemitter3",
|
||||
"bourbon": "bourbon.scss",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const { merge } = require('webpack-merge');
|
||||
const common = require('./webpack.common');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
@@ -14,6 +15,14 @@ module.exports = merge(common, {
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
__OPENMCT_ROOT_RELATIVE__: '"dist/"'
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: './static-root.json',
|
||||
to: '.'
|
||||
}
|
||||
]
|
||||
})
|
||||
],
|
||||
devtool: 'eval-source-map'
|
||||
|
||||
Reference in New Issue
Block a user