未验证 提交 50fab2de 编写于 作者: P Peter Pan 提交者: GitHub

fix extrema cannot display correctly when there are multiple values with same...

fix extrema cannot display correctly when there are multiple values with same step in scalar page (#981)

* chore: update dependencies

* fix(scalar): cannot display minmax values when more then 1 point in same step

* chore: update snowpack to 3.0

* chore: update snowpack to 3.0
上级 2afd6f89
node_modules
dist
packages/icons/components
packages/wasm/dist
license-header.js
*.d.ts
...@@ -22,10 +22,9 @@ module.exports = { ...@@ -22,10 +22,9 @@ module.exports = {
}, },
extends: ['plugin:prettier/recommended'], extends: ['plugin:prettier/recommended'],
parserOptions: { parserOptions: {
ecmaVersion: 2018, ecmaVersion: 2020,
sourceType: 'module' sourceType: 'module'
}, },
ignorePatterns: ['node_modules/', 'dist/', 'output/', 'license-header.js'],
plugins: ['license-header'], plugins: ['license-header'],
rules: { rules: {
'no-console': 'warn', 'no-console': 'warn',
...@@ -34,7 +33,7 @@ module.exports = { ...@@ -34,7 +33,7 @@ module.exports = {
}, },
overrides: [ overrides: [
{ {
files: ['packages/cli/**/*', 'packages/mock/**/*', 'packages/demo/**/*', 'packages/server/**/*'], files: ['packages/cli/**/*', 'packages/demo/**/*', 'packages/server/**/*'],
extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'], extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
rules: { rules: {
...@@ -71,6 +70,9 @@ module.exports = { ...@@ -71,6 +70,9 @@ module.exports = {
'react/prop-types': 'off', 'react/prop-types': 'off',
'react/react-in-jsx-scope': 'off' 'react/react-in-jsx-scope': 'off'
} }
},
{
files: ['packages/icons/**/*']
} }
] ]
}; };
...@@ -12,7 +12,6 @@ coverage ...@@ -12,7 +12,6 @@ coverage
.next .next
# production # production
build
dist dist
# misc # misc
...@@ -27,4 +26,4 @@ yarn-error.log* ...@@ -27,4 +26,4 @@ yarn-error.log*
lerna-debug.log* lerna-debug.log*
# output # output
/output output
node_modules
dist dist
out packages/icons/components
wasm packages/wasm/dist
output
license-header.js license-header.js
...@@ -26,8 +26,7 @@ const getPackages = filenames => ...@@ -26,8 +26,7 @@ const getPackages = filenames =>
module.exports = { module.exports = {
// lint all files when global package.json or eslint config changes. // lint all files when global package.json or eslint config changes.
'./(package.json|.eslintrc.js)': () => './(package.json|.eslintrc.js)': () => `eslint --ext .tsx,.jsx.ts,.js ${__dirname}`,
`eslint --ext .tsx,.jsx.ts,.js --ignore-path ${path.join(__dirname, '.gitignore')} ${__dirname}`,
// check types when ts file or package.json changes. // check types when ts file or package.json changes.
'./(packages/*/package.json|packages/*/**/*.ts?(x))': filenames => './(packages/*/package.json|packages/*/**/*.ts?(x))': filenames =>
......
...@@ -29,8 +29,14 @@ ...@@ -29,8 +29,14 @@
"scripts": { "scripts": {
"bootstrap": "lerna bootstrap", "bootstrap": "lerna bootstrap",
"build": "./scripts/build.sh", "build": "./scripts/build.sh",
"build:core": "yarn workspace @visualdl/core build",
"build:demo": "yarn workspace @visualdl/demo build",
"clean": "rimraf output packages/*/dist packages/wasm/target", "clean": "rimraf output packages/*/dist packages/wasm/target",
"lint": "eslint --ext .tsx,.jsx.ts,.js --ignore-path .gitignore .", "dev": "yarn dev:core",
"dev:core": "yarn workspace @visualdl/core dev",
"dev:demo": "yarn workspace @visualdl/server dev:demo",
"dev:server": "yarn workspace @visualdl/server dev",
"lint": "eslint --ext .tsx,.jsx.ts,.js,.mjs .",
"format": "prettier --write \"**/*.{ts,tsx,js,jsx}\"", "format": "prettier --write \"**/*.{ts,tsx,js,jsx}\"",
"test": "yarn workspaces run test", "test": "yarn workspaces run test",
"prepublishOnly": "yarn lint && yarn test && yarn build", "prepublishOnly": "yarn lint && yarn test && yarn build",
...@@ -38,19 +44,19 @@ ...@@ -38,19 +44,19 @@
"version": "yarn format && git add -A" "version": "yarn format && git add -A"
}, },
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "4.24.0", "@typescript-eslint/eslint-plugin": "4.26.0",
"@typescript-eslint/parser": "4.24.0", "@typescript-eslint/parser": "4.26.0",
"eslint": "7.26.0", "eslint": "7.28.0",
"eslint-config-prettier": "8.3.0", "eslint-config-prettier": "8.3.0",
"eslint-plugin-license-header": "0.2.0", "eslint-plugin-license-header": "0.2.0",
"eslint-plugin-prettier": "3.4.0", "eslint-plugin-prettier": "3.4.0",
"eslint-plugin-react": "7.23.2", "eslint-plugin-react": "7.24.0",
"eslint-plugin-react-hooks": "4.2.0", "eslint-plugin-react-hooks": "4.2.0",
"lerna": "4.0.0", "lerna": "4.0.0",
"lint-staged": "11.0.0", "lint-staged": "11.0.0",
"prettier": "2.3.0", "prettier": "2.3.1",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"typescript": "4.2.4", "typescript": "4.3.2",
"yarn": "1.22.10" "yarn": "1.22.10"
}, },
"engines": { "engines": {
......
../../LICENSE
\ No newline at end of file
# VisualDL FrontEnd cli
## Usage
> nodejs ≥ 10 and npm ≥ 6 are required.
```bash
npm install -g @visualdl/cli
# or
yarn global add @visualdl/cli
```
Then you can start visualdl server by
```bash
visualdl start --backend="http://127.0.0.1:8040"
```
To stop visualdl server, just type
```bash
visualdl stop
```
For more usage infomation, please type
```bash
visualdl -h
```
#!/usr/bin/env node
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-console */
import ora, {Ora} from 'ora';
import ecosystem from '@visualdl/server/ecosystem.config';
import pm2 from 'pm2';
const app = ecosystem.apps[0];
const argv = require('yargs')
.usage('Usage: $0 <command> [options]')
.command('start', 'Start VisualDL server')
.command('stop', 'Stop VisualDL server')
.example(
'$0 start --backend="http://172.17.0.82:8040"',
'Start VisualDL server with backend address http://172.17.0.82:8040'
)
.alias('p', 'port')
.nargs('p', 1)
.nargs('port', 1)
.describe('p', 'Port of server')
.nargs('host', 1)
.describe('host', 'Host of server')
.alias('b', 'backend')
.nargs('b', 1)
.nargs('backend', 1)
.describe('b', 'Backend API address')
.boolean('demo')
.describe('demo', 'Run in demo mode')
.boolean('open')
.describe('open', 'Open browser when server is ready')
.help('h')
.alias('h', 'help')
.epilog('Visit https://github.com/PaddlePaddle/VisualDL for more information.').argv;
const command = argv._[0];
const exit = () => {
console.log('Command not found, use -h or --help for help');
process.exit(1);
};
const exitIfError = (err?: Error, exitCode = 1, spinner?: Ora) => {
if (!err) {
return;
}
if (spinner) {
spinner.fail('Error!');
}
console.error(err);
process.exit(exitCode);
};
if (!command) {
exit();
}
const banner = `
█████ █████ ███ ████ ██████████ █████
░░███ ░░███ ░░░ ░░███ ░░███░░░░███ ░░███
░███ ░███ ████ █████ █████ ████ ██████ ░███ ░███ ░░███ ░███
░███ ░███ ░░███ ███░░ ░░███ ░███ ░░░░░███ ░███ ░███ ░███ ░███
░░███ ███ ░███ ░░█████ ░███ ░███ ███████ ░███ ░███ ░███ ░███
░░░█████░ ░███ ░░░░███ ░███ ░███ ███░░███ ░███ ░███ ███ ░███ █
░░███ █████ ██████ ░░████████░░████████ █████ ██████████ ███████████
░░░ ░░░░░ ░░░░░░ ░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░░░░░░░
`;
pm2.connect(err => {
exitIfError(err, 2);
pm2.list((err, list) => {
exitIfError(err, 2);
const host = argv.host || 'localhost';
const port = Number.parseInt(argv.port, 10) || 8999;
const url = `http://${host}:${port}`;
if (command === 'start') {
if (list.find(item => item.name === app.name)) {
exitIfError(new Error('VisualDL server is already running'), 1);
}
const spinner = ora('Starting VisualDL server...').start();
pm2.start(
{
...app,
env: {
...app.env,
HOST: host,
PORT: port + '',
BACKEND: argv.backend,
DEMO: argv.demo ? '1' : ''
}
},
err => {
pm2.disconnect();
exitIfError(err, 2, spinner);
spinner.succeed('Starting VisualDL server... Done');
console.log(banner);
console.log(`> VisualDL server is running at ${url}`);
if (argv.open) {
console.log(' Opening your browser for you...');
const open = require('open');
open(url);
}
}
);
} else if (command === 'stop') {
if (!list.find(item => item.name === app.name)) {
exitIfError(new Error('VisualDL server is not running'), 1);
}
const spinner = ora('Stopping VisualDL server...').start();
pm2.delete(app.name, err => {
exitIfError(err, 2);
const end = (err?: Error) => {
pm2.disconnect();
exitIfError(err, 2);
spinner.succeed('Stopping VisualDL server... Done');
console.log('> VisualDL server stopped');
console.log(' See you next time');
process.exit(0);
};
pm2.list((err, newList) => {
exitIfError(err, 2);
if (!newList.length) {
pm2.killDaemon(end);
} else {
end();
}
});
});
} else {
exit();
}
});
});
{
"compilerOptions": {
"target": "es5",
"lib": [
"esnext",
"esnext.asynciterable",
"dom"
],
"moduleResolution": "node",
"esModuleInterop": true,
"declaration": true,
"skipLibCheck": true,
"outDir": "dist"
}
}
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
// cSpell:words esmodules
module.exports = {
extends: '@snowpack/app-scripts-react/babel.config.json',
presets: [
[
'@babel/preset-env',
{
targets: {
esmodules: true
},
bugfixes: true,
modules: false
}
]
],
plugins: ['styled-components', '@babel/plugin-proposal-class-properties', 'emotion']
};
...@@ -14,32 +14,18 @@ ...@@ -14,32 +14,18 @@
* limitations under the License. * limitations under the License.
*/ */
/* eslint-disable @typescript-eslint/no-var-requires */ // cspell:words baiducloud
/* eslint-disable no-console */
const path = require('path'); import {BosClient} from '@baiducloud/sdk';
const fs = require('fs/promises'); import Logger from './log.js';
const {BosClient} = require('@baiducloud/sdk'); import fs from 'fs/promises';
const mime = require('mime-types'); import mime from 'mime-types';
import path from 'path';
const endpoint = process.env.BOS_ENDPOINT || 'https://bos.bj.baidubce.com'; const logger = new Logger('CDN');
const ak = process.env.BOS_AK;
const sk = process.env.BOS_SK;
const version = process.env.CDN_VERSION || 'latest';
const config = {
endpoint,
credentials: {
ak,
sk
}
};
const bucket = 'visualdl-static'; const bucket = 'visualdl-static';
const client = new BosClient(config);
async function getFiles(dir) { async function getFiles(dir) {
const result = []; const result = [];
try { try {
...@@ -57,14 +43,20 @@ async function getFiles(dir) { ...@@ -57,14 +43,20 @@ async function getFiles(dir) {
} }
} }
} catch (e) { } catch (e) {
console.error(e); logger.error(e);
} }
return result; return result;
} }
async function push(directory, options) { async function push(directory, options) {
if (!ak || !sk) { logger.start();
console.error('No AK and SK specified!');
const version = options?.version ?? 'latest';
logger.process(`pushing to CDN with version "${version}"...`);
if (!options?.ak || !options?.sk) {
logger.error('No AK and SK specified!');
process.exit(1); process.exit(1);
} }
...@@ -83,24 +75,51 @@ async function push(directory, options) { ...@@ -83,24 +75,51 @@ async function push(directory, options) {
size: stats.size size: stats.size
}); });
} else { } else {
console.error(`${directory} does not exist!`); logger.error(`${directory} does not exist!`);
process.exit(1); process.exit(1);
} }
} catch (e) { } catch (e) {
console.error(e); logger.error(e);
process.exit(1); process.exit(1);
} }
const config = {
endpoint: options?.endpoint ?? 'https://bos.bj.baidubce.com',
credentials: {
ak: options.ak,
sk: options.sk
}
};
const client = new BosClient(config);
const q = [];
for (const file of files) { for (const file of files) {
(function (f) { (function (f) {
client q.push(
.putObjectFromFile(bucket, `assets/${version}/${f.filename}`, f.name, { new Promise((resolve, reject) => {
'Content-Length': f.size, client
'Content-Type': `${f.mime}` .putObjectFromFile(bucket, `assets/${version}/${f.filename}`, f.name, {
'Content-Length': f.size,
'Content-Type': `${f.mime}`
})
.then(() => {
logger.info([f.filename, f.mime, f.size].join(', '));
resolve();
})
.catch(error => {
logger.error(f + error + '');
reject();
});
}) })
.then(() => console.log([f.name, f.mime, f.size].join(', '))) );
.catch(error => console.error(f, error));
})(file); })(file);
} }
try {
await Promise.all(q);
logger.end('CDN Pushed.');
} catch {
logger.error('Some errors occurred when pushing to CDN.');
}
} }
module.exports = push; export default push;
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
/* eslint-disable @typescript-eslint/no-var-requires */
const express = require('express');
const mock = require('./mock');
const icons = require('./icons');
const netron = require('./netron');
const wasm = require('./wasm');
const argv = require('yargs').nargs('port', 1).number('port').nargs('host', 1).argv;
const app = express();
app.use(mock.pathname, mock.middleware());
app.use(icons.pathname, icons.middleware());
app.use(netron.pathname, express.static(netron.root, {index: false}));
app.get(`${wasm.pathname}/${wasm.out}`, (_req, res) => {
res.type('application/wasm');
res.sendFile(wasm.source);
});
app.listen(argv.port, argv.host);
...@@ -14,10 +14,12 @@ ...@@ -14,10 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
// cspell:words tongji
// This file is used to generate environment variables which used by the app // This file is used to generate environment variables which used by the app
// PUBLIC_PATH is for assets, can be set to a CDN address // PUBLIC_PATH is for assets, can be set to a CDN address
process.env.SNOWPACK_PUBLIC_PATH = process.env.CDN_VERSION export const SNOWPACK_PUBLIC_PATH = process.env.CDN_VERSION
? `https://visualdl-static.cdn.bcebos.com/assets/${process.env.CDN_VERSION}` ? `https://visualdl-static.cdn.bcebos.com/assets/${process.env.CDN_VERSION}`
: process.env.PUBLIC_PATH === '/' || !process.env.PUBLIC_PATH : process.env.PUBLIC_PATH === '/' || !process.env.PUBLIC_PATH
? '' ? ''
...@@ -25,9 +27,9 @@ process.env.SNOWPACK_PUBLIC_PATH = process.env.CDN_VERSION ...@@ -25,9 +27,9 @@ process.env.SNOWPACK_PUBLIC_PATH = process.env.CDN_VERSION
// BASE_URI is for env, router and workers. Must be local address which starts with a `/` or empty string // BASE_URI is for env, router and workers. Must be local address which starts with a `/` or empty string
// if it is not set and PUBLIC_PATH is not a CDN address, it will be set to the same value of PUBLIC_PATH // if it is not set and PUBLIC_PATH is not a CDN address, it will be set to the same value of PUBLIC_PATH
process.env.SNOWPACK_PUBLIC_BASE_URI = export const SNOWPACK_PUBLIC_BASE_URI =
process.env.SNOWPACK_PUBLIC_PATH.startsWith('/') || process.env.PUBLIC_PATH === '' SNOWPACK_PUBLIC_PATH.startsWith('/') || process.env.PUBLIC_PATH === ''
? process.env.SNOWPACK_PUBLIC_PATH ? SNOWPACK_PUBLIC_PATH
: process.env.BASE_URI === '/' || !process.env.BASE_URI : process.env.BASE_URI === '/' || !process.env.BASE_URI
? '' ? ''
: process.env.BASE_URI; : process.env.BASE_URI;
...@@ -35,19 +37,21 @@ process.env.SNOWPACK_PUBLIC_BASE_URI = ...@@ -35,19 +37,21 @@ process.env.SNOWPACK_PUBLIC_BASE_URI =
// API_URL is for api requests // API_URL is for api requests
// it will be set to `${BASE_URI}/api` by default // it will be set to `${BASE_URI}/api` by default
// if it is set to a absolute address refer to another hostname, CORS headers must be set // if it is set to a absolute address refer to another hostname, CORS headers must be set
process.env.SNOWPACK_PUBLIC_API_URL = process.env.API_URL || `${process.env.SNOWPACK_PUBLIC_BASE_URI}/api`; export const SNOWPACK_PUBLIC_API_URL = process.env.API_URL || `${SNOWPACK_PUBLIC_BASE_URI}/api`;
// TELEMETRY_ID is for Baidu Tongji // TELEMETRY_ID is for Baidu Tongji
// set to an empty string will disable telemetry // set to an empty string will disable telemetry
process.env.SNOWPACK_PUBLIC_TELEMETRY_ID = process.env.TELEMETRY_ID || ''; export const SNOWPACK_PUBLIC_TELEMETRY_ID = process.env.TELEMETRY_ID || '';
// API_TOKEN_KEY is for vdl-service // API_TOKEN_KEY is for vdl-service
// if it is set, api requests will add an additional header `X-VisualDL-Instance-ID` from the token key in query string // if it is set, api requests will add an additional header `X-VisualDL-Instance-ID` from the token key in query string
process.env.SNOWPACK_PUBLIC_API_TOKEN_KEY = process.env.API_TOKEN_KEY || ''; export const SNOWPACK_PUBLIC_API_TOKEN_KEY = process.env.API_TOKEN_KEY || '';
// supported languages // supported languages
process.env.SNOWPACK_PUBLIC_LANGUAGES = process.env.LANGUAGES || 'en,zh'; export const SNOWPACK_PUBLIC_LANGUAGES = process.env.LANGUAGES || 'en,zh';
// default language // default language
process.env.SNOWPACK_PUBLIC_DEFAULT_LANGUAGE = process.env.DEFAULT_LANGUAGE || 'en'; export const SNOWPACK_PUBLIC_DEFAULT_LANGUAGE = process.env.DEFAULT_LANGUAGE || 'en';
// theme // theme
process.env.SNOWPACK_PUBLIC_THEME = process.env.THEME || ''; export const SNOWPACK_PUBLIC_THEME = process.env.THEME || '';
// demo
export const DEMO = '';
...@@ -14,76 +14,48 @@ ...@@ -14,76 +14,48 @@
* limitations under the License. * limitations under the License.
*/ */
/* eslint-disable no-console */ import Logger from './log.js';
/* eslint-disable @typescript-eslint/no-var-requires */ import {fileURLToPath} from 'url';
import fs from 'fs/promises';
const path = require('path'); import path from 'path';
const fs = require('fs/promises');
const {default: svgr} = require('@svgr/core'); const logger = new Logger('Icons');
const babel = require('@babel/core');
const {camelCase} = require('lodash'); const cwd = path.dirname(fileURLToPath(import.meta.url));
const {ensureDir} = require('fs-extra'); const iconsPath = path.resolve(cwd, '../dist/__snowpack__/link/packages/icons/components');
const reactPath = path.resolve(cwd, '../dist/__snowpack__/pkg/react.js');
const root = path.resolve(__dirname, '../public/icons'); const relativePath = path.relative(iconsPath, reactPath).replace(/\\\\/g, '/');
const pathname = '/icons';
const dist = path.resolve(__dirname, '../dist'); export default async function build() {
const dest = path.join(dist, pathname); logger.start();
logger.process('building icons...');
async function transform(file, minified) { const files = await fs.readdir(iconsPath);
const basename = path.basename(file, '.svg'); const q = [];
let jsx = await svgr(
await fs.readFile(file, 'utf-8'),
{
icon: true,
svgProps: {
fill: 'currentColor',
className: 'vdl-icon'
}
},
{componentName: camelCase(basename).replace(/./, w => w.toUpperCase())}
);
jsx = jsx.replace('import * as React from "react";', 'import React from "../web_modules/react.js";');
const result = await babel.transformAsync(jsx, {
filename: basename + '.jsx',
presets: ['@babel/preset-react'],
minified
});
return result.code;
}
async function build() {
await ensureDir(dest);
const files = await fs.readdir(root);
for (const file of files) { for (const file of files) {
if (path.extname(file) === '.svg') { (function (f) {
const js = await transform(path.join(root, file), false); const filename = path.join(iconsPath, f);
await fs.writeFile(path.join(dest, path.basename(file, '.svg') + '.js'), js, 'utf-8'); if (path.extname(filename) === '.js') {
} q.push(
new Promise(async (resolve, reject) => {
try {
const content = await fs.readFile(filename, 'utf-8');
await fs.writeFile(
filename,
content.replace('import*as React from"react";', `import React from"${relativePath}";`)
);
resolve();
} catch {
reject();
}
})
);
}
})(file);
}
try {
await Promise.all(q);
logger.end('Icons built.');
} catch {
logger.error('Some errors occurred when building icons.');
} }
console.log('Icons copied!');
}
if (require.main === module) {
build();
} }
const middleware = () => {
return async (req, res) => {
const file = path.join(root, req.path.replace(/\.js$/, '.svg'));
if ((await fs.stat(file)).isFile()) {
if (req.path.endsWith('.js')) {
res.type('js');
res.send(await transform(file, false));
} else {
res.type(req.path.split('.').pop());
res.send(await fs.readFile(file));
}
}
};
};
module.exports = {
middleware,
root,
pathname
};
...@@ -14,17 +14,30 @@ ...@@ -14,17 +14,30 @@
* limitations under the License. * limitations under the License.
*/ */
/* eslint-disable @typescript-eslint/no-var-requires */ import Logger from './log.js';
import {fileURLToPath} from 'url';
import fs from 'fs/promises';
import path from 'path';
const path = require('path'); const logger = new Logger('Inject env');
const fs = require('fs/promises');
const ENV_INJECT = 'const env = globalThis.__snowpack_env__ || {}; export default env;'; const cwd = path.dirname(fileURLToPath(import.meta.url));
const dest = path.resolve(cwd, '../dist/__snowpack__');
const dest = path.resolve(__dirname, '../dist/__snowpack__');
const envFile = path.join(dest, 'env.js'); const envFile = path.join(dest, 'env.js');
module.exports = async () => { async function envInjectTemplate(env) {
return `const env = globalThis.__snowpack_env__ || {}; export const ${Object.keys(env)
.map(key => `${key}=env["${key}"]`)
.join(',')};`;
}
export default async () => {
logger.start();
const env = await import(envFile);
const envInject = await envInjectTemplate(env);
logger.process('renaming env.js to env.local.js...');
await fs.rename(envFile, path.join(dest, 'env.local.js')); await fs.rename(envFile, path.join(dest, 'env.local.js'));
await fs.writeFile(envFile, ENV_INJECT, 'utf-8'); logger.process('regenerating env.js...');
await fs.writeFile(envFile, envInject, 'utf-8');
logger.end('Env injected.');
}; };
...@@ -14,25 +14,31 @@ ...@@ -14,25 +14,31 @@
* limitations under the License. * limitations under the License.
*/ */
/* eslint-disable @typescript-eslint/no-var-requires */ import {SNOWPACK_PUBLIC_BASE_URI, SNOWPACK_PUBLIC_PATH} from './env.js';
const path = require('path'); import Logger from './log.js';
const fs = require('fs/promises'); import {fileURLToPath} from 'url';
const {minify} = require('html-minifier'); import fs from 'fs/promises';
import {minify} from 'html-minifier';
import path from 'path';
const dist = path.resolve(__dirname, '../dist'); const logger = new Logger('Inject template');
const cwd = path.dirname(fileURLToPath(import.meta.url));
const dist = path.resolve(cwd, '../dist');
const input = path.join(dist, 'index.html'); const input = path.join(dist, 'index.html');
const output = path.join(dist, 'index.tpl.html'); const output = path.join(dist, 'index.tpl.html');
function envProviderTemplate(baseUri) { function envProviderTemplate(baseUri) {
return ` return `
<script type="module"> <script type="module">
import env from '${baseUri}/__snowpack__/env.local.js'; window.__snowpack_env__ = env; import * as env from '${baseUri}/__snowpack__/env.local.js'; window.__snowpack_env__ = env;
</script> </script>
`; `;
} }
const ENV_PROVIDER = envProviderTemplate(process.env.SNOWPACK_PUBLIC_BASE_URI); const ENV_PROVIDER = envProviderTemplate(SNOWPACK_PUBLIC_BASE_URI);
const ENV_TEMPLATE_PROVIDER = envProviderTemplate('%BASE_URI%'); const ENV_TEMPLATE_PROVIDER = envProviderTemplate('%BASE_URI%');
function injectProvider(content, provider) { function injectProvider(content, provider) {
...@@ -42,7 +48,7 @@ function injectProvider(content, provider) { ...@@ -42,7 +48,7 @@ function injectProvider(content, provider) {
function prependPublicPath(content, publicPath) { function prependPublicPath(content, publicPath) {
return content.replace(/\b(src|href)=(['"]?)([^'"\s>]*)/gi, (_matched, attr, quote, url) => { return content.replace(/\b(src|href)=(['"]?)([^'"\s>]*)/gi, (_matched, attr, quote, url) => {
if (/^\/(_dist_|__snowpack__|web_modules|favicon.ico)\b/.test(url)) { if (/^\/(_dist_|__snowpack__|web_modules|favicon.ico|imported-styles.css)\b/.test(url)) {
url = publicPath + url; url = publicPath + url;
} }
return attr + '=' + quote + url; return attr + '=' + quote + url;
...@@ -63,12 +69,18 @@ async function writeMinified(file, content) { ...@@ -63,12 +69,18 @@ async function writeMinified(file, content) {
); );
} }
module.exports = async () => { export default async () => {
logger.start();
logger.process('injecting env to index.html...');
const index = await fs.readFile(input, 'utf-8'); const index = await fs.readFile(input, 'utf-8');
const indexWithPublicPath = prependPublicPath(index, process.env.SNOWPACK_PUBLIC_PATH); const indexWithPublicPath = prependPublicPath(index, SNOWPACK_PUBLIC_PATH);
const injected = injectProvider(indexWithPublicPath, ENV_PROVIDER); const injected = injectProvider(indexWithPublicPath, ENV_PROVIDER);
logger.process('minifying index.html...');
await writeMinified(input, injected); await writeMinified(input, injected);
logger.process('injecting env to index.tpl.html...');
const template = prependPublicPath(index, '%PUBLIC_URL%'); const template = prependPublicPath(index, '%PUBLIC_URL%');
const injectedTemplate = injectProvider(template, ENV_TEMPLATE_PROVIDER); const injectedTemplate = injectProvider(template, ENV_TEMPLATE_PROVIDER);
logger.process('minifying index.tpl.html...');
await writeMinified(output, injectedTemplate); await writeMinified(output, injectedTemplate);
logger.end('Template injected.');
}; };
...@@ -16,42 +16,60 @@ ...@@ -16,42 +16,60 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import express from 'express'; import chalk from 'chalk';
import middleware from './middleware'; import moment from 'moment';
const host = process.env.HOST || 'localhost'; export default class Logger {
const port = Number.parseInt(process.env.PORT || '', 10) || 8998; name = '';
const apiUrl = process.env.API_URL || '/api'; startTime;
export interface Options { constructor(name) {
host?: string; this.name = name;
port?: number; this.start();
apiUrl?: string; }
}
const server = express(); #prepend() {
let ret = `[${moment().format('HH:mm:ss')}] `;
async function start(options?: Options) { if (this.name) {
const config = Object.assign({host, port, apiUrl}, options); ret += `[${this.name}] `;
}
server.use(config.apiUrl, middleware()); return chalk.gray(ret);
}
const s = server.listen(config.port, config.host, () => {
process.send?.('ready');
console.log(`> Ready on http://${config.host}:${config.port}${config.apiUrl}`);
process.on('SIGINT', () => {
s.close((err: Error | undefined) => {
if (err) {
throw err;
}
process.exit(0);
});
});
});
}
if (require.main === module) { log(msg) {
start(); console.log(this.#prepend() + msg);
} }
info(msg) {
this.log(msg);
}
warn(msg) {
this.log(chalk.yellow(msg));
}
export {start, middleware}; error(msg) {
this.log(chalk.red(msg));
}
process(msg) {
this.warn('! ' + msg);
}
start() {
this.startTime = new Date().valueOf();
}
end(msg) {
const endTime = new Date().valueOf();
this.log(
'' +
msg +
chalk.gray(` [${Math.round(moment.duration(endTime - this.startTime).asSeconds() * 100) / 100}s]`)
);
}
complete(msg) {
this.log(chalk.green.bold.underline(msg));
}
}
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const fs = require('fs-extra');
const root = path.dirname(require('enhanced-resolve').sync(__dirname, '@visualdl/netron') || '');
const pathname = '/netron';
const dist = path.resolve(__dirname, '../dist');
const dest = path.join(dist, pathname);
async function build() {
await fs.ensureDir(dest);
await fs.copy(root, dest, {preserveTimestamps: true});
console.log('Netron copied!');
}
if (require.main === module) {
build();
}
module.exports = {
root,
dest,
pathname
};
...@@ -14,28 +14,41 @@ ...@@ -14,28 +14,41 @@
* limitations under the License. * limitations under the License.
*/ */
/* eslint-disable @typescript-eslint/no-var-requires */ import Logger from './log.js';
import buildIcons from './icons.js';
import {config} from 'dotenv';
import {fileURLToPath} from 'url';
import injectEnv from './inject-env.js';
import injectTemplate from './inject-template.js';
import path from 'path';
import pushCdn from './cdn.js';
require('dotenv').config(); const logger = new Logger('Post Build');
require('./environment');
const path = require('path'); config();
const pushCdn = require('./cdn'); const cwd = path.dirname(fileURLToPath(import.meta.url));
const injectTemplate = require('./inject-template'); const dist = path.resolve(cwd, '../dist');
const injectEnv = require('./inject-env');
const dist = path.resolve(__dirname, '../dist');
async function main() { async function main() {
logger.info('Post-build Start');
await injectTemplate(); await injectTemplate();
await injectEnv(); await injectEnv();
await buildIcons();
if (process.env.CDN_VERSION) { if (process.env.CDN_VERSION) {
await pushCdn(dist, { await pushCdn(dist, {
version: process.env.CDN_VERSION,
endpoint: process.env.BOS_ENDPOINT,
ak: process.env.BOS_AK,
sk: process.env.BOS_SK,
exclude: ['index.html', 'index.tpl.html', '__snowpack__/env.local.js'] exclude: ['index.html', 'index.tpl.html', '__snowpack__/env.local.js']
}); });
} }
logger.complete('▶ Post-build Complete!');
} }
main(); main();
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const fs = require('fs-extra');
const root = path.dirname(require('enhanced-resolve').sync(__dirname, '@visualdl/wasm'));
const source = path.join(root, 'index_bg.wasm');
const dist = path.resolve(__dirname, '../dist');
const pathname = '/wasm';
const out = 'visualdl.wasm';
const dest = path.join(dist, pathname, out);
async function build() {
await fs.ensureDir(path.join(dist, pathname));
await fs.copy(source, dest, {preserveTimestamps: true});
console.log('WebAssembly copied!');
}
if (require.main === module) {
build();
}
module.exports = {
dest,
source,
pathname,
out
};
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
export const env: {
SNOWPACK_PUBLIC_PATH: string;
SNOWPACK_PUBLIC_BASE_URI: string;
SNOWPACK_PUBLIC_API_URL: string;
SNOWPACK_PUBLIC_TELEMETRY_ID: string;
SNOWPACK_PUBLIC_API_TOKEN_KEY: string;
SNOWPACK_PUBLIC_LANGUAGES: string;
SNOWPACK_PUBLIC_DEFAULT_LANGUAGE: string;
SNOWPACK_PUBLIC_THEME: string;
};
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
/* eslint-disable @typescript-eslint/no-var-requires */ import * as env from './builder/env.js';
module.exports = { export {env};
...require('@snowpack/app-scripts-react/jest.config.js')()
};
...@@ -24,37 +24,42 @@ ...@@ -24,37 +24,42 @@
}, },
"scripts": { "scripts": {
"dev": "snowpack dev", "dev": "snowpack dev",
"dev:reload": "yarn dev --reload",
"build": "snowpack build && node builder/post-build.js", "build": "snowpack build && node builder/post-build.js",
"start": "yarn dev --reload", "snowpack": "snowpack",
"test": "jest --passWithNoTests" "test": "web-test-runner \"test/**/*.tsx\""
}, },
"main": "dist/index.html", "type": "module",
"main": "index.js",
"types": "index.d.ts",
"files": [ "files": [
"dist", "index.js",
"builder/environment.js" "index.d.ts",
"dist"
], ],
"dependencies": { "dependencies": {
"@tippyjs/react": "4.2.5", "@tippyjs/react": "4.2.5",
"@visualdl/icons": "2.2.0-1",
"@visualdl/netron": "2.2.0-1", "@visualdl/netron": "2.2.0-1",
"@visualdl/wasm": "2.2.0-1", "@visualdl/wasm": "2.2.0-1",
"bignumber.js": "9.0.1", "bignumber.js": "9.0.1",
"classnames": "2.3.1", "classnames": "2.3.1",
"d3": "6.7.0", "d3": "6.7.0",
"d3-format": "3.0.0", "d3-format": "3.0.1",
"echarts": "4.9.0", "echarts": "4.9.0",
"echarts-gl": "1.1.2", "echarts-gl": "1.1.2",
"eventemitter3": "4.0.7", "eventemitter3": "4.0.7",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"i18next": "20.2.4", "i18next": "20.3.1",
"i18next-browser-languagedetector": "6.1.1", "i18next-browser-languagedetector": "6.1.1",
"i18next-fetch-backend": "3.0.0", "i18next-fetch-backend": "3.0.0",
"jszip": "3.6.0", "jszip": "3.6.0",
"lodash": "4.17.21", "lodash": "4.17.21",
"mime-types": "2.1.30", "mime-types": "2.1.31",
"moment": "2.29.1", "moment": "2.29.1",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"numeric": "1.2.6", "numeric": "1.2.6",
"polished": "4.1.2", "polished": "4.1.3",
"query-string": "7.0.0", "query-string": "7.0.0",
"react": "17.0.2", "react": "17.0.2",
"react-content-loader": "6.0.3", "react-content-loader": "6.0.3",
...@@ -62,69 +67,60 @@ ...@@ -62,69 +67,60 @@
"react-dnd-html5-backend": "14.0.0", "react-dnd-html5-backend": "14.0.0",
"react-dom": "17.0.2", "react-dom": "17.0.2",
"react-helmet": "6.1.0", "react-helmet": "6.1.0",
"react-i18next": "11.8.15", "react-i18next": "11.10.0",
"react-input-range": "1.3.0", "react-input-range": "1.3.0",
"react-is": "17.0.2",
"react-rangeslider": "2.2.0", "react-rangeslider": "2.2.0",
"react-redux": "7.2.4", "react-redux": "7.2.4",
"react-router-dom": "5.2.0", "react-router-dom": "5.2.0",
"react-spinners": "0.10.6", "react-spinners": "0.11.0",
"react-table": "7.7.0", "react-table": "7.7.0",
"react-table-sticky": "1.1.3", "react-table-sticky": "1.1.3",
"react-toastify": "7.0.4", "react-toastify": "7.0.4",
"redux": "4.1.0", "redux": "4.1.0",
"styled-components": "5.3.0", "styled-components": "5.3.0",
"swr": "0.5.6", "swr": "0.5.6",
"three": "0.128.0", "three": "0.129.0",
"tippy.js": "6.3.1", "tippy.js": "6.3.1",
"umap-js": "1.3.3" "umap-js": "1.3.3"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.14.3",
"@babel/plugin-proposal-class-properties": "7.13.0",
"@babel/preset-env": "7.14.2",
"@babel/preset-react": "7.13.13",
"@baiducloud/sdk": "1.0.0-rc.28", "@baiducloud/sdk": "1.0.0-rc.28",
"@simbathesailor/use-what-changed": "2.0.0", "@simbathesailor/use-what-changed": "2.0.0",
"@snowpack/app-scripts-react": "1.12.6", "@snowpack/plugin-dotenv": "2.1.0",
"@snowpack/plugin-dotenv": "2.0.5", "@snowpack/plugin-optimize": "0.2.13",
"@snowpack/plugin-optimize": "0.2.10", "@snowpack/plugin-react-refresh": "2.5.0",
"@snowpack/plugin-run-script": "2.3.0", "@snowpack/plugin-typescript": "1.2.1",
"@svgr/core": "5.5.0", "@snowpack/web-test-runner-plugin": "0.2.2",
"@testing-library/jest-dom": "5.12.0",
"@testing-library/react": "11.2.7", "@testing-library/react": "11.2.7",
"@types/d3": "6.5.0", "@types/chai": "4.2.18",
"@types/d3": "6.7.0",
"@types/d3-format": "2.0.0", "@types/d3-format": "2.0.0",
"@types/echarts": "4.9.7", "@types/echarts": "4.9.7",
"@types/file-saver": "2.0.2", "@types/file-saver": "2.0.2",
"@types/jest": "26.0.23", "@types/lodash": "4.14.170",
"@types/loadable__component": "5.13.3",
"@types/lodash": "4.14.169",
"@types/mime-types": "2.1.0", "@types/mime-types": "2.1.0",
"@types/nprogress": "0.2.0", "@types/nprogress": "0.2.0",
"@types/numeric": "1.2.1", "@types/numeric": "1.2.1",
"@types/react": "17.0.6", "@types/react": "17.0.9",
"@types/react-dom": "17.0.5", "@types/react-dom": "17.0.6",
"@types/react-helmet": "6.1.1", "@types/react-helmet": "6.1.1",
"@types/react-rangeslider": "2.2.3", "@types/react-rangeslider": "2.2.3",
"@types/react-redux": "7.1.16", "@types/react-redux": "7.1.16",
"@types/react-router-dom": "5.1.7", "@types/react-router-dom": "5.1.7",
"@types/react-table": "7.7.0", "@types/react-table": "7.7.1",
"@types/snowpack-env": "2.3.3", "@types/snowpack-env": "2.3.3",
"@types/styled-components": "5.1.9", "@types/styled-components": "5.1.9",
"@types/three": "0.128.0", "@types/three": "0.129.1",
"@visualdl/mock": "2.2.0-1", "@visualdl/mock": "2.2.0-1",
"babel-plugin-styled-components": "1.12.0", "@web/test-runner": "0.13.5",
"dotenv": "9.0.2", "chai": "4.3.4",
"chalk": "4.1.1",
"dotenv": "10.0.0",
"enhanced-resolve": "5.8.2", "enhanced-resolve": "5.8.2",
"express": "4.17.1",
"fs-extra": "10.0.0",
"html-minifier": "4.0.0", "html-minifier": "4.0.0",
"http-proxy-middleware": "2.0.0", "snowpack": "3.5.5",
"jest": "26.6.3", "snowpack-plugin-copy": "1.0.1",
"snowpack": "2.18.5", "typescript": "4.3.2"
"typescript": "4.2.4",
"yargs": "17.0.1"
}, },
"engines": { "engines": {
"node": ">=14", "node": ">=14",
......
...@@ -14,63 +14,118 @@ ...@@ -14,63 +14,118 @@
* limitations under the License. * limitations under the License.
*/ */
/* eslint-disable @typescript-eslint/no-var-requires */ // cspell:words pnpify svgs entrypoints
require('./builder/environment'); import * as env from './builder/env.js';
const mock = require('./builder/mock');
const icons = require('./builder/icons');
const netron = require('./builder/netron');
const wasm = require('./builder/wasm');
const port = Number.parseInt(process.env.PORT || 3000, 10); import {fileURLToPath} from 'url';
const devServer = { import fs from 'fs';
port: port + 1, import path from 'path';
host: '127.0.0.1' import resolve from 'enhanced-resolve';
};
const cwd = path.dirname(fileURLToPath(import.meta.url));
const workspaceRoot = path.resolve(cwd, '../../');
function isWorkspace() {
try {
const packageJson = fs.readFileSync(path.resolve(workspaceRoot, './package.json'), 'utf-8');
return !!JSON.parse(packageJson).workspaces;
} catch {
return false;
}
}
const iconsPath = path.dirname(resolve.sync(cwd, '@visualdl/icons'));
const netronPath = path.dirname(resolve.sync(cwd, '@visualdl/netron'));
const wasmPath = path.dirname(resolve.sync(cwd, '@visualdl/wasm'));
const mockPath = path.dirname(resolve.sync(cwd, '@visualdl/mock'));
const dest = path.resolve(cwd, './dist/__snowpack__/link/packages');
module.exports = { /** @type {import("snowpack").SnowpackUserConfig } */
extends: '@snowpack/app-scripts-react', export default {
cwd,
workspaceRoot: isWorkspace() ? workspaceRoot : undefined,
mount: {
src: '/_dist_',
public: {
url: '/',
static: true
}
},
routes: [
{
match: 'routes',
src: '.*',
dest: '/index.html'
}
],
env,
alias: {
'~': './src'
},
plugins: [ plugins: [
'@snowpack/plugin-react-refresh',
'@snowpack/plugin-dotenv', '@snowpack/plugin-dotenv',
[
'@snowpack/plugin-typescript',
{
/* Yarn PnP workaround: see https://www.npmjs.com/package/@snowpack/plugin-typescript */
...(process.versions.pnp ? {tsc: 'yarn pnpify tsc'} : {})
}
],
[ [
'@snowpack/plugin-optimize', '@snowpack/plugin-optimize',
{ {
minifyHTML: false, // we will do it later in post-build minifyHTML: false,
preloadModules: true, preloadModules: true,
target: ['chrome79', 'firefox67', 'safari11.1', 'edge79'] // browsers support es module preloadCSS: true,
target: ['chrome79', 'firefox67', 'safari11.1', 'edge79']
} }
], ],
[ [
'@snowpack/plugin-run-script', 'snowpack-plugin-copy',
{ {
cmd: 'node builder/icons.js && node builder/netron.js && node builder/wasm.js', patterns: [
watch: `node builder/dev-server.js --port ${devServer.port} --host ${devServer.host}`, {
output: 'dashboard' source: ['components/*.js', 'svgs/*.svg'],
destination: path.join(dest, 'icons'),
options: {
cwd: iconsPath,
parents: true
}
},
{
source: [path.join(netronPath, '**/*')],
destination: path.join(dest, 'netron/dist')
},
{
source: [path.join(wasmPath, '*.{js,wasm}')],
destination: path.join(dest, 'wasm/dist')
},
{
source: ['./{data,assets}/**/*'],
destination: path.join(dest, 'mock'),
options: {
cwd: mockPath,
parents: true
}
}
]
} }
] ]
], ],
install: ['@visualdl/wasm'],
alias: {
'~': './src'
},
proxy: {
...[mock.pathname, icons.pathname, netron.pathname, wasm.pathname].reduce((m, pathname) => {
m[
process.env.SNOWPACK_PUBLIC_BASE_URI + pathname
] = `http://${devServer.host}:${devServer.port}${pathname}`;
return m;
}, {})
},
devOptions: { devOptions: {
hostname: process.env.HOST || 'localhost', hostname: process.env.HOST || 'localhost',
port port: Number.parseInt(process.env.PORT || 3000, 10)
},
packageOptions: {
polyfillNode: true,
knownEntrypoints: ['chai', '@testing-library/react']
}, },
buildOptions: { buildOptions: {
out: 'dist', out: 'dist',
baseUrl: '/', // set it in post-build baseUrl: '/',
clean: true clean: true,
}, metaUrlPath: '__snowpack__'
installOptions: {
polyfillNode: true
} }
}; };
...@@ -21,6 +21,7 @@ import {contentHeight, position, primaryColor, rem, size, transitionProps} from ...@@ -21,6 +21,7 @@ import {contentHeight, position, primaryColor, rem, size, transitionProps} from
import ChartToolbox from '~/components/ChartToolbox'; import ChartToolbox from '~/components/ChartToolbox';
import HashLoader from 'react-spinners/HashLoader'; import HashLoader from 'react-spinners/HashLoader';
import logo from '~/assets/images/netron.png'; import logo from '~/assets/images/netron.png';
import netron from '@visualdl/netron';
import styled from 'styled-components'; import styled from 'styled-components';
import {toast} from 'react-toastify'; import {toast} from 'react-toastify';
import useTheme from '~/hooks/useTheme'; import useTheme from '~/hooks/useTheme';
...@@ -287,7 +288,7 @@ const Graph = React.forwardRef<GraphRef, GraphProps>( ...@@ -287,7 +288,7 @@ const Graph = React.forwardRef<GraphRef, GraphProps>(
<Content> <Content>
<iframe <iframe
ref={iframe} ref={iframe}
src={`${PUBLIC_PATH}/netron/index.html`} src={PUBLIC_PATH + netron}
frameBorder={0} frameBorder={0}
scrolling="no" scrolling="no"
marginWidth={0} marginWidth={0}
......
...@@ -17,11 +17,10 @@ ...@@ -17,11 +17,10 @@
import React, {FunctionComponent, Suspense, useMemo} from 'react'; import React, {FunctionComponent, Suspense, useMemo} from 'react';
import type {WithStyled} from '~/utils/style'; import type {WithStyled} from '~/utils/style';
import icons from '@visualdl/icons';
import styled from 'styled-components'; import styled from 'styled-components';
import useClassNames from '~/hooks/useClassNames'; import useClassNames from '~/hooks/useClassNames';
const PUBLIC_PATH: string = import.meta.env.SNOWPACK_PUBLIC_PATH;
const Wrapper = styled.i` const Wrapper = styled.i`
speak: none; speak: none;
font-style: normal; font-style: normal;
...@@ -39,7 +38,7 @@ type IconProps = { ...@@ -39,7 +38,7 @@ type IconProps = {
}; };
const Icon: FunctionComponent<IconProps & WithStyled> = ({type, onClick, className}) => { const Icon: FunctionComponent<IconProps & WithStyled> = ({type, onClick, className}) => {
const Svg = useMemo(() => React.lazy(() => import(`${PUBLIC_PATH}/icons/${type}.js`)), [type]); const Svg = useMemo(() => React.lazy(() => icons(type)), [type]);
const classNames = useClassNames('vdl-icon', `icon-${type}`, className, [type, className]); const classNames = useClassNames('vdl-icon', `icon-${type}`, className, [type, className]);
......
...@@ -131,9 +131,9 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({ ...@@ -131,9 +131,9 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
const getTooltipTableData = useCallback( const getTooltipTableData = useCallback(
(series: number[]) => { (series: number[]) => {
const idx = xAxisMap[xAxis]; const idx = xAxisMap[xAxis];
const points = nearestPoint(smoothedDatasets ?? [], runs, idx, series[idx]).map((point, index) => ({ const points = nearestPoint(smoothedDatasets ?? [], runs, idx, series[idx]).map(point => ({
...point, ...point,
...datasetRanges?.[index] ...datasetRanges?.[runs.findIndex(run => run.label === point.run.label)]
})); }));
const sort = sortingMethodMap[sortingMethod]; const sort = sortingMethodMap[sortingMethod];
const sorted = sort(points, series); const sorted = sort(points, series);
......
...@@ -41,17 +41,18 @@ const Wrapper = styled.div` ...@@ -41,17 +41,18 @@ const Wrapper = styled.div`
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
padding: 0.15em 0;
} }
} }
th { th {
font-size: 1.166666667em; font-size: 1.166666667em;
font-weight: bold; font-weight: bold;
padding: 0.15em 0.285714286em; padding: 0 0.285714286em;
} }
td { td {
padding: 0.15em 0.333333333em; padding: 0 0.333333333em;
&.run-indicator > span { &.run-indicator > span {
${size(12, 12)} ${size(12, 12)}
......
...@@ -36,20 +36,31 @@ if (import.meta.env.MODE === 'production' && TELEMETRY_ID) { ...@@ -36,20 +36,31 @@ if (import.meta.env.MODE === 'production' && TELEMETRY_ID) {
})(); })();
} }
ReactDOM.render( function render() {
<React.StrictMode> ReactDOM.render(
<GlobalStyle /> <React.StrictMode>
<React.Suspense fallback={<BodyLoading />}> <GlobalStyle />
<Provider store={store}> <React.Suspense fallback={<BodyLoading />}>
<App /> <Provider store={store}>
</Provider> <App />
</React.Suspense> </Provider>
</React.StrictMode>, </React.Suspense>
document.getElementById('root') </React.StrictMode>,
); document.getElementById('root')
);
// Hot Module Replacement (HMR) - Remove this snippet to remove HMR. // Hot Module Replacement (HMR) - Remove this snippet to remove HMR.
// Learn more: https://www.snowpack.dev/#hot-module-replacement // Learn more: https://www.snowpack.dev/#hot-module-replacement
if (import.meta.hot) { if (import.meta.hot) {
import.meta.hot.accept(); import.meta.hot.accept();
}
}
if (import.meta.env.MODE === 'development' && !import.meta.env.DEMO) {
import('@visualdl/mock').then(async ({initMock}) => {
await initMock();
render();
});
} else {
render();
} }
...@@ -120,7 +120,7 @@ const Graph: FunctionComponent = () => { ...@@ -120,7 +120,7 @@ const Graph: FunctionComponent = () => {
const {data, loading} = useRequest<BlobResponse>(files ? null : '/graph/graph'); const {data, loading} = useRequest<BlobResponse>(files ? null : '/graph/graph');
useEffect(() => { useEffect(() => {
if (data?.data.size) { if (data?.data?.size) {
setFiles([new File([data.data], data.filename || 'unknown_model')]); setFiles([new File([data.data], data.filename || 'unknown_model')]);
} }
}, [data]); }, [data]);
......
...@@ -36,13 +36,14 @@ import { ...@@ -36,13 +36,14 @@ import {
import EventEmitter from 'eventemitter3'; import EventEmitter from 'eventemitter3';
const BASE_URI: string = import.meta.env.SNOWPACK_PUBLIC_BASE_URI; const BASE_URI: string = import.meta.env.SNOWPACK_PUBLIC_BASE_URI;
const env: ImportMeta['env'] = JSON.parse(JSON.stringify(import.meta.env));
export default class WebWorker implements IWorker { export default class WebWorker implements IWorker {
private listeners: Listeners = {}; private listeners: Listeners = {};
private onceListeners: Listeners = {}; private onceListeners: Listeners = {};
private worker: Worker | null = null; private worker: Worker | null = null;
private emitter: EventEmitter | null = null; private emitter: EventEmitter | null = null;
env = import.meta.env; env = env;
constructor(name: string) { constructor(name: string) {
const workerPath = `${BASE_URI}/_dist_/worker`; const workerPath = `${BASE_URI}/_dist_/worker`;
...@@ -50,7 +51,7 @@ export default class WebWorker implements IWorker { ...@@ -50,7 +51,7 @@ export default class WebWorker implements IWorker {
if (checkWorkerModuleSupport()) { if (checkWorkerModuleSupport()) {
this.worker = new Worker(`${workerPath}/worker.js`, {type: 'module'}); this.worker = new Worker(`${workerPath}/worker.js`, {type: 'module'});
this.worker.addEventListener('message', this.listener.bind(this)); this.worker.addEventListener('message', this.listener.bind(this));
this.emit<InitializeData>('INITIALIZE', {name, env: import.meta.env}); this.emit<InitializeData>('INITIALIZE', {name, env});
} else { } else {
this.emitter = new EventEmitter(); this.emitter = new EventEmitter();
this.emitter.addListener('message', this.listener.bind(this)); this.emitter.addListener('message', this.listener.bind(this));
......
...@@ -22,9 +22,7 @@ import initWasm from '@visualdl/wasm'; ...@@ -22,9 +22,7 @@ import initWasm from '@visualdl/wasm';
type FuncNames = Exclude<keyof typeof funcs, 'default'>; type FuncNames = Exclude<keyof typeof funcs, 'default'>;
const runner: Runner = async worker => { const runner: Runner = async worker => {
const PUBLIC_PATH = worker.env.SNOWPACK_PUBLIC_PATH; await initWasm();
await initWasm(`${PUBLIC_PATH}/wasm/visualdl.wasm`);
worker.on<{name: FuncNames; params: unknown[]}>('RUN', ({name, params}) => { worker.on<{name: FuncNames; params: unknown[]}>('RUN', ({name, params}) => {
try { try {
......
...@@ -16,11 +16,23 @@ ...@@ -16,11 +16,23 @@
import * as React from 'react'; import * as React from 'react';
import App from '../src/App'; // import App from '../src/App';
import {expect} from 'chai';
import {render} from '@testing-library/react'; import {render} from '@testing-library/react';
test('renders learn react link', () => { describe('<App>', () => {
const {getByText} = render(<App />); // it('renders learn react link', () => {
const linkElement = getByText(/learn react/i); // const {getByText} = render(<App />);
expect(linkElement).toBeInTheDocument(); // const linkElement = getByText(/learn react/i);
// expect(document.body.contains(linkElement));
// });
it('test demo', () => {
const {getByText} = render(
<div>
<a>hello world!</a>
</div>
);
const linkElement = getByText(/hello world!/i);
expect(document.body.contains(linkElement));
});
}); });
...@@ -7,14 +7,26 @@ ...@@ -7,14 +7,26 @@
"exclude": [ "exclude": [
"node_modules" "node_modules"
], ],
"extends": "@snowpack/app-scripts-react/tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"module": "ESNext",
"target": "ESNext",
"moduleResolution": "node",
"jsx": "preserve",
"baseUrl": "./", "baseUrl": "./",
"isolatedModules": true, "isolatedModules": true,
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"types": [
"mocha",
"snowpack-env"
],
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"importsNotUsedAsValues": "error",
"esModuleInterop": true,
"paths": { "paths": {
"*": [
"web_modules/.types/*"
],
"~/*": [ "~/*": [
"./src/*" "./src/*"
] ]
......
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
declare module '@visualdl/netron' {
const ref: string;
export default ref;
}
...@@ -17,7 +17,36 @@ ...@@ -17,7 +17,36 @@
/* Use this file to declare any custom file extensions for importing */ /* Use this file to declare any custom file extensions for importing */
/* Use this folder to also add/extend a package d.ts file, if needed. */ /* Use this folder to also add/extend a package d.ts file, if needed. */
/* CSS MODULES */
declare module '*.module.css' {
const classes: {[key: string]: string};
export default classes;
}
declare module '*.module.scss' {
const classes: {[key: string]: string};
export default classes;
}
declare module '*.module.sass' {
const classes: {[key: string]: string};
export default classes;
}
declare module '*.module.less' {
const classes: {[key: string]: string};
export default classes;
}
declare module '*.module.styl' {
const classes: {[key: string]: string};
export default classes;
}
/* CSS */
declare module '*.css'; declare module '*.css';
declare module '*.scss';
declare module '*.sass';
declare module '*.less';
declare module '*.styl';
/* IMAGES */
declare module '*.svg' { declare module '*.svg' {
const ref: string; const ref: string;
export default ref; export default ref;
...@@ -42,7 +71,5 @@ declare module '*.png' { ...@@ -42,7 +71,5 @@ declare module '*.png' {
const ref: string; const ref: string;
export default ref; export default ref;
} }
declare module '*.webp' {
const ref: string; /* CUSTOM: ADD YOUR OWN HERE */
export default ref;
}
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
import webTestRunnerPlugin from '@snowpack/web-test-runner-plugin';
process.env.NODE_ENV = 'test';
export default {
plugins: [webTestRunnerPlugin()]
};
...@@ -18,12 +18,15 @@ ...@@ -18,12 +18,15 @@
import IO from './io'; import IO from './io';
import type {Worker} from './types'; import type {Worker} from './types';
import {fileURLToPath} from 'url';
import getPort from 'get-port'; import getPort from 'get-port';
import mkdirp from 'mkdirp'; import mkdirp from 'mkdirp';
import path from 'path'; import path from 'path';
import rimraf from 'rimraf'; import rimraf from 'rimraf';
import {spawn} from 'child_process'; import {spawn} from 'child_process';
const cwd = path.dirname(fileURLToPath(import.meta.url));
const host = '127.0.0.1'; const host = '127.0.0.1';
const publicPath = '/visualdl'; const publicPath = '/visualdl';
const pages = [ const pages = [
...@@ -39,7 +42,7 @@ const pages = [ ...@@ -39,7 +42,7 @@ const pages = [
'high-dimensional', 'high-dimensional',
'hyper-parameter' 'hyper-parameter'
]; ];
const dataDir = path.resolve(__dirname, '../data'); const dataDir = path.resolve(cwd, '../data');
async function start() { async function start() {
rimraf.sync(dataDir); rimraf.sync(dataDir);
...@@ -65,7 +68,7 @@ async function start() { ...@@ -65,7 +68,7 @@ async function start() {
publicPath publicPath
], ],
{ {
cwd: path.resolve(__dirname, '../logs'), cwd: path.resolve(cwd, '../logs'),
stdio: ['ignore', 'pipe', 'pipe'] stdio: ['ignore', 'pipe', 'pipe']
} }
); );
......
...@@ -17,9 +17,12 @@ ...@@ -17,9 +17,12 @@
import {Request, Response} from 'express'; import {Request, Response} from 'express';
import IO from './builder/io'; import IO from './builder/io';
import {fileURLToPath} from 'url';
import meta from './data/meta.json'; import meta from './data/meta.json';
import path from 'path'; import path from 'path';
const cwd = path.dirname(fileURLToPath(import.meta.url));
function notFound(res: Response) { function notFound(res: Response) {
res.status(404).send({ res.status(404).send({
status: 1, status: 1,
...@@ -42,7 +45,7 @@ export default async (req: Request, res: Response) => { ...@@ -42,7 +45,7 @@ export default async (req: Request, res: Response) => {
return notFound(res); return notFound(res);
} }
res.sendFile(path.join(__dirname, 'data/data', data.uri, data.filename), { res.sendFile(path.join(cwd, 'data/data', data.uri, data.filename), {
headers: data.headers headers: data.headers
}); });
}; };
...@@ -22,29 +22,30 @@ ...@@ -22,29 +22,30 @@
"url": "https://github.com/PaddlePaddle/VisualDL.git", "url": "https://github.com/PaddlePaddle/VisualDL.git",
"directory": "frontend/packages/demo" "directory": "frontend/packages/demo"
}, },
"type": "module",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"files": [ "files": [
"dist" "dist"
], ],
"scripts": { "scripts": {
"build": "rimraf dist data && ts-node --script-mode builder/index.ts && tsc && cpy data dist/ --parents", "build": "rimraf dist data && node --loader ts-node/esm --es-module-specifier-resolution=node builder/index.ts && tsc && cpy data dist/ --parents",
"test": "echo \"Error: no test specified\" && exit 0" "test": "echo \"Error: no test specified\" && exit 0"
}, },
"devDependencies": { "devDependencies": {
"@types/express": "4.17.11", "@types/express": "4.17.12",
"@types/mkdirp": "1.0.1", "@types/mkdirp": "1.0.1",
"@types/node": "15.3.0", "@types/node": "15.12.1",
"@types/node-fetch": "2.5.10", "@types/node-fetch": "2.5.10",
"@types/rimraf": "3.0.0", "@types/rimraf": "3.0.0",
"cpy-cli": "3.1.1", "cpy-cli": "3.1.1",
"get-port": "5.1.1", "get-port": "5.1.1",
"mime-types": "2.1.30", "mime-types": "2.1.31",
"mkdirp": "1.0.4", "mkdirp": "1.0.4",
"node-fetch": "2.6.1", "node-fetch": "2.6.1",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"ts-node": "9.1.1", "ts-node": "10.0.0",
"typescript": "4.2.4" "typescript": "4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"express": "^4.17.1" "express": "^4.17.1"
......
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2018", "target": "ESNext",
"module": "commonjs", "module": "ESNext",
"lib": [ "lib": [
"esnext", "esnext",
"esnext.asynciterable" "esnext.asynciterable"
......
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
// cspell:words svgs multipass
import {ensureDir, remove} from 'fs-extra';
import babel from '@babel/core';
import camelCase from 'camelcase';
import {fileURLToPath} from 'url';
import fs from 'fs/promises';
import path from 'path';
import {optimize as svgo} from 'svgo';
import svgr from '@svgr/core';
const cwd = path.dirname(fileURLToPath(import.meta.url));
const src = path.resolve(cwd, './icons');
const components = path.resolve(cwd, './components');
const svgs = path.resolve(cwd, './svgs');
async function transform(file, minified = false) {
const basename = path.basename(file, '.svg');
const jsx = await svgr.default(
await fs.readFile(file, 'utf-8'),
{
plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx'],
icon: true,
svgProps: {
fill: 'currentColor',
className: 'vdl-icon'
}
},
{componentName: camelCase(basename).replace(/./, w => w.toUpperCase())}
);
const result = await babel.transformAsync(jsx, {
filename: basename + '.jsx',
presets: ['@babel/preset-react'],
minified
});
return result.code;
}
async function optimize(file) {
const result = svgo(await fs.readFile(file, 'utf-8'), {
multipass: true
});
return result.data;
}
async function build() {
await remove(components);
await ensureDir(components);
await remove(svgs);
await ensureDir(svgs);
const files = await fs.readdir(src);
for (const file of files) {
if (path.extname(file) === '.svg') {
const filePath = path.join(src, file);
const js = await transform(filePath, true);
await fs.writeFile(path.join(components, path.basename(file, '.svg') + '.js'), js, 'utf-8');
const svg = await optimize(filePath);
await fs.writeFile(path.join(svgs, file), svg, 'utf-8');
}
}
}
build();
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
import type React from 'react';
export default function (
type: string
): Promise<{default: React.ForwardRefRenderFunction<SVGSVGElement, React.SVGAttributes<SVGSVGElement>>}>;
/**
* Copyright 2020 Baidu Inc. All Rights Reserved.
*
* 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.
*/
export default type => import(`./components/${type}.js`);
{ {
"name": "@visualdl/cli", "name": "@visualdl/icons",
"version": "2.2.0-1", "version": "2.2.0-1",
"description": "A platform to visualize the deep learning process and result.", "description": "A platform to visualize the deep learning process and result.",
"keywords": [ "keywords": [
...@@ -20,32 +20,34 @@ ...@@ -20,32 +20,34 @@
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/PaddlePaddle/VisualDL.git", "url": "https://github.com/PaddlePaddle/VisualDL.git",
"directory": "frontend/packages/cli" "directory": "frontend/packages/icons"
}, },
"scripts": { "main": "index.js",
"build": "tsc", "module": "index.js",
"dev": "cross-env NODE_ENV=development ts-node index.ts", "type": "module",
"start": "node index.js", "types": "index.d.ts",
"test": "echo \"Error: no test specified\" && exit 0"
},
"bin": "dist/index.js",
"types": "dist/index.d.ts",
"files": [ "files": [
"dist" "index.js",
"index.d.ts",
"svgs",
"components"
], ],
"dependencies": { "scripts": {
"@visualdl/server": "2.2.0-1", "build": "node build.js",
"open": "8.0.9", "test": "echo \"Error: no test specified\" && exit 0"
"ora": "5.4.0",
"pm2": "4.5.6",
"yargs": "17.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "15.3.0", "@babel/core": "7.14.3",
"@types/yargs": "16.0.2", "@babel/preset-react": "7.13.13",
"cross-env": "7.0.3", "@svgr/core": "5.5.0",
"ts-node": "9.1.1", "@svgr/plugin-jsx": "5.5.0",
"typescript": "4.2.4" "@svgr/plugin-svgo": "5.5.0",
"camelcase": "6.2.0",
"fs-extra": "10.0.0",
"svgo": "2.3.0"
},
"peerDependencies": {
"react": "^16.0.0 || ^17.0.0"
}, },
"engines": { "engines": {
"node": ">=12", "node": ">=12",
......
# VisualDL FrontEnd Mock # VisualDL FrontEnd Mock
Mock data for development. Mock data for development.
## Build
```bash
yarn build
```
[net]
# Testing
# batch=1
# subdivisions=1
# Training
batch=64
subdivisions=16
width=608
height=608
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1
learning_rate=0.001
burn_in=1000
max_batches = 500200
policy=steps
steps=400000,450000
scales=.1,.1
[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky
# Downsample
[convolutional]
batch_normalize=1
filters=64
size=3
stride=2
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=32
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
# Downsample
[convolutional]
batch_normalize=1
filters=128
size=3
stride=2
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=64
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=64
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
# Downsample
[convolutional]
batch_normalize=1
filters=256
size=3
stride=2
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
# Downsample
[convolutional]
batch_normalize=1
filters=512
size=3
stride=2
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
# Downsample
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=2
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky
[shortcut]
from=-3
activation=linear
######################
[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=1024
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=1024
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=1024
activation=leaky
[convolutional]
size=1
stride=1
pad=1
filters=255
activation=linear
[yolo]
mask = 6,7,8
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
classes=80
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1
[route]
layers = -4
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[upsample]
stride=2
[route]
layers = -1, 61
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=512
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=512
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=512
activation=leaky
[convolutional]
size=1
stride=1
pad=1
filters=255
activation=linear
[yolo]
mask = 3,4,5
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
classes=80
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1
[route]
layers = -4
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[upsample]
stride=2
[route]
layers = -1, 36
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=256
activation=leaky
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=256
activation=leaky
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=256
activation=leaky
[convolutional]
size=1
stride=1
pad=1
filters=255
activation=linear
[yolo]
mask = 0,1,2
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
classes=80
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1
...@@ -14,21 +14,24 @@ ...@@ -14,21 +14,24 @@
* limitations under the License. * limitations under the License.
*/ */
import {Request, Response} from 'express'; import audio1 from '../../assets/audio/1.mp3';
import audio2 from '../../assets/audio/2.wav';
import fs from 'fs/promises'; import audio3 from '../../assets/audio/3.mp3';
import audio4 from '../../assets/audio/4.wav';
import audio5 from '../../assets/audio/5.wav';
import audio6 from '../../assets/audio/6.mp3';
import audio7 from '../../assets/audio/7.wav';
import mime from 'mime-types'; import mime from 'mime-types';
import path from 'path';
const audios = ['1.mp3', '2.wav', '3.mp3', '4.wav', '5.wav', '6.mp3', '7.wav']; const audios = [audio1, audio2, audio3, audio4, audio5, audio6, audio7];
export default async (req: Request, res: Response) => { export default async req => {
const index = (+req.query.index ?? 0) % audios.length; const index = +(req.query.index ?? 0) % audios.length;
const file = path.resolve(__dirname, '../../assets/audio', audios[index]); const result = await fetch(audios[index]);
const result = await fs.readFile(file); const response = new Response(await result.arrayBuffer());
const contentType = mime.contentType(audios[index]); const contentType = mime.contentType(audios[index]);
if (contentType) { if (contentType) {
res.setHeader('Content-Type', contentType); response.headers.set('Content-Type', contentType);
} }
return result; return response;
}; };
...@@ -15,4 +15,3 @@ ...@@ -15,4 +15,3 @@
*/ */
export default ['embeddings', 'scalar', 'image', 'text', 'graph', 'pr_curve', 'roc_curve']; export default ['embeddings', 'scalar', 'image', 'text', 'graph', 'pr_curve', 'roc_curve'];
// export default ['embeddings', 'scalar', 'image', 'audio', 'text', 'graph', 'histogram', 'pr_curve', 'roc_curve'];
...@@ -14,24 +14,23 @@ ...@@ -14,24 +14,23 @@
* limitations under the License. * limitations under the License.
*/ */
import {Request, Response} from 'express'; import iris from '../../assets/embedding/metadata/metadata-edited.tsv';
import word2vec from '../../assets/embedding/metadata/word2vec_10000_200d_labels.tsv';
import fs from 'fs/promises';
import path from 'path';
const metadatas = { const metadatas = {
'Word2Vec 10K': 'word2vec_10000_200d_labels.tsv', 'Word2Vec 10K': word2vec,
Iris: 'metadata-edited.tsv' Iris: iris
}; };
export default async (req: Request, res: Response) => { export default async req => {
const metadata = metadatas[req.query.name + '']; const metadata = metadatas[req.query.name + ''];
res.setHeader('Content-Type', 'text/tab-separated-values');
if (!metadata) { if (!metadata) {
res.status(404); return new Response('', {status: 404});
return '';
} }
const file = path.resolve(__dirname, '../../assets/embedding/metadata', metadata); const result = await fetch(metadata);
const result = await fs.readFile(file); return new Response(await result.text(), {
return result.toString('utf-8'); headers: {
'Content-Type': 'text/tab-separated-values'
}
});
}; };
...@@ -14,24 +14,23 @@ ...@@ -14,24 +14,23 @@
* limitations under the License. * limitations under the License.
*/ */
import {Request, Response} from 'express'; import iris from '../../assets/embedding/tensor/iris_tensors.bytes';
import word2vec from '../../assets/embedding/tensor/word2vec_10000_200d_tensors.bytes';
import fs from 'fs/promises';
import path from 'path';
const tensors = { const tensors = {
'Word2Vec 10K': 'word2vec_10000_200d_tensors.bytes', 'Word2Vec 10K': word2vec,
Iris: 'iris_tensors.bytes' Iris: iris
}; };
export default async (req: Request, res: Response) => { export default async req => {
const tensor = tensors[req.query.name + '']; const tensor = tensors[req.query.name + ''];
res.setHeader('Content-Type', 'application/octet-stream');
if (!tensor) { if (!tensor) {
res.status(404); return new Response(new ArrayBuffer(0), {status: 404});
return Buffer.from(new ArrayBuffer(0));
} }
const file = path.resolve(__dirname, '../../assets/embedding/tensor', tensor); const result = await fetch(tensor);
const result = await fs.readFile(file); return new Response(await result.arrayBuffer(), {
return result; headers: {
'Content-Type': 'application/octet-stream'
}
});
}; };
...@@ -14,14 +14,18 @@ ...@@ -14,14 +14,18 @@
* limitations under the License. * limitations under the License.
*/ */
/* eslint-disable @typescript-eslint/no-var-requires */ // cSpell:disable
const {middleware} = require('@visualdl/mock'); import graph from '../../assets/graph/yolov3.cfg';
const {createProxyMiddleware} = require('http-proxy-middleware');
module.exports = { export default async () => {
middleware: process.env.MOCK const result = await fetch(graph);
? () => createProxyMiddleware({target: process.env.MOCK, changeOrigin: true})
: middleware, return new Response(await result.arrayBuffer(), {
pathname: '/api' status: 200,
headers: {
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment; filename="yolov3.cfg"'
}
});
}; };
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册