Skip to content

Commit

Permalink
feat: support release (microsoft#361)
Browse files Browse the repository at this point in the history
* feat: support release and set electron version to ^3.0.13

* docs: update readme to include destop app and release support

* style: remove blank lines

* fix: redirect load failed to home page

* docs: add to test runbook

* feat: support latest electron versions

* feat: support mac menu

* fix: downgrade to supported version of electron 8.3.0

* docs: update readme with release folder info

* fix: mac issue with command bar

* fix: support cmaps

* docs: update readme

Co-authored-by: kunzheng <[email protected]>
  • Loading branch information
stew-ro and kunzms authored Jul 2, 2020
1 parent 11c6c38 commit 7192170
Show file tree
Hide file tree
Showing 17 changed files with 204 additions and 86 deletions.
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Form Labeling Tool requires [NodeJS (>= 10.x, Dubnium) and NPM](https://github.c
cd OCR-Form-Tools
yarn install
yarn build
yarn react-start
yarn start
```

### Set up this tool with Docker
Expand All @@ -44,7 +44,28 @@ Please see instructions [here](https://docs.microsoft.com/en-us/azure/cognitive-

Using a modern Web browser, FOTT can be run directly at: https://fott.azurewebsites.net/

**Note: The site is for testing purpose only.**
### Run as desktop application

FOTT can be run as a desktop application after initial set up.

```bash
yarn electron-start
```

The desktop application has additional features, such as:
- Support for local file system as provider storage
- Support for cross-domain resource requests

### Release as desktop application

FOTT can be released as a distributable desktop application.

```bash
yarn release
```
The distributable will saved in the releases folder of the cloned repository.

**Note: the site is for testing purpose only.**

## Using labeling tool

Expand Down
Binary file removed app-icons/Tag.png
Binary file not shown.
Binary file modified app-icons/icon.icns
Binary file not shown.
Binary file modified app-icons/icon.ico
Binary file not shown.
Binary file modified app-icons/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 27 additions & 2 deletions docs/manual_testing/manual-test-runbook.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
# Test Runbook

## Feat: support distributable releasing

> ### Feature description ###
- Support distributable releasing for Windows, Mac, and Linux

> ### Use Case ###
**As** a user
**I want** to release my project as a distributable
**So** I can easily set up FOTT

> ### Acceptance criteria ###
#### Scenario One ####

**Given** I've updated dependencies.
**When** I run `yarn release`.
**Then** a distributable installer should be created in the releases folder.

#### Scenario Two ####

**Given** I've created a distributable installer.
**When** I execute the installer.
**Then** a the FOTT desktop application should install and run as expected.

___

## Feat: support document management

> ### Feature description ###
Expand All @@ -11,8 +38,6 @@
**I want** to delete a document and it's files through FOTT
**So** I don't have to delete the document through a storage provider

> ### Acceptance criteria ###
#### Scenario One ####

**Given** I've selected a document in the editor page.
Expand Down
21 changes: 21 additions & 0 deletions electron-builder.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# only use if package.json doesn't contain a "build"

directories:
output: releases
buildResources: app-icons # this is where app-icons is store
appId: com.microsoft.vott
artifactName: '${productName}-${version}-${platform}.${ext}'
extends: null # need this otherwise it won't use the entry point we set in "main" in package.json
files:
- filter:
- build/ # copy this directory to the asar directory that electron-builder use to look for the main entry file
mac:
icon: app-icons/icon.icns
target: dmg
identity: null # don't sign the app
win:
icon: app-icons/icon.ico
linux:
target:
- snap
publish: null
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"url": "https://github.com/microsoft/OCR-Form-Tools"
},
"description": "OCR Form Labeling Tool - an labeling tool for forms.",
"homepage": ".",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/OCR-Form-Tools"
Expand All @@ -14,13 +15,13 @@
"private": true,
"main": "build/main.js",
"dependencies": {
"file-type": "^14.6.2",
"@azure/storage-blob": "10.3.0",
"@fluentui/react": "^7.117.2",
"axios": "^0.19.0",
"bootstrap": "^4.4.1",
"chart.js": "^2.9.3",
"exif-js": "^2.3.0",
"file-type": "^14.6.2",
"lodash": "^4.17.15",
"ol": "^5.3.3",
"promise.allsettled": "^1.0.2",
Expand Down Expand Up @@ -59,7 +60,8 @@
"electron:run:prod": "yarn webpack:prod && electron . --remote-debugging-port=9223",
"electron:start:dev": "yarn electron-start",
"electron:start:prod": "yarn webpack:prod && yarn electron-start",
"electron-start": "yarn webpack:dev && node src/electron/start",
"electron-start": "node src/electron/start",
"release": "yarn build && yarn webpack:prod && yarn electron-builder",
"tslint": "./node_modules/.bin/tslint 'src/**/*.ts*'",
"tslintfix": "./node_modules/.bin/tslint 'src/**/*.ts*' --fix"
},
Expand Down Expand Up @@ -94,17 +96,17 @@
"@types/reactstrap": "^8.2.0",
"@types/redux-logger": "^3.0.7",
"acorn": "^7.1.1",
"foreman": "^3.0.1",
"electron": "^8.3.0",
"electron": "8.3.0",
"electron-builder": "^22.6.1",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"eslint-utils": "^1.4.3",
"foreman": "^3.0.1",
"jquery": "^3.5.0",
"kind-of": "^6.0.3",
"minimist": "^1.2.2",
"node-sass": "^4.14.1",
"pdfjs-dist": "2.3.200",
"pdfjs-dist": "^2.4.456",
"react-scripts": "3.4.1",
"redux-immutable-state-invariant": "^2.1.0",
"redux-logger": "^3.0.6",
Expand Down
Binary file modified public/favicon.ico
Binary file not shown.
8 changes: 5 additions & 3 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

import { appInfo } from "./appInfo"

const appVersionArr = appInfo.version.split(".");
appVersionArr[1] = appVersionArr[1] + "-preview";
const appVersion = appVersionArr.join(".");

const appVersion = "2.1-preview.1";
const apiVersion = "v2.1-preview.1";

/**
Expand Down Expand Up @@ -34,10 +36,10 @@ export const constants = {
apiModelsPath: `/formrecognizer/${apiVersion}/custom/models`,

pdfjsWorkerSrc(version: string) {
return `//fotts.azureedge.net/npm/pdfjs-dist/${version}/pdf.worker.js`;
return `http://fotts.azureedge.net/npm/pdfjs-dist/${version}/pdf.worker.js`;
},

pdfjsCMapUrl(version: string) {
return `//fotts.azureedge.net/npm/pdfjs-dist/${version}/cmaps/`;
return `http://fotts.azureedge.net/npm/pdfjs-dist/${version}/cmaps/`;
},
};
40 changes: 25 additions & 15 deletions src/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,27 @@ import LocalFileSystem from "./providers/storage/localFileSystem";
let mainWindow: BrowserWindow | null;
let ipcMainProxy: IpcMainProxy;

const isMac = process.platform === "darwin"
const isLinux = process.platform === "linux"

async function createWindow() {
const windowOptions: BrowserWindowConstructorOptions = {
width: 1024,
height: 768,
minWidth: 450,
minHeight: 100,
frame: process.platform === "linux",
frame: isLinux,
titleBarStyle: "hidden",
backgroundColor: "#272B30",
show: false,
icon: "app-icons/Tag.png"
icon: "app-icons/icon.png"
};
windowOptions.webPreferences = {
nodeIntegration: true,
webSecurity: false,
};

const staticUrl = process.env.ELECTRON_START_URL || `file:///${__dirname}/index.html`;
if (process.env.ELECTRON_START_URL) {
windowOptions.webPreferences = {
nodeIntegration: true,
webSecurity: false,
};
}

mainWindow = new BrowserWindow(windowOptions);
mainWindow.loadURL(staticUrl);
mainWindow.maximize();
Expand All @@ -43,6 +43,10 @@ async function createWindow() {
ipcMainProxy.unregisterAll();
});

mainWindow.webContents.on("did-fail-load", () => {
mainWindow.loadURL(staticUrl);
});

mainWindow.once("ready-to-show", () => {
mainWindow.show();
});
Expand Down Expand Up @@ -92,10 +96,10 @@ function registerContextMenu(browserWindow: BrowserWindow): void {
const menuItems: MenuItemConstructorOptions[] = [
{
label: "File", submenu: [
{ role: "quit" },
isMac ? { role: "close" } : { role: "quit" }
],
},
// { role: "editMenu" },
{ role: "editMenu" },
{
label: "View", submenu: [
{ role: "reload" },
Expand All @@ -109,10 +113,16 @@ function registerContextMenu(browserWindow: BrowserWindow): void {
],
},
{
label: "Window", submenu: [
{ role: "minimize" },
{ role: "close" },
]
label: "Window", submenu:
(isMac ? [
{ role: "minimize" },
{ role: "front" },
{ type: "separator" },
{ role: "window" }
] : [
{ role: "minimize" },
{ role: "close" }
])
},
];
const menu = Menu.buildFromTemplate(menuItems);
Expand Down
2 changes: 1 addition & 1 deletion src/electron/providers/storage/localFileSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default class LocalFileSystem implements IStorageProvider {
properties: ["openDirectory", "createDirectory"],
});

if (!result.filePaths || result.filePaths.length !== 1) {
if (!result || result.filePaths.length !== 1) {
return reject();
}

Expand Down
3 changes: 2 additions & 1 deletion src/electron/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@ const tryConnection = () => client.connect({ port: port }, () => {
tryConnection();

client.on("error", (error) => {
setTimeout(tryConnection, 1000);
console.log(`Trying to connect to ${process.env.ELECTRON_START_URL}... (start web service with 'yarn react-start')`);
setTimeout(tryConnection, 10000);
});
1 change: 0 additions & 1 deletion src/react/components/common/assetPreview/pdfAsset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import * as pdfjsLib from "pdfjs-dist";
import { constants } from "../../../../common/constants";
import {resizeCanvas} from "../../../../common/utils";

// temp hack for enabling worker
pdfjsLib.GlobalWorkerOptions.workerSrc = constants.pdfjsWorkerSrc(pdfjsLib.version);

export interface IPDFAssetState {
Expand Down
1 change: 1 addition & 0 deletions src/react/components/pages/predict/predictPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { getPrimaryGreenTheme, getPrimaryWhiteTheme,
getGreenWithWhiteBackgroundTheme } from "../../../../common/themes";
import axios from "axios";

pdfjsLib.GlobalWorkerOptions.workerSrc = constants.pdfjsWorkerSrc(pdfjsLib.version);
const cMapUrl = constants.pdfjsCMapUrl(pdfjsLib.version);

export interface IPredictPageProps extends RouteComponentProps, React.Props<PredictPage> {
Expand Down
36 changes: 19 additions & 17 deletions src/react/components/shell/titleBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ import { PlatformType, isElectron } from "../../../common/hostProcess";
import { getLightGreyTheme, getSubMenuTheme } from "../../../common/themes";
import "./titleBar.scss";

const isElectronCheck = isElectron();
const platform = global && global.process && global.process.platform ? global.process.platform : PlatformType.Web;
const isMac = platform === "darwin";
const isLinux = platform === "linux";
const isElectronAndNotMacOrLinux = isElectronCheck && !(isMac || isLinux);
const isNotElectronAndMacOrLinux = !(isElectronCheck && (isMac || isLinux));

export interface ITitleBarProps extends React.Props<TitleBar> {
icon?: string | JSX.Element;
title?: string;
}

export interface ITitleBarState {
isElectron: boolean;
platform: string;
maximized: boolean;
fullscreen: boolean;
menu: Electron.Menu;
Expand All @@ -31,21 +36,16 @@ function mapStateToProps(state: IApplicationState) {
@connect(mapStateToProps, null)
export class TitleBar extends React.Component<ITitleBarProps, ITitleBarState> {
public state: ITitleBarState = {
isElectron: false,
platform: global && global.process && global.process.platform ? global.process.platform : PlatformType.Web,
maximized: false,
fullscreen: false,
menu: null,
};

private isElectron: boolean;
private remote: Electron.Remote;
private currentWindow: Electron.BrowserWindow;

public componentDidMount() {
this.isElectron = isElectron();

if (this.isElectron) {
if (isElectronCheck) {
this.remote = window.require("electron").remote as Electron.Remote;
this.currentWindow = this.remote.getCurrentWindow();
this.currentWindow.on("maximize", () => this.onMaximize(true));
Expand Down Expand Up @@ -106,11 +106,13 @@ export class TitleBar extends React.Component<ITitleBarProps, ITitleBarState> {

return (
<div className="title-bar bg-lighter-3">
<div className="title-bar-icon">
{typeof (this.props.icon) === "string" && <FontIcon iconName={this.props.icon} />}
{typeof (this.props.icon) !== "string" && this.props.icon}
</div>
{this.isElectron &&
{isNotElectronAndMacOrLinux &&
<div className="title-bar-icon">
{typeof (this.props.icon) === "string" && <FontIcon iconName={this.props.icon} />}
{typeof (this.props.icon) !== "string" && this.props.icon}
</div>
}
{isElectronAndNotMacOrLinux &&
<Customizer {...titleBarTheme}>
<OverflowSet
role="menubar"
Expand All @@ -123,7 +125,7 @@ export class TitleBar extends React.Component<ITitleBarProps, ITitleBarState> {
<div className="title-bar-main">{this.props.title || "Welcome"}</div>
<div className="title-bar-controls">
{this.props.children}
{this.isElectron &&
{isElectronAndNotMacOrLinux &&
[
<Separator vertical key="seperator" className="mr-2 ml-2"/>,
<div key="minimizeDiv">
Expand Down Expand Up @@ -191,11 +193,11 @@ export class TitleBar extends React.Component<ITitleBarProps, ITitleBarState> {

private onMenuItemClick(e: any, menuItem: Electron.MenuItem) {
if (menuItem.label === "Zoom In") {
this.currentWindow.webContents.setZoomLevel(this.currentWindow.webContents.zoomLevel + .3);
this.currentWindow.webContents.setZoomLevel(this.currentWindow.webContents.getZoomLevel() + .3)
} else if (menuItem.label === "Zoom Out") {
this.currentWindow.webContents.setZoomLevel(this.currentWindow.webContents.zoomLevel - .3);
this.currentWindow.webContents.setZoomLevel(this.currentWindow.webContents.getZoomLevel() - .3)
} else if (menuItem.label === "Reset Zoom") {
this.currentWindow.webContents.setZoomLevel(-3);
this.currentWindow.webContents.setZoomLevel(0);
} else if (menuItem.click) {
menuItem.click.call(menuItem, menuItem, this.currentWindow);
}
Expand Down
Loading

0 comments on commit 7192170

Please sign in to comment.