Remove Open/Save buttons from Model pane
This commit is contained in:
Родитель
54ec8d2eb5
Коммит
64d73f60cf
|
@ -5,6 +5,7 @@ import { Provider } from 'react-redux'
|
|||
import App from './App';
|
||||
import store from './datastore/store';
|
||||
import './index.css';
|
||||
import { registerKeyboardShurtcuts } from './native/menu';
|
||||
import registerServiceWorker from './registerServiceWorker';
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -13,4 +14,5 @@ ReactDOM.render(
|
|||
</Provider>,
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
||||
registerKeyboardShurtcuts();
|
||||
registerServiceWorker();
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { fileFilterToAccept } from "./dialog";
|
||||
|
||||
it('converts Array<FileFilter> to HTML accept field', () => {
|
||||
expect(fileFilterToAccept([
|
||||
{ name: 'CoreML model', extensions: [ 'mlmodel' ] },
|
||||
{ name: 'Keras model', extensions: [ 'keras', 'h5' ] },
|
||||
{ name: 'ONNX model', extensions: [ 'onnx' ] },
|
||||
])).toBe('.mlmodel,.keras,.h5,.onnx');
|
||||
});
|
|
@ -7,7 +7,7 @@ import * as path from 'path';
|
|||
|
||||
import { getElectron } from './util';
|
||||
|
||||
export function filterToAccept(filters: Electron.FileFilter[]) {
|
||||
export function fileFilterToAccept(filters: Electron.FileFilter[]) {
|
||||
/**
|
||||
* Convert Electron FileFilter[] to HTML accept field.
|
||||
*/
|
||||
|
@ -46,7 +46,7 @@ export async function showOpenDialog(filters: Electron.FileFilter[]) {
|
|||
return file as File;
|
||||
});
|
||||
}
|
||||
return showWebOpenDialog(filterToAccept(filters));
|
||||
return showWebOpenDialog(fileFilterToAccept(filters));
|
||||
}
|
||||
|
||||
export function showWebSaveDialog(data: Uint8Array, filename: string) {
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* Provide native menus and shortcuts. In the web, installs shortcuts only.
|
||||
*/
|
||||
|
||||
import { setFile } from "../datastore/actionCreators";
|
||||
import { ModelProtoSingleton } from "../datastore/proto/modelProto";
|
||||
import store from "../datastore/store";
|
||||
import { save, showOpenDialog } from "./dialog";
|
||||
import { isWeb } from "./util";
|
||||
|
||||
export function createMenu(electron: typeof Electron) {
|
||||
const { Menu } = electron.remote;
|
||||
const template = [
|
||||
{
|
||||
label: 'File',
|
||||
submenu: [
|
||||
{ label: 'Open', accelerator: 'Ctrl+O', click: onOpen },
|
||||
{ label: 'Save', accelerator: 'Ctrl+S', click: onSave, enabled: false },
|
||||
],
|
||||
}, {
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{ role: 'undo' },
|
||||
{ role: 'redo' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'cut' },
|
||||
{ role: 'copy' },
|
||||
{ role: 'paste' },
|
||||
{ role: 'pasteandmatchstyle' },
|
||||
{ role: 'delete' },
|
||||
{ role: 'selectall '},
|
||||
],
|
||||
}, {
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{ role: 'toggledevtools' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'resetzoom' },
|
||||
{ role: 'zoomin' },
|
||||
{ role: 'zoomout' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'togglefullscreen '},
|
||||
],
|
||||
}, {
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{ label: 'Project Page', click () { alert('TODO') } },
|
||||
],
|
||||
}
|
||||
];
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
template.unshift({
|
||||
label: 'WinML Dashboard',
|
||||
submenu: [
|
||||
{ role: 'about' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'services', submenu: [] },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideothers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'quit '},
|
||||
],
|
||||
} as any);
|
||||
}
|
||||
|
||||
const menu = Menu.buildFromTemplate(template as any);
|
||||
store.subscribe(() => (menu.items[0] as any).submenu.items[1].enabled = !!store.getState().nodes);
|
||||
Menu.setApplicationMenu(menu);
|
||||
}
|
||||
|
||||
export function registerKeyboardShurtcuts() {
|
||||
if (isWeb()) { // Electron's accelerators are used outside web builds
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.ctrlKey) {
|
||||
switch (event.code) {
|
||||
case 'KeyS':
|
||||
onSave();
|
||||
break;
|
||||
|
||||
case 'KeyO':
|
||||
onOpen();
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onSave() {
|
||||
if (ModelProtoSingleton.proto) {
|
||||
save(ModelProtoSingleton.serialize(), 'model.onnx', [{ name: 'ONNX model', extensions: [ 'onnx', 'prototxt' ] }]);
|
||||
}
|
||||
}
|
||||
|
||||
async function onOpen() {
|
||||
const files = await showOpenDialog([
|
||||
{ name: 'ONNX Model', extensions: [ 'onnx', 'pb' ] },
|
||||
{ name: 'Keras Model', extensions: [ 'h5', 'json', 'keras' ] },
|
||||
{ name: 'CoreML Model', extensions: [ 'mlmodel' ] },
|
||||
{ name: 'Caffe Model', extensions: [ 'caffemodel' ] },
|
||||
{ name: 'Caffe2 Model', extensions: [ 'pb' ] },
|
||||
{ name: 'MXNet Model', extensions: [ 'model', 'json' ] },
|
||||
{ name: 'TensorFlow Graph', extensions: [ 'pb', 'meta' ] },
|
||||
{ name: 'TensorFlow Saved Model', extensions: [ 'pb' ] },
|
||||
{ name: 'TensorFlow Lite Model', extensions: [ 'tflite' ] }
|
||||
]);
|
||||
if (files) {
|
||||
store.dispatch(setFile(files[0]));
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ import * as fs from 'fs';
|
|||
import { createMenu } from './menu';
|
||||
|
||||
export function isWeb() {
|
||||
return !fs.exists;
|
||||
return !fs.exists || typeof it === 'function';
|
||||
}
|
||||
|
||||
let electron: typeof Electron;
|
||||
|
|
|
@ -4,6 +4,7 @@ import { connect } from 'react-redux';
|
|||
|
||||
import Collapsible from '../../components/Collapsible';
|
||||
import KeyValueEditor from '../../components/KeyValueEditor'
|
||||
import Resizable from '../../components/Resizable';
|
||||
import { setMetadataProps } from '../../datastore/actionCreators';
|
||||
import IState, { IMetadataProps } from '../../datastore/state';
|
||||
import MetadataSchema from '../../schema/Metadata';
|
||||
|
@ -27,7 +28,7 @@ class RightPanel extends React.Component<IComponentProperties, {}> {
|
|||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Resizable>
|
||||
<Label>Model</Label>
|
||||
<div className='Panel'>
|
||||
<Collapsible label='Properties'>
|
||||
|
@ -37,7 +38,7 @@ class RightPanel extends React.Component<IComponentProperties, {}> {
|
|||
<KeyValueEditor actionCreator={setMetadataProps} getState={this.getMetadataPropsFromState} schema={MetadataSchema} />
|
||||
</Collapsible>
|
||||
</div>
|
||||
</div>
|
||||
</Resizable>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,48 +1,19 @@
|
|||
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
|
||||
import * as React from 'react';
|
||||
|
||||
import Resizable from '../../components/Resizable';
|
||||
import { ModelProtoSingleton } from '../../datastore/proto/modelProto';
|
||||
import { showWebOpenDialog, showWebSaveDialog } from '../../native/dialog';
|
||||
import LeftPanel from './LeftPanel';
|
||||
import * as netron from './netron/Netron';
|
||||
import { Netron } from './netron/Netron';
|
||||
import RightPanel from './RightPanel';
|
||||
|
||||
import './View.css';
|
||||
|
||||
interface IComponentState {
|
||||
file?: File,
|
||||
}
|
||||
|
||||
export default class EditView extends React.Component<{}, IComponentState> {
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
this.state = {
|
||||
file: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export default class EditView extends React.Component {
|
||||
public render() {
|
||||
return (
|
||||
<div id='EditView'>
|
||||
<LeftPanel />
|
||||
<netron.Netron />
|
||||
<Resizable>
|
||||
<DefaultButton text='Open file' onClick={this.openFile}/>
|
||||
<DefaultButton text='Save file' onClick={this.saveFile}/>
|
||||
<RightPanel />
|
||||
</Resizable>
|
||||
<Netron />
|
||||
<RightPanel />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private openFile = () =>
|
||||
showWebOpenDialog('.onnx,.pb,.meta,.tflite,.keras,.h5,.json,.mlmodel,.caffemodel')
|
||||
.then((files) => {
|
||||
if (files) {
|
||||
this.setState({ file: files[0] });
|
||||
}
|
||||
});
|
||||
|
||||
private saveFile = () => showWebSaveDialog(ModelProtoSingleton.serialize(), 'model.onnx');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs"
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче