feat: complete boilerplate overhaul. main/renderer processes split, scripts updated, i18n, pre-commit, locales, tests, webpack configs, hot, store updated, configs redesigned

This commit is contained in:
Andrzej Ziolek
2019-11-18 07:18:44 +01:00
parent 8713158aa0
commit 644025e8d9
111 changed files with 10658 additions and 7564 deletions

16
.editorconfig Executable file
View File

@@ -0,0 +1,16 @@
# http://editorconfig.org/
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{json,yml,js,ts,tsx,css,scss,graphql,gql,html}]
indent_size = 2

3
.env
View File

@@ -1,3 +0,0 @@
AWS_ACCESS_KEY_ID=AKIAJJ66DJJUOB5YDCTQ
AWS_SECRET_ACCESS_KEY=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
BUCKET_NAME=pure-app-develop

View File

@@ -1,3 +0,0 @@
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
BUCKET_NAME=

View File

@@ -1,17 +0,0 @@
Jira: [YY-XXX]
**Description**
<details>
<summary><b>Screenshots</b></summary>
// put images here
</details>
**PR Status**
- [ ] Code Review
- [ ] Quality Assurance
**Blockers**
**Deploy Notes**

View File

@@ -1,24 +0,0 @@
name: Linting
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install, build, and test
run: |
npm install
npm run lint
env:
CI: true

View File

@@ -1,24 +0,0 @@
name: Unit Tests
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install, build, and test
run: |
npm install
npm test
env:
CI: true

View File

@@ -1,24 +0,0 @@
name: Type Checking
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install, build, and test
run: |
npm install
npm run type-check
env:
CI: true

14
.gitignore vendored
View File

@@ -25,19 +25,19 @@ build/Release
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
app/node_modules
src/node_modules
# OSX
.DS_Store
# App packaged
release
app/main.js
app/main.js.map
app/bundle.js
app/bundle.js.map
app/style.css
app/style.css.map
src/main.js
src/main.js.map
src/bundle.js
src/bundle.js.map
src/style.css
src/style.css.map
dist
main.js
main.js.map

1
.nvmrc
View File

@@ -1 +0,0 @@
12.9.1

View File

@@ -1,12 +1,13 @@
import { configure, addDecorator } from "@storybook/react"
import { action } from "@storybook/addon-actions"
import GlobalStyle from "../app/theming/global-style.component"
import { Normalize } from "styled-normalize"
import React from "react"
import { ThemeProvider } from "styled-components"
import theme from "../app/theming/theme"
import { Normalize } from "styled-normalize"
import { configure, addDecorator } from "@storybook/react"
import { action } from "@storybook/addon-actions"
const req = require.context("../app", true, /\.stories\.tsx$/)
import GlobalStyle from "Renderer/styles/global-style.component"
import theme from "Renderer/styles/theming/theme"
const req = require.context("../src", true, /\.stories\.tsx$/)
function loadStories() {
req.keys().forEach(filename => req(filename))
}

View File

@@ -1,3 +1,5 @@
const { resolve } = require('../webpack/resolve');
module.exports = ({ config }) => {
// use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
config.module.rules[0].use[0].loader = require.resolve("babel-loader")
@@ -27,7 +29,7 @@ module.exports = ({ config }) => {
],
},
})
config.resolve.extensions.push(".ts", ".tsx")
config.resolve = resolve
return config
}

View File

@@ -1,51 +0,0 @@
sudo: false
language: node_js
node_js:
- 8
- 7
cache:
yarn: true
directories:
- node_modules
- app/node_modules
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
- icnsutils
- graphicsmagick
- xz-utils
- xorriso
before_install: yarn global add greenkeeper-lockfile@1
install:
- export CXX="g++-4.8"
- yarn
- cd app && yarn && cd ..
- /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile
--background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16
before_script:
- greenkeeper-lockfile-update
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start &
- sleep 3
script:
- node --version
- yarn package
- yarn test
- yarn test-e2e
after_script: greenkeeper-lockfile-upload
env:
global:
secure: hH+MmHE3WhyyBflZoOZLqqr501OOnvA1VtaqF3WU9rJCpjnKb4fZvHejYtVw65Ho2C40G2a34oBGxnT6INF1BfClYz4IMijL689xuR8dgStQzvcpMTwEQkrLsaCTSqXJR6nzqbRRGmaRfjSLdF6vhd3bGmtVNMEtoEky5EsXeBVjn8D5WMrme17m4F4D/qjHty6Xr5PjZL6eInVKlPZEbALYBhnIWqE5Xw6LcGa8JkqsWw80sLNtz4yWQSwkjrZ1lzCNd/GSUDN5K/BFK6kUZB5HpJZUzUoIQyXmEft+ALZFE4p4tX/H044JguPN9sKsP4SNkz2+3tOMevz/x5of3ssLMqB7gFtd5SGKwjdn6sWYNHKeM0MALyXAARhilyzY0v+xf226ZLRb++8Ih/vAZNymvQjn0idBfwC8ffUSXEx786Zysot1AqWrxaktKFHkBHkiQ4BGkAXVT4FLCgLtdMta+NLYYmuNrmXoU2iEhSzwvZmw94wcBxZie+TvuXE76TgrOiopRPbGXw/0iDm8J1MVWpoPmqSLUG5Vbq9fSNZnR/6j89j7Ws83fdnfZby+qOcV5WMJetQs/EHTxfWJu/AM6bxCYSSmXEJUb8dHpk8el8T+MGLI9pCTiiyy1ozOeo1WKpcOdmF6GU64EOxRWn2837+a9W0kXXAj6tPCW6A=

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018-present R. Franken
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

211
README.md
View File

@@ -1,213 +1,42 @@
# electron-react-typescript-boilerplate
# PDA: Mudita's Pure Desktop App
[![Build Status][travis-image]][travis-url]
[![Greenkeeper badge](https://badges.greenkeeper.io/iRath96/electron-react-typescript-boilerplate.svg)](https://greenkeeper.io/)
This is a slight modificiation of the great [electron-react-boilerplate](https://github.com/chentsulin/electron-react-boilerplate) by chentsulin.
Instead of [Babel](https://babeljs.io) and [flow](https://flowtype.org) this version uses [TypeScript](https://www.typescriptlang.org). Support for [Sass](http://sass-lang.com) has also been added.
# electron-react-boilerplate
![](./erb-logo.png)
> Live editing development on desktop app
[Electron](http://electron.atom.io/) application boilerplate based on [React](https://facebook.github.io/react/), [Redux](https://github.com/reactjs/redux), [React Router](https://github.com/reactjs/react-router), [Webpack](http://webpack.github.io/docs/), [React Transform HMR](https://github.com/gaearon/react-transform-hmr) for rapid application development
## Screenshot
![Electron Boilerplate Demo](https://cloud.githubusercontent.com/assets/3382565/10557547/b1f07a4e-74e3-11e5-8d27-79ab6947d429.gif)
### A Boilerplate for an Easy Start with TypeScript, React, and Electron.
## Install
```bash
npm install
```
* **Note: requires a node version >= 6 and an npm version >= 3.**
* **If you have installation or compilation issues with this project, please see [our debugging guide](https://github.com/chentsulin/electron-react-boilerplate/issues/400)**
First, clone the repo via git:
## Usage
Both processes have to be started **simultaneously** in different console tabs:
```bash
git clone https://github.com/iRath96/electron-react-typescript-boilerplate.git your-project-name
npm run start-renderer-dev
npm run start-main-dev
```
And then install dependencies.
**ProTip**: Install with [yarn](https://github.com/yarnpkg/yarn) for faster and safer installation
This will start the application with hot-reload so you can instantly start developing your application.
You can also run do the following to start both in a single process:
```bash
$ cd your-project-name && npm install
npm run start-dev
```
:bulb: *In order to remove boilerplate sample code, simply run `npm run cleanup`. After this is run, the initial sample boilerplate code will be removed in order for a clean project for starting custom dev*
## Run
Run these two commands __simultaneously__ in different console tabs.
```bash
$ npm run hot-server
$ npm run start-hot
```
or run two servers with one command
```bash
$ npm run dev
```
## Editor Configuration
**Atom**
```bash
apm install editorconfig es6-javascript atom-ternjs javascript-snippets linter linter-eslint language-babel autocomplete-modules
```
**Sublime**
* https://github.com/sindresorhus/editorconfig-sublime#readme
* https://github.com/SublimeLinter/SublimeLinter3
* https://github.com/roadhump/SublimeLinter-eslint
* https://github.com/babel/babel-sublime
**Others**
* [Editorconfig](http://editorconfig.org/#download)
* [ESLint](http://eslint.org/docs/user-guide/integrations#editors)
* Babel Syntax Plugin
## DevTools
#### Toggle Chrome DevTools
- OS X: <kbd>Cmd</kbd> <kbd>Alt</kbd> <kbd>I</kbd> or <kbd>F12</kbd>
- Linux: <kbd>Ctrl</kbd> <kbd>Shift</kbd> <kbd>I</kbd> or <kbd>F12</kbd>
- Windows: <kbd>Ctrl</kbd> <kbd>Shift</kbd> <kbd>I</kbd> or <kbd>F12</kbd>
*See [electron-debug](https://github.com/sindresorhus/electron-debug) for more information.*
#### DevTools extension
This boilerplate is included following DevTools extensions:
* [Devtron](https://github.com/electron/devtron) - Install via [electron-debug](https://github.com/sindresorhus/electron-debug).
* [React Developer Tools](https://github.com/facebook/react-devtools) - Install via [electron-devtools-installer](https://github.com/GPMDP/electron-devtools-installer).
* [Redux DevTools](https://github.com/zalmoxisus/redux-devtools-extension) - Install via [electron-devtools-installer](https://github.com/GPMDP/electron-devtools-installer).
You can find the tabs on Chrome DevTools.
If you want to update extensions version, please set `UPGRADE_EXTENSIONS` env, just run:
```bash
$ UPGRADE_EXTENSIONS=1 npm run dev
# For Windows
$ set UPGRADE_EXTENSIONS=1 && npm run dev
```
## CSS Modules
This boilerplate out of the box is configured to use [css-modules](https://github.com/css-modules/css-modules).
All `.css` file extensions will use css-modules unless it has `.global.css`.
If you need global styles, stylesheets with `.global.css` will not go through the
css-modules loader. e.g. `app.global.css`
If you want to import global css libraries (like `bootstrap`), you can just write the following code in `.global.css`:
```css
@import "~bootstrap/dist/css/bootstrap.css";
```
## Packaging
To package apps for the local platform:
We use [Electron builder](https://www.electron.build/) to build and package the application. By default you can run the following to package for your current platform:
```bash
$ npm run package
npm run dist
```
To package apps for all platforms:
This will create a installer for your platform in the `releases` folder.
First, refer to [Multi Platform Build](https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Build) for dependencies.
Then,
```bash
$ npm run package-all
```
To package apps with options:
You can make builds for specific platforms (or multiple platforms) by using the options found [here](https://www.electron.build/cli). E.g. building for all platforms (Windows, Mac, Linux):
```bash
$ npm run package -- --[option]
npm run dist -- -mwl
```
## Further commands
To run the application without packaging run
```bash
$ npm run build
$ npm start
```
To run End-to-End Test
```bash
$ npm run build
$ npm run test-e2e
```
#### Options
See [electron-builder CLI Usage](https://github.com/electron-userland/electron-builder#cli-usage)
#### Module Structure
This boilerplate uses a [two package.json structure](https://github.com/electron-userland/electron-builder#two-packagejson-structure).
1. If the module is native to a platform or otherwise should be included with the published package (i.e. bcrypt, openbci), it should be listed under `dependencies` in `./app/package.json`.
2. If a module is `import`ed by another module, include it in `dependencies` in `./package.json`. See [this ESLint rule](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md).
3. Otherwise, modules used for building, testing and debugging should be included in `devDependencies` in `./package.json`.
## Static Type Checking
This project comes with Flow support out of the box! You can annotate your code with types, [get Flow errors as ESLint errors](https://github.com/amilajack/eslint-plugin-flowtype-errors), and get [type errors during runtime](https://github.com/gcanti/babel-plugin-tcomb-boilerplate) during development. Types are completely optional.
## Native-like UI
If you want to have native-like User Interface (OS X El Capitan and Windows 10), [react-desktop](https://github.com/gabrielbull/react-desktop) may perfect suit for you.
## Dispatching redux actions from main process
see discusses in [#118](https://github.com/chentsulin/electron-react-boilerplate/issues/118) and [#108](https://github.com/chentsulin/electron-react-boilerplate/issues/108)
## How to keep the boilerplate updated
If your application is a fork from this repo, you can add this repo to another git remote:
```sh
git remote add upstream https://github.com/chentsulin/electron-react-boilerplate.git
```
Then, use git to merge some latest commits:
```sh
git pull upstream master
```
## Maintainers
- [C. T. Lin](https://github.com/chentsulin)
- [Jhen-Jie Hong](https://github.com/jhen0409)
- [Amila Welihinda](https://github.com/amilajack)
## License
MIT © [C. T. Lin](https://github.com/chentsulin)
[npm-image]: https://img.shields.io/npm/v/electron-react-boilerplate.svg?style=flat-square
[npm-url]: https://npmjs.org/package/electron-react-boilerplate
[travis-image]: https://travis-ci.org/iRath96/electron-react-typescript-boilerplate.svg?branch=master
[travis-url]: https://travis-ci.org/iRath96/electron-react-typescript-boilerplate
[appveyor-image]: https://ci.appveyor.com/api/projects/status/github/chentsulin/electron-react-boilerplate?svg=true
[appveyor-url]: https://ci.appveyor.com/project/chentsulin/electron-react-boilerplate/branch/master
[david_img]: https://img.shields.io/david/chentsulin/electron-react-boilerplate.svg
[david_site]: https://david-dm.org/chentsulin/electron-react-boilerplate
## Precommit and Prettier
This project comes with both Precommit and Prettier setup to ensure a consistent code style.

View File

@@ -1 +0,0 @@
module.exports = "test-file-stub"

View File

@@ -1,46 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello Electron React!</title>
<script>
(function() {
if (!process.env.HOT) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = './dist/style.css';
document.getElementsByTagName('head')[0].appendChild(link);
}
}());
</script>
</head>
<body>
<!--Current version: <span id="version">vX.Y.Z</span>-->
<!--<div id="messages"></div>-->
<div id="root"></div>
<script>
{
const script = document.createElement('script');
const port = process.env.PORT || 3000;
script.src = (process.env.HOT)
? 'http://localhost:' + port + '/dist/bundle.js'
: './dist/bundle.js';
// HACK: Writing the script path should be done with webpack
document.body.appendChild(script);
// let version = window.location.hash.substring(1);
// document.getElementById('version').innerText = version;
// // Listen for messages
// const {ipcRenderer} = require('electron');
//
// ipcRenderer.on('message', function(event, text) {
// var container = document.getElementById('messages');
// var message = document.createElement('div');
// message.innerHTML = text;
// container.appendChild(message);
// })
}
</script>
</body>
</html>

View File

Binary file not shown.

View File

@@ -1,11 +0,0 @@
import * as React from "react"
import styled from "styled-components"
import FunctionComponent from "../types/function-component.interface"
const AppWrapper = styled.div``
const AppContainer: FunctionComponent = ({ children }) => {
return <AppWrapper>{children}</AppWrapper>
}
export default AppContainer

View File

@@ -1,4 +0,0 @@
import { combineEpics } from "redux-observable"
import { setFilesEffect } from "../files/effects/files.effects"
export const rootEpic = combineEpics(setFilesEffect)

View File

@@ -1,44 +0,0 @@
export const SET_FILES = "SET FILES"
export type SET_FILES = typeof SET_FILES
export const SET_CURRENT_PATH = "SET_CURRENT_PATH"
export type SET_CURRENT_PATH = typeof SET_CURRENT_PATH
export const SET_FILES_WITH_TYPES = "SET FILES WITH TYPES"
export type SET_FILES_WITH_TYPES = typeof SET_FILES_WITH_TYPES
export interface SetFilesAction {
readonly type: SET_FILES
payload: string[]
}
export interface SetCurrentPathAction {
readonly type: SET_CURRENT_PATH
payload: string
}
export interface FileType {
type: string
name: string
}
interface SetFilesWithTypes {
readonly type: SET_FILES_WITH_TYPES
payload: FileType[]
}
export function setFiles(files: string[]): SetFilesAction {
return {
type: SET_FILES,
payload: files,
}
}
export function setCurrentPath(path: string): SetCurrentPathAction {
return {
type: SET_CURRENT_PATH,
payload: path,
}
}
export type Actions = SetFilesAction | SetCurrentPathAction | SetFilesWithTypes

View File

@@ -1,26 +0,0 @@
import * as React from "react"
import styled from "styled-components"
import FunctionComponent from "../../../types/function-component.interface"
interface FileListElementProps {
el?: string
onClick: (element: string | undefined) => void
}
const FileListElementWrapper = styled.li`
border-bottom: 1px solid #ddd;
`
const FileListElement: FunctionComponent<FileListElementProps> = ({
el,
onClick,
}) => {
const handleWrapperClick = () => onClick(el)
return (
<FileListElementWrapper onClick={handleWrapperClick}>
{el}
</FileListElementWrapper>
)
}
export default FileListElement

View File

@@ -1,96 +0,0 @@
import { useEffect } from "react"
import * as React from "react"
import { connect } from "react-redux"
import styled from "styled-components"
import RootState from "../../../reducers/state"
import FunctionComponent from "../../../types/function-component.interface"
import { setCurrentPath, setFiles } from "../../actions/files.actions"
import { State as FileState } from "../../reducers/files.reducer"
import { currentPath, selectFiles } from "../../selectors/file.selector"
import FileListElementComponent from "../file-list-element/file-list-element.component"
const { remote } = require("electron")
const mainRef = remote.require("./main.js")
const fileUtils = mainRef.electronUtils.fileUtils
interface FileProps {
link?: string
}
interface DispatchProps {
setCurrentPath: (path: string) => void
setFiles: (files: string[]) => void
}
const FilesWrapper = styled.div`
background-color: #222;
padding: 1rem;
color: white;
`
export const FilesIntro = styled.p`
font-size: large;
code {
font-size: 1.3rem;
}
`
export const FilesTitle = styled.h1`
font-weight: 900;
`
const FileListWrapper = styled.ul`
background: #00c2;
padding: 20px;
margin: 0;
padding: 0.5rem 1rem;
border: 1px solid #ddd;
border-left: 0.4rem solid red;
`
const Files: FunctionComponent<FileProps & FileState & DispatchProps> = ({
currentFolder,
filePaths,
setCurrentPath: setCurrentPathAction,
setFiles: setFilesAction,
}) => {
useEffect(() => {
fileUtils.listFiles().then(setFilesAction)
}, [])
const onElementClick = (element: string | undefined) => {
if (element) {
setCurrentPathAction(element)
}
}
return (
<FilesWrapper>
<FilesTitle>{currentFolder}</FilesTitle>
<FilesIntro>File list below</FilesIntro>
<FileListWrapper>
{filePaths.map((el, key) => (
<FileListElementComponent
onClick={onElementClick}
key={key}
el={el.name}
/>
))}
</FileListWrapper>
</FilesWrapper>
)
}
const mapStateToProps = (state: RootState): FileState => ({
currentFolder: currentPath(state),
filePaths: selectFiles(state),
})
const mapDispatchToProps = (dispatch: any): DispatchProps => ({
setCurrentPath: (path: string) => dispatch(setCurrentPath(path)),
setFiles: (path: string[]) => dispatch(setFiles(path)),
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(Files)

View File

@@ -1,34 +0,0 @@
import { ofType } from "redux-observable"
import { flatMap, map, tap } from "rxjs/operators"
import {
SET_FILES,
SET_FILES_WITH_TYPES,
SetFilesAction,
} from "../actions/files.actions"
const { remote } = require("electron")
const mainRef = remote.require("./main.js")
const fileUtils = mainRef.electronUtils.fileUtils
export const setFilesEffect = (action$: any) =>
action$.pipe(
ofType(SET_FILES),
tap(() => console.log("Setting path type")), // debugging
flatMap((action: SetFilesAction) => {
return Promise.all(
action.payload.map(async (el: string) => {
return {
name: el,
type: await fileUtils.checkType(el),
}
})
)
}),
map(data => {
return {
type: SET_FILES_WITH_TYPES,
payload: data,
}
})
)

View File

@@ -1,23 +0,0 @@
import * as React from "react"
import styled from "styled-components"
import Navigation from "../../../shared/components/navigation/navigation.component"
import FunctionComponent from "../../../types/function-component.interface"
import Files from "../../components/file/files.component"
const FilePageWrapper = styled.div`
display: flex;
flex-direction: column;
border: 1px #ccc dotted;
padding: 10px;
`
const FilesPage: FunctionComponent = () => {
return (
<FilePageWrapper>
<Navigation />
<Files />
</FilePageWrapper>
)
}
export default FilesPage

View File

@@ -1,22 +0,0 @@
import { expect } from "chai"
import { setCurrentPath } from "../actions/files.actions"
import { getInitialState, reducer } from "./files.reducer"
test("starts with empty path", () => {
expect(getInitialState().currentFolder).eq("")
})
test("starts with empty file paths", () => {
expect(getInitialState().filePaths).deep.eq([])
})
test("returns the state on unrecognized actions", () => {
const state = getInitialState()
expect(reducer(state, { type: "SOME_RANDOM_UNKNOWN" } as any)).eq(state)
})
test("sets current path to given", () => {
const state = getInitialState()
const expectedState = { ...getInitialState(), currentFolder: "currentPath" }
expect(reducer(state, setCurrentPath("currentPath"))).deep.eq(expectedState)
})

View File

@@ -1,32 +0,0 @@
import * as filesAction from "../actions/files.actions"
import { FileType } from "../actions/files.actions"
export interface State {
readonly currentFolder: string
readonly filePaths: FileType[]
}
export const getInitialState = (): State =>
({
currentFolder: "",
filePaths: [],
} as State)
const initState = getInitialState()
export function reducer(state: State = initState, action: filesAction.Actions) {
switch (action.type) {
case filesAction.SET_CURRENT_PATH:
return {
...state,
currentFolder: action.payload,
}
case filesAction.SET_FILES_WITH_TYPES:
return {
...state,
filePaths: [...action.payload],
}
default:
return state
}
}

View File

@@ -1,20 +0,0 @@
import { expect } from "chai"
import { currentPath, selectFiles, selectFilesState } from "./file.selector"
test("selects the files state", () => {
expect(selectFilesState({ files: "files state" } as any)).deep.eq(
"files state"
)
})
describe("when filePaths exists", () => {
test("selects the filePaths", () => {
expect(selectFiles({ files: { filePaths: [] } } as any)).deep.eq([])
})
})
describe("when currentPath exists", () => {
test("selects the should select currentFolder", () => {
expect(currentPath({ files: { currentFolder: "./" } } as any)).deep.eq("./")
})
})

View File

@@ -1,7 +0,0 @@
import RootState from "../../reducers/state"
export const selectFilesState = (state: RootState) => state.files
export const selectFiles = (state: RootState) =>
selectFilesState(state).filePaths
export const currentPath = (state: RootState) =>
selectFilesState(state).currentFolder

View File

@@ -1,61 +0,0 @@
import * as React from "react"
import { useEffect, useState } from "react"
import styled from "styled-components"
import FunctionComponent from "../../../types/function-component.interface"
const { remote } = require("electron")
const mainRef = remote.require("./main.js")
const fileUtils = mainRef.electronUtils.fileUtils
const basePath = require("electron").remote.app.getPath("documents")
const FilesHookWrapper = styled.div`
flex: 1;
`
const UlStyle = styled.ul`
padding: 0;
`
const LiStyle = styled.li`
padding-left: 16px;
content: "*";
padding-right: 8px;
`
const FilesHook: FunctionComponent = () => {
const [currentPath, setCurrentPath] = useState(`${basePath}`)
const [paths, setPaths] = useState([] as any[])
useEffect(() => {
fileUtils.listFiles(currentPath).then((result: any[]) => {
const structuredPaths = result.map(el => {
return {
type: fileUtils.checkType(el),
path: el,
}
})
console.log(structuredPaths)
setPaths(structuredPaths)
// setCurrentPath('.')
})
}, [currentPath])
const linkedPaths = paths.map((el, index) => {
const handleElementClick = () =>
setCurrentPath(`${currentPath}.\\${el.path}`)
return (
<LiStyle onClick={handleElementClick} key={index}>
{el.path}
</LiStyle>
)
})
return (
<FilesHookWrapper>
<UlStyle>{linkedPaths}</UlStyle>
</FilesHookWrapper>
)
}
export default FilesHook

View File

@@ -1,22 +0,0 @@
import * as React from "react"
import styled from "styled-components"
import Navigation from "../../../shared/components/navigation/navigation.component"
import FilesHook from "../../components/files-hook/files-hook.component"
const FilePageWrapper = styled.div`
display: flex;
flex-direction: column;
border: 1px #ccc dotted;
padding: 10px;
`
const FilesPageHook = () => {
return (
<FilePageWrapper>
<Navigation />
<FilesHook />
</FilePageWrapper>
)
}
export default FilesPageHook

View File

@@ -1,32 +0,0 @@
import * as React from "react"
import { render } from "react-dom"
import { AppContainer } from "react-hot-loader"
import RootContainer from "./containers/root.container"
import { rootEpic } from "./effects/root.effects"
const {
configureStore,
history,
epicMiddleware,
} = require("./store/configureStore")
const store = configureStore()
epicMiddleware.run(rootEpic)
render(
<AppContainer>
<RootContainer store={store} history={history} />
</AppContainer>,
document.getElementById("root")
)
if ((module as any).hot) {
;(module as any).hot.accept("./containers/root.container", () => {
const NextRoot = require("./containers/root.container").default
render(
<AppContainer>
<NextRoot store={store} history={history} />
</AppContainer>,
document.getElementById("root") as HTMLElement
)
})
}

View File

@@ -1,136 +0,0 @@
const {darwinWindow, windowsWindow} = require("./electron/window");
const {app, BrowserWindow, Menu} = require('electron');
const {autoUpdater} = require("electron-updater");
const log = require('electron-log');
log.transports.file.level = "debug";
autoUpdater.logger = log;
let menu;
let template;
let mainWindow = null;
if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support'); // eslint-disable-line
sourceMapSupport.install();
}
if (process.env.NODE_ENV === 'development') {
require('electron-debug')(); // eslint-disable-line global-require
const path = require('path'); // eslint-disable-line
const p = path.join(__dirname, '..', 'app', 'node_modules'); // eslint-disable-line
require('module').globalPaths.push(p); // eslint-disable-line
}
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
//`fsPromises.readdir`
//
// mainWindow.webContents.send('ping', value)
function sendStatusToWindow(text) {
log.info(text);
mainWindow.webContents.send('message', text);
}
const installExtensions = () => {
if (process.env.NODE_ENV === 'development') {
const installer = require('electron-devtools-installer'); // eslint-disable-line global-require
require('devtron').install();
const extensions = [
'REACT_DEVELOPER_TOOLS',
'REDUX_DEVTOOLS'
];
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
return Promise.all(extensions.map(name => installer.default(installer[name], forceDownload)));
}
return Promise.resolve([]);
};
app.on('ready', async () => {
await installExtensions();
// const appVersion = require('./package.json').version;
// log.info(`app.getVersion ${app.getVersion()}`);
// log.info(`package.json-require.version ${appVersion}`);
mainWindow = new BrowserWindow({
show: false,
width: 1024,
height: 728,
webPreferences: {
// Warning! https://github.com/electron/electron/issues/18139#issuecomment-489137050
// Leaving it for now as the current app requires access to the process.
nodeIntegration: true
}
});
mainWindow.loadURL(`file://${__dirname}/app.html`);
mainWindow.webContents.on('did-finish-load', async () => {
mainWindow.show();
mainWindow.focus();
await autoUpdater.checkForUpdatesAndNotify();
});
mainWindow.on('closed', () => {
mainWindow = null;
});
autoUpdater.on('checking-for-update', () => {
sendStatusToWindow('Checking for update...');
});
autoUpdater.on('update-available', (info) => {
sendStatusToWindow('Update available.');
});
autoUpdater.on('update-not-available', (info) => {
sendStatusToWindow('Update not available.');
});
autoUpdater.on('error', (err) => {
sendStatusToWindow('Error in auto-updater. ' + err);
});
autoUpdater.on('download-progress', (progressObj) => {
let log_message = "Download speed: " + progressObj.bytesPerSecond;
log_message = log_message + ' - Downloaded ' + progressObj.percent + '%';
log_message = log_message + ' (' + progressObj.transferred + "/" + progressObj.total + ')';
sendStatusToWindow(log_message);
});
autoUpdater.on('update-downloaded', (info) => {
sendStatusToWindow('Update downloaded');
});
if (process.env.NODE_ENV === 'development') {
mainWindow.openDevTools();
mainWindow.webContents.on('context-menu', (e, props) => {
const {x, y} = props;
Menu.buildFromTemplate([{
label: 'Inspect element',
click() {
mainWindow.inspectElement(x, y);
}
}]).popup(mainWindow);
});
}
if (process.platform === 'darwin') {
template = darwinWindow(app, mainWindow);
menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
} else {
template = windowsWindow(app, mainWindow);
menu = Menu.buildFromTemplate(template);
mainWindow.setMenu(menu)
}
});
exports.electronUtils = require('./utils/file.utils');

5
app/package-lock.json generated
View File

@@ -1,5 +0,0 @@
{
"name": "pure-desktop-app",
"version": "0.15.0",
"lockfileVersion": 1
}

View File

@@ -1,17 +0,0 @@
{
"name": "pure-desktop-app",
"productName": "Pure desktop app",
"version": "0.15.0",
"description": "Electron pure desktop",
"main": "./main.js",
"scripts": {
"postinstall": "npm rebuild --runtime=electron --target=1.6.6 --disturl=https://atom.io/download/atom-shell --build-from-source"
},
"license": "MIT",
"dependencies": {},
"author": {
"name": "Appnroll",
"email": "dota@appnroll.com",
"url": "https://github.com/Appnroll"
}
}

View File

@@ -1,13 +0,0 @@
import { connectRouter } from "connected-react-router"
import { History } from "history"
import { combineReducers } from "redux"
import { reducer as fileReducer } from "../files/reducers/files.reducer"
import RootState from "./state"
const createRootReducer = (history: History) =>
combineReducers<RootState>({
router: connectRouter(history),
files: fileReducer,
})
export default createRootReducer

View File

@@ -1,16 +0,0 @@
import * as React from "react"
import { Route, Switch } from "react-router"
import AppContainer from "./containers/app.container"
import FilesPage from "./files/pages/files/files.page"
import FilesPageHook from "./fileshook/pages/files-hook/files-hook.page"
import HomePage from "./home/pages/home/home.page"
export default () => (
<AppContainer>
<Switch>
<Route path="/filesHooks" component={FilesPageHook} />
<Route path="/files" component={FilesPage} />
<Route path="/" component={HomePage} />
</Switch>
</AppContainer>
)

View File

@@ -1,56 +0,0 @@
import { push, routerMiddleware } from "connected-react-router"
import { createHashHistory } from "history"
import { applyMiddleware, compose, createStore } from "redux"
import { createLogger } from "redux-logger"
import { createEpicMiddleware } from "redux-observable"
import thunk from "redux-thunk"
import * as filesAction from "../files/actions/files.actions"
import createRootReducer from "../reducers"
const epicMiddleware = createEpicMiddleware()
declare const window: Window & {
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?(a: any): void
}
declare const module: NodeModule & {
hot?: {
accept(...args: any[]): any
}
}
const actionCreators = Object.assign({}, filesAction, { push })
const logger = (createLogger as any)({
level: "info",
collapsed: true,
})
const history = createHashHistory() // must be hash, do not change
const composeEnhancers: typeof compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
// Options: http://zalmoxisus.github.io/redux-devtools-extension/API/Arguments.html
actionCreators,
}) as any)
: compose
const enhancer = composeEnhancers(
applyMiddleware(thunk, logger, routerMiddleware(history), epicMiddleware)
)
export = {
epicMiddleware,
history,
configureStore() {
const store = createStore(createRootReducer(history), {}, enhancer)
if (module.hot) {
module.hot.accept(
"../reducers",
() => store.replaceReducer(require("../reducers")) // eslint-disable-line global-require
)
}
return store
},
}

View File

@@ -1,16 +0,0 @@
import { createBrowserHistory } from "history"
import { routerMiddleware } from "react-router-redux"
import { applyMiddleware, createStore } from "redux"
import thunk from "redux-thunk"
import createRootReducer from "../reducers"
const history = createBrowserHistory()
const router = routerMiddleware(history)
const enhancer = applyMiddleware(thunk, router)
export = {
history,
configureStore() {
return createStore(createRootReducer(history), {}, enhancer)
},
}

View File

@@ -1,9 +0,0 @@
let configureStore: any
if (process.env.NODE_ENV === "production") {
configureStore = require("./configureStore.production")
} else {
configureStore = require("./configureStore.development")
}
export = configureStore

View File

@@ -1,52 +0,0 @@
const fsPromises = require("fs").promises
const fs = require("fs")
const FileType = {
file: "file",
directory: "directory",
unknown: "unknown",
}
const listFiles = async (path = "./") => {
return await fsPromises.readdir(path)
}
const isElementFile = async path => {
try {
const file = await fsPromises.lstat(path)
return file.isFile()
} catch (err) {
throw new Error("is element file error")
}
}
const isElementDirectory = async path => {
try {
const file = await fsPromises.lstat(path)
return file.isDirectory()
} catch (err) {
throw new Error("is element file error")
}
}
const checkType = path => {
const isFile = fs.lstatSync(path).isFile()
const isDirectory = fs.lstatSync(path).isDirectory()
if (isFile) {
return FileType.file
}
if (isDirectory) {
return FileType.directory
}
return FileType.unknown
}
exports.fileUtils = {
checkType,
listFiles,
isElementFile,
isElementDirectory,
}

View File

@@ -1,2 +0,0 @@
AWS_ACCESS_KEY_ID=AKIAJJ66DJJUOB5YDCTQ
AWS_SECRET_ACCESS_KEY=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

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1 +0,0 @@
export default 'test-file-stub';

View File

@@ -8,7 +8,7 @@ module.exports = {
".+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/__mocks__/file-mock.js",
},
rootDir: "../",
rootDir: "./",
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
testPathIgnorePatterns: ["node_modules", ".cache", "public", "cypress"],
globals: {

15688
package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,111 +1,99 @@
{
"name": "electron-pure-desktop-app",
"productName": "Pure desktop app",
"version": "1.0.0",
"description": "Electron pure desktop",
"main": "main.js",
"name": "pure-desktop-app",
"version": "0.0.1",
"description": "",
"main": "./dist/main.js",
"scripts": {
"test": "jest --config=./.jest/config.js",
"test-all": "npm run test && npm run build && npm run test-e2e",
"build-main": "cross-env NODE_ENV=production webpack --config webpack.main.prod.config.js",
"build-renderer": "cross-env NODE_ENV=production webpack --config webpack.renderer.prod.config.js",
"build": "npm run build-main && npm run build-renderer",
"start-renderer-dev": "webpack-dev-server --config webpack.renderer.dev.config.js",
"start-main-dev": "webpack --config webpack.main.config.js && electron ./dist/main.js",
"start-dev": "cross-env START_HOT=1 npm run start-renderer-dev",
"prestart": "npm run build",
"start": "electron .",
"lint": "tslint '{src,test,mocks}/**/*.{ts,tsx}' --project ./tsconfig.json",
"test": "jest",
"test-all": "npm run test && npm run build",
"test:watch": "tsc && cross-env NODE_ENV=test cross-env TEST_DIALECT=sqlite mocha -w --recursive --compilers ts:ts-node/register --bail \"test/**/*.spec.ts\"",
"test-watch": "npm test -- --watch",
"test-e2e": "cross-env NODE_ENV=test node --trace-warnings ./test/runTests.js e2e",
"lint": "tslint --project .",
"type-check": "tsc --noEmit",
"hot-server": "cross-env NODE_ENV=development node --max_old_space_size=2096 server.js",
"build-main": "cross-env NODE_ENV=production node ./node_modules/webpack/bin/webpack --config webpack.config.electron.js --progress --profile --colors",
"build-renderer": "cross-env NODE_ENV=production node ./node_modules/webpack/bin/webpack --config webpack.config.production.js --progress --profile --colors",
"build": "npm run build-main && npm run build-renderer",
"start": "cross-env NODE_ENV=production electron ./app/",
"start-hot": "cross-env HOT=1 NODE_ENV=development electron ./app/main.development",
"postinstall": "npm run build",
"develop": "npm run hot-server -- --start-hot",
"format": "prettier --write app/**/*.{js,jsx,ts,tsx}",
"package": "npm run build && build --publish never",
"package-win": "npm run build && build --win --x64",
"package-linux": "npm run build && build --linux",
"package-all": "npm run build && build -mwl",
"cleanup": "mop -v",
"pack": "electron-builder --dir",
"dist": "electron-builder",
"publish_s3": "npm run build && electron-builder --publish always",
"pretest:e2e": "npm run build",
"test:e2e": "jest '(\\/test\\/e2e/).*'",
"pack": "npm run build && electron-builder --dir",
"dist": "npm run build && electron-builder",
"postinstall": "electron-builder install-app-deps",
"beforecommit": "lint-staged && npm test && npm run check:translations",
"check:translations": "ts-node -r esm ./scripts/translationCheck",
"generate:translations": "ts-node -r esm ./scripts/translationRunner.js",
"storybook:serve": "start-storybook -p 6006",
"storybook:build": "build-storybook"
},
"pre-commit": "beforecommit",
"lint-staged": {
"{src,test,mocks}/**/*.{js,ts,tsx,json,css,scss,md}": [
"tslint --fix",
"git add"
]
},
"jest": {
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testRegex": "(/test/.+\\.spec)\\.tsx?$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"json",
"node"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/mocks/fileMock.js",
"\\.(s?css|sass)$": "<rootDir>/mocks/styleMock.js"
}
},
"build": {
"productName": "Pure-desktop-app",
"appId": "com.mudita.pure",
"dmg": {
"contents": [
{
"x": 410,
"y": 150,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 150,
"type": "file"
}
]
"productName": "PureDesktopApp",
"appId": "mudita.pure.desktopApp",
"mac": {
"category": "your.app.category.type"
},
"directories": {
"output": "release"
},
"files": [
"dist/",
"node_modules/",
"app.html",
"main.js",
"main.js.map",
"package.json"
],
"directories": {
"buildResources": "resources",
"output": "release"
},
"publish": {
"provider": "s3",
"bucket": "pure-app-develop",
"path": "/release",
"acl": "public-read"
"linux": {
"target": "deb"
},
"win": {
"target": "nsis"
},
"linux": {
"target": [
"deb",
"AppImage"
]
}
},
"bin": {
"electron": "./node_modules/.bin/electron"
},
"repository": {
"type": "git",
"url": "git+https://github.com/irath96/electron-react-typescript-boilerplate.git"
"url": "https://github.com/Appnroll/pure-desktop-app"
},
"author": {
"name": "Appnroll",
"email": "dota@appnroll.com",
"url": "https://github.com/Appnroll"
"name": "Mudita",
"email": "contact@mudita.com"
},
"license": "MIT",
"license": "SEE LICENSE",
"bugs": {
"url": "https://github.com/Appnroll/pure-desktop-app/issues"
},
"keywords": [
"electron",
"boilerplate",
"react",
"react-router",
"flux",
"webpack",
"react-hot"
],
"homepage": "https://github.com/irath96/electron-react-typescript-boilerplate#readme",
"homepage": "https://github.com/Appnroll/pure-desktop-app",
"devDependencies": {
"@babel/core": "^7.7.2",
"@babel/plugin-proposal-class-properties": "^7.7.0",
"@babel/polyfill": "^7.7.0",
"@babel/preset-env": "^7.7.1",
"@babel/preset-react": "^7.7.0",
"@babel/preset-typescript": "^7.7.2",
"@hot-loader/react-dom": "^16.11.0",
"@storybook/addon-actions": "^5.2.5",
"@storybook/addon-knobs": "^5.2.5",
"@storybook/addon-links": "^5.2.5",
@@ -114,66 +102,92 @@
"@testing-library/jest-dom": "^4.2.3",
"@testing-library/react": "^9.3.2",
"@types/chai": "^4.2.4",
"@types/electron-devtools-installer": "^2.2.0",
"@types/history": "^4.7.3",
"@types/jest": "^24.0.22",
"@types/jest": "^24.0.13",
"@types/node": "^12.12.6",
"@types/react": "16.9.11",
"@types/react-dom": "16.9.4",
"@types/react-hot-loader": "4.1.0",
"@types/react-redux": "7.1.5",
"@types/react": "^16.8.18",
"@types/react-dom": "^16.8.4",
"@types/react-hot-loader": "^4.1.1",
"@types/react-redux": "^7.0.9",
"@types/react-router": "^5.1.2",
"@types/react-router-dom": "^5.1.2",
"@types/react-router-redux": "^5.0.18",
"@types/react-test-renderer": "^16.9.1",
"@types/redux-logger": "^3.0.7",
"@types/redux-mock-store": "^1.0.1",
"@types/sinon": "^7.5.0",
"@types/webdriverio": "^5.0.0",
"@types/webpack-env": "^1.14.1",
"asar": "^2.0.1",
"babel-core": "7.0.0-bridge.0",
"babel-loader": "^8.0.6",
"babel-plugin-styled-components": "^1.10.6",
"babel-runtime": "^6.26.0",
"boiler-room-custodian": "^0.6.2",
"chalk": "^3.0.0",
"circular-dependency-plugin": "^5.2.0",
"concurrently": "^5.0.0",
"cross-env": "^6.0.3",
"css-loader": "^3.2.0",
"devtron": "^1.4.0",
"electron": "^7.1.0",
"electron-builder": "22.1.0",
"electron": "^7.1.1",
"electron-builder": "^21.2.0",
"electron-builder-http": "^19.27.5",
"electron-devtools-installer": "^2.2.4",
"electron-rebuild": "^1.8.6",
"express": "^4.17.1",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^4.2.0",
"html-webpack-plugin": "3.2.0",
"fork-ts-checker-webpack-plugin": "^3.1.0",
"fs": "0.0.1-security",
"glob": "^7.1.6",
"html-webpack-plugin": "^3.2.0",
"identity-obj-proxy": "^3.0.0",
"jest": "24.9.0",
"image-webpack-loader": "^6.0.0",
"jest": "^24.8.0",
"jest-styled-components": "^6.3.3",
"json-loader": "^0.5.7",
"lint-staged": "^9.4.3",
"mini-css-extract-plugin": "0.8.0",
"mocha": "^6.2.2",
"prettier": "^1.18.2",
"react-hot-loader": "^4.12.16",
"react-test-renderer": "^16.11.0",
"node-sass": "^4.13.0",
"pre-commit": "^1.2.2",
"prettier": "^1.17.1",
"react-hot-loader": "^4.8.8",
"react-intl": "^3.6.0",
"react-intl-translations-manager": "^5.0.3",
"react-test-renderer": "^16.8.6",
"redux-devtools-extension": "^2.13.5",
"redux-logger": "^3.0.6",
"redux-mock-store": "^1.5.3",
"sass-loader": "^8.0.0",
"sinon": "^7.5.0",
"source-map-loader": "^0.2.4",
"spectron": "^9.0.0",
"style-loader": "^1.0.0",
"ts-jest": "^24.1.0",
"ts-jest": "^24.0.2",
"ts-loader": "6.2.1",
"ts-node": "^8.4.1",
"tslint": "^5.20.1",
"ts-node": "^8.5.2",
"tslint": "^5.16.0",
"tslint-config-airbnb": "^5.11.2",
"tslint-config-prettier": "^1.18.0",
"tslint-eslint-rules": "^5.4.0",
"tslint-plugin-prettier": "^2.0.1",
"typescript": "3.7.2",
"tslint-react": "^4.0.0",
"typescript": "^3.4.5",
"url-loader": "2.2.0",
"webpack": "4.41.2",
"webpack-cli": "^3.3.10",
"webpack": "^4.32.2",
"webpack-cli": "^3.3.2",
"webpack-dev-middleware": "3.7.2",
"webpack-dev-server": "^3.9.0",
"webpack-hot-middleware": "2.25.0",
"webpack-merge": "4.2.2"
"webpack-merge": "^4.2.1"
},
"dependencies": {
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.0.3",
"redux": "^4.0.1",
"@storybook/addon-info": "^5.2.5",
"@storybook/cli": "^5.2.5",
"@types/styled-components": "^4.1.21",
@@ -185,16 +199,10 @@
"electron-publisher-s3": "^20.17.2",
"electron-updater": "^4.2.0",
"font-awesome": "^4.7.0",
"fork-ts-checker-webpack-plugin": "^3.0.1",
"history": "^4.10.1",
"react": "16.11.0",
"react-docgen-typescript-webpack-plugin": "^1.1.0",
"react-dom": "16.11.0",
"react-redux": "^7.1.3",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"react-router-redux": "^5.0.0-alpha.6",
"redux": "^4.0.4",
"redux-observable": "^1.2.0",
"redux-thunk": "^2.3.0",
"rxjs": "^6.5.3",
@@ -205,9 +213,5 @@
"tslint-react": "^4.1.0",
"update-electron-app": "^1.5.0",
"usb": "^1.6.1"
},
"devEngines": {
"node": ">=12.9",
"npm": ">=6.10"
}
}

View File

Binary file not shown.

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 954 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

48
scripts/translationCheck.js Executable file
View File

@@ -0,0 +1,48 @@
const { sync: globSync } = require('glob');
const { readFileSync } = require('fs');
const chalk = require('chalk');
const stringToHash = require('../src/renderer/utils/stringToHash.ts').default;
const { LANGUAGE } = require('../src/renderer/constants/languages.ts');
function checkTranslations(dir) {
let files;
if (LANGUAGE.available.length > 1) {
files = globSync(`${dir}{${LANGUAGE.available.join(',')}}.json`);
} else {
files = globSync(`${dir}${LANGUAGE.available[0]}.json`);
}
if (!files.length || files.length !== LANGUAGE.available.length) {
console.log(
chalk.red(`${dir} directory probably does not exist or is empty or not all files present`),
);
process.exitCode = 1;
return;
}
const keys = files
.map(filename => JSON.parse(readFileSync(filename, 'utf8')))
.map(data => Object.keys(data).sort());
const hashes = keys.map(data => stringToHash(data.join(' ')));
const equal = hashes.every((str, idx, arr) => str === arr[0]);
if (!equal) {
console.log(chalk.red('Number of keys in translation files is not equal'));
keys.forEach((data, idx) => {
console.log(
chalk.blue(`${dir}${files[idx]}.json`),
chalk.gray('keys:'),
chalk.yellow(data.length),
chalk.gray('hash:'),
chalk.yellow(hashes[idx]),
);
});
process.exitCode = 2;
} else {
console.log(chalk.green('Number of keys in translation files is equal: '));
files.forEach(file => console.log(chalk.gray(` ${file}`)));
}
}
checkTranslations('./src/renderer/locales/main/');

37
scripts/translationRunner.js Executable file
View File

@@ -0,0 +1,37 @@
const chalk = require('chalk');
const manageTranslations = require('react-intl-translations-manager').default;
const { sync: globSync } = require('glob');
const { LANGUAGE } = require('../src/renderer/constants/languages.ts');
const provideExtractedMessagesCustom = require('./provideExtractedMessagesCustom');
const jsonOptions = { space: 2, trailingNewline: true };
const messagesDirectory = './tmp/extractedMessages';
const files = globSync('./tmp/extractedMessages/**/*.json');
if (!files.length) {
console.log(
chalk.red('./tmp directory probably does not exist or is empty'),
chalk.yellow('Change some files and restart build (`npm run start`)'),
);
return;
}
const commonOptions = {
messagesDirectory,
languages: LANGUAGE.available,
jsonOptions,
};
manageTranslations({
...commonOptions,
translationsDirectory: './src/locales/main',
overrideCoreMethods: {
beforeReporting() {
console.log(chalk.cyan('--------------- ./src/locales/main ---------------\n'));
},
provideExtractedMessages: () => provideExtractedMessagesCustom(messagesDirectory),
},
});

View File

@@ -1,51 +0,0 @@
/**
* Setup and run the development server for Hot-Module-Replacement
* https://webpack.github.io/docs/hot-module-replacement-with-webpack.html
*/
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const { spawn } = require('child_process');
const config = require('./webpack.config.development');
const argv = require('minimist')(process.argv.slice(2));
const app = express();
const compiler = webpack(config);
const PORT = process.env.PORT || 3000;
const wdm = webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
stats: {
colors: true
}
});
app.use(wdm);
app.use(webpackHotMiddleware(compiler));
const server = app.listen(PORT, 'localhost', serverError => {
if (serverError) {
return console.error(serverError);
}
if (argv['start-hot']) {
spawn('npm', ['run', 'start-hot'], { shell: true, env: process.env, stdio: 'inherit' })
.on('close', code => process.exit(code))
.on('error', spawnError => console.error(spawnError));
}
console.log(`Listening at http://localhost:${PORT}`);
});
process.on('SIGTERM', () => {
console.log('Stopping dev server');
wdm.close();
server.close(() => {
process.exit(0);
});
});

View File

@@ -1,65 +0,0 @@
// Note: this file is the configuration file *only* for
// use by the boiler-room-custodian utility. the point
// of the boiler-room-custodian is to clean sample code
// from the boilerplate from initial state so that you
// can start custom development on a "blank project"
//
// For more information or to report issues please go
// to https://github.com/tstringer/boiler-room-custodian
//
// This file should remain unmodified by end users and
// should only be invoked by running `npm run cleanup`
module.exports = {
// remove the following files as they are mostly
// related to the sample counter page and functionality
remove: [
{ file: 'app/actions/counter.ts' },
{ file: 'app/components/Counter.scss' },
{ file: 'app/components/Counter.tsx' },
{ file: 'app/containers/CounterPage.tsx' },
{ file: 'app/reducers/counter.ts' },
{ file: 'test/actions/counter.spec.ts' },
{ file: 'test/components/Counter.spec.tsx' },
{ file: 'test/containers/CounterPage.spec.tsx' },
{ file: 'test/reducers/counter.spec.ts' },
{ file: 'erb-logo.png' }
],
// clean the following files by either clearing them
// (by specifying {clear: true}) or by removing lines
// that match a regex pattern
clean: [
{
file: 'app/reducers/index.ts',
pattern: /counter/
},
{
file: 'app/store/configureStore.development.ts',
pattern: /counterActions/
},
{
file: 'app/routes.tsx',
pattern: /CounterPage/
},
{
file: 'test/e2e.ts',
clear: true
},
{
file: 'README.md',
clear: true
},
{
file: 'app/components/Home.tsx',
pattern: /(h2|Link)/
}
],
// add the following files to the project, mostly
// related to .gitkeep for version control
add: [
{ file: 'app/actions/.gitkeep' },
{ file: 'test/actions/.gitkeep' },
{ file: 'test/components/.gitkeep' },
{ file: 'test/containers/.gitkeep' },
{ file: 'test/reducers/.gitkeep' }
]
};

67
src/main/main.ts Normal file
View File

@@ -0,0 +1,67 @@
import { app, BrowserWindow } from "electron"
import * as path from "path"
import * as url from "url"
let win: BrowserWindow | null
const installExtensions = async () => {
const installer = require("electron-devtools-installer")
const forceDownload = !!process.env.UPGRADE_EXTENSIONS
const extensions = ["REACT_DEVELOPER_TOOLS", "REDUX_DEVTOOLS"]
return Promise.all(
extensions.map(name => installer.default(installer[name], forceDownload))
).catch(console.log)
}
const createWindow = async () => {
if (process.env.NODE_ENV !== "production") {
await installExtensions()
}
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
})
if (process.env.NODE_ENV !== "production") {
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = "1"
win.loadURL(`http://localhost:2003`)
} else {
win.loadURL(
url.format({
pathname: path.join(__dirname, "index.html"),
protocol: "file:",
slashes: true,
})
)
}
if (process.env.NODE_ENV !== "production") {
// Open DevTools, see https://github.com/electron/electron/issues/12438 for why we wait for dom-ready
win.webContents.once("dom-ready", () => {
win!.webContents.openDevTools()
})
}
win.on("closed", () => {
win = null
})
}
app.on("ready", createWindow)
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit()
}
})
app.on("activate", () => {
if (win === null) {
createWindow()
}
})

18
src/renderer/app.tsx Normal file
View File

@@ -0,0 +1,18 @@
import * as React from "react"
import * as ReactDOM from "react-dom"
import { AppContainer } from "react-hot-loader"
import history from "Renderer/routes/history"
import store from "Renderer/store"
import RootWrapper from "Renderer/wrappers/root.wrapper"
// Create main element
const mainElement = document.createElement("div")
document.body.appendChild(mainElement)
ReactDOM.render(
<AppContainer>
<RootWrapper store={store} history={history} />
</AppContainer>,
mainElement
)

View File

@@ -1,6 +1,7 @@
import * as React from "react"
import styled from "styled-components"
import FunctionComponent from "../../../types/function-component.interface"
import FunctionComponent from "Renderer/types/function-component.interface"
const HeaderWrapper = styled.div`
flex: 1;
@@ -10,7 +11,7 @@ const HeaderWrapper = styled.div`
`
const Header: FunctionComponent = () => {
return <HeaderWrapper> Header </HeaderWrapper>
return <HeaderWrapper>Header</HeaderWrapper>
}
export default Header

View File

View File

@@ -0,0 +1,5 @@
export const LANGUAGE = {
default: "en-US",
defaultShort: "en",
available: ["en-US"],
}

View File

@@ -0,0 +1,5 @@
export const URL_MAIN = {
root: "/",
files: "/files",
filesHooks: "/filesHooks",
}

View File

View File

@@ -0,0 +1,3 @@
{
"test": "test"
}

View File

@@ -1,7 +1,7 @@
import * as React from "react"
import { textColor } from "Renderer/styles/theming/theme-getters"
import FunctionComponent from "Renderer/types/function-component.interface"
import styled from "styled-components"
import { textColor } from "../../../theming/theme-getters"
import FunctionComponent from "../../../types/function-component.interface"
const HomeWrapper = styled.div`
color: ${textColor("primary")}

View File

@@ -1,9 +1,10 @@
import * as React from "react"
import styled from "styled-components"
import Header from "../../../shared/components/header/header.component"
import Navigation from "../../../shared/components/navigation/navigation.component"
import FunctionComponent from "../../../types/function-component.interface"
import Home from "../../components/home/home.component"
import Header from "Renderer/components/header/header.component"
import Navigation from "Renderer/components/navigation/navigation.component"
import FunctionComponent from "Renderer/types/function-component.interface"
import Home from "./components/home/home.component"
const HomePageWrapper = styled.div`
display: flex;

View File

@@ -0,0 +1,12 @@
import { connectRouter } from "connected-react-router"
import { History } from "history"
import { combineReducers } from "redux"
import history from "Renderer/routes/history"
import RootState from "./state"
const createRootReducer = (historyState: History) =>
combineReducers<RootState>({
router: connectRouter(historyState),
})
export default createRootReducer(history)

View File

@@ -1,7 +1,5 @@
import { RouterState } from "connected-react-router"
import { State as FileState } from "../files/reducers/files.reducer"
export default interface State {
router: RouterState
files: FileState
}

View File

@@ -0,0 +1,15 @@
import * as React from "react"
import { Route, Switch } from "react-router"
import HomePage from "Renderer/modules/home/home.page"
import AppWrapper from "Renderer/wrappers/app.wrapper"
import { URL_MAIN } from "Renderer/constants/urls"
export default () => (
<AppWrapper>
<Switch>
<Route path={URL_MAIN.root} component={HomePage} />
</Switch>
</AppWrapper>
)

View File

@@ -0,0 +1,3 @@
import { createHashHistory } from "history"
export default createHashHistory()

View File

@@ -0,0 +1,21 @@
import { applyMiddleware, createStore, Store } from "redux"
import { composeWithDevTools } from "redux-devtools-extension"
import rootReducer from "Renderer/reducers"
import RootState from "Renderer/reducers/state"
const index = (initialState?: RootState): Store<RootState | undefined> => {
const middlewares: any[] = []
const enhancer = composeWithDevTools(applyMiddleware(...middlewares))
return createStore(rootReducer, initialState, enhancer)
}
const store = index()
if (typeof module.hot !== "undefined") {
module.hot.accept("../reducers", () =>
store.replaceReducer(require("../reducers").rootReducer)
)
}
export default store

View File

@@ -1,5 +1,5 @@
import { createGlobalStyle } from "styled-components"
import { Theme } from "./theme"
import { Theme } from "./theming/theme"
const GlobalStyle = createGlobalStyle<{ theme: Theme }>`
html, body {

View File

@@ -0,0 +1,31 @@
/* tslint:disable no-bitwise prettier */
/**
* Converts string to numeric hash
* @param {string} str - string to be converted
* @returns {number}
*
* Please note:
* This is a JS implementation of Java's String.hashCode() method, converted to function.
* It looks utterly ugly but it's short and it gets the job done.
* Reference: https://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
*/
const stringToHash = (str: string) => {
let hash = 0
const strLength = str.length
if (strLength === 0) {
return hash
}
for (let i = 0; i < strLength; i++) {
const char = str.charCodeAt(i)
hash = ((hash << 5) - hash) + char;
hash &= hash; // convert to 32bit integer
}
return hash;
};
export default stringToHash;

View File

@@ -0,0 +1,12 @@
import * as React from "react"
import styled from "styled-components"
import FunctionComponent from "Renderer/types/function-component.interface"
const SAppWrapper = styled.div``
const AppWrapper: FunctionComponent = ({ children }) => {
return <SAppWrapper>{children}</SAppWrapper>
}
export default AppWrapper

View File

@@ -4,17 +4,18 @@ import * as React from "react"
import { Provider } from "react-redux"
import { ThemeProvider } from "styled-components"
import { Normalize } from "styled-normalize"
import Routes from "../routes"
import GlobalStyle from "../theming/global-style.component"
import theme from "../theming/theme"
import FunctionComponent from "../types/function-component.interface"
import BaseRoutes from "Renderer/routes/base-routes"
import GlobalStyle from "Renderer/styles/global-style.component"
import theme from "Renderer/styles/theming/theme"
import FunctionComponent from "Renderer/types/function-component.interface"
interface Props {
store: any
history: History
}
const RootContainer: FunctionComponent<Props> = ({ store, history }) => {
const RootWrapper: FunctionComponent<Props> = ({ store, history }) => {
return (
<ThemeProvider theme={theme}>
<>
@@ -22,7 +23,7 @@ const RootContainer: FunctionComponent<Props> = ({ store, history }) => {
<GlobalStyle />
<Provider store={store}>
<ConnectedRouter history={history}>
<Routes />
<BaseRoutes />
</ConnectedRouter>
</Provider>
</>
@@ -30,4 +31,4 @@ const RootContainer: FunctionComponent<Props> = ({ store, history }) => {
)
}
export default RootContainer
export default RootWrapper

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -1,30 +1,120 @@
{
"compilerOptions": {
/***** Basic Options ******/
/* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
"target": "es5",
"moduleResolution": "node",
/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"module": "commonjs",
"jsx": "react",
"lib": ["dom", "es6", "dom.iterable", "scripthost", "es5", "es7", "es2017"],
"types": ["jest", "node"],
/* Specify library files to be included in the compilation: */
"lib": [
"dom",
"es6",
"dom.iterable",
"scripthost",
"es5",
"es7",
"es2017"
],
/* Allow javascript files to be compiled. */
"allowJs": true,
/* Report errors in .js files. */
// "checkJs": true,
/* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"jsx": "react",
/* Generates corresponding '.d.ts' file. */
// "declaration": true,
/* Generates corresponding '.map' file. */
"sourceMap": true,
/* Concatenate and emit output to single file. */
// "outFile": "./",
/* Redirect output structure to the directory. */
"outDir": "./dist",
/* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "rootDir": "./",
/* Do not emit comments to output. */
// "removeComments": true,
/* Do not emit outputs. */
// "noEmit": true,
/* Import emit helpers from 'tslib'. */
// "importHelpers": true,
/* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "downlevelIteration": true,
/* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
// "isolatedModules": true,
/***** Strict Type-Checking Options ******/
/* Enable all strict type-checking options. */
"strict": true,
"alwaysStrict": true,
"strictNullChecks": true,
/* Raise error on expressions and declarations with an implied 'any' type. */
"noImplicitAny": true,
"noImplicitReturns": true,
/* Enable strict null checks. */
"strictNullChecks": true,
/* Enable strict checking of function types. */
// "strictFunctionTypes": true,
/* Raise error on 'this' expressions with an implied 'any' type. */
"noImplicitThis": true,
/* Parse in strict mode and emit "use strict" for each source file. */
"alwaysStrict": true,
/***** Additional Checks *****/
/* Report errors on unused locals. */
"noUnusedLocals": true,
"skipLibCheck": true,
/* Report errors on unused parameters. */
// "noUnusedParameters": true,
/* Report error when not all code paths in function return a value. */
"noImplicitReturns": true,
/* Report errors for fallthrough cases in switch statement. */
// "noFallthroughCasesInSwitch": true,
/***** Module Resolution Options *****/
/* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"moduleResolution": "node",
/* Base directory to resolve non-absolute module names. */
"baseUrl": "./",
/* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
"paths": {
"App/*": ["src/*"],
"Renderer/*": ["src/renderer/*"],
"Cypress/*": ["cypress/*"],
"Storybook/*": [".storybook/*"]
},
/* List of root folders whose combined content represents the structure of the project at runtime. */
// "rootDirs": [],
/* List of folders to include type definitions from. */
// "typeRoots": [],
/* Type declaration files to be included in compilation. */
"types": ["jest", "node"],
/* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
// "allowSyntheticDefaultImports": true,
/* Do not resolve the real path of symlinks. */
// "preserveSymlinks": true,
/***** Source Map Options *****/
/* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "sourceRoot": "./",
/* Specify the location where debugger should locate map files instead of generated locations. */
// "mapRoot": "./",
/* Emit a single file with source maps instead of having a separate file. */
// "inlineSourceMap": true,
/* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
// "inlineSources": true,
/***** Experimental Options *****/
/* Enables experimental support for ES7 decorators. */
"experimentalDecorators": true,
/* Enables experimental support for emitting type metadata for decorators. */
"emitDecoratorMetadata": true,
"sourceMap": true,
"outDir": "dist"
"skipLibCheck": true
},
"files": ["app/index.tsx"],
"include": [
"app/**/*.ts",
"app/**/*.tsx"
"./src",
"./test",
"./mocks"
],
"exclude": ["dist", "node_modules"]
}

View File

@@ -1,20 +1,20 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended",
"tslint-react",
"tslint-eslint-rules",
"tslint-config-prettier"
],
"jsRules": {},
"rules": {
"semicolon": false,
"interface-name": false,
"no-console": false,
"object-literal-sort-keys": false,
"jsx-boolean-value": false,
"no-var-requires": false,
"prettier": true
},
"rulesDirectory": ["tslint-plugin-prettier"]
"defaultSeverity": "error",
"extends": [
"tslint:recommended",
"tslint-react",
"tslint-eslint-rules",
"tslint-config-prettier"
],
"jsRules": {},
"rules": {
"semicolon": false,
"interface-name": false,
"no-console": false,
"object-literal-sort-keys": false,
"jsx-boolean-value": false,
"no-var-requires": false,
"prettier": true
},
"rulesDirectory": ["tslint-plugin-prettier"]
}

View File

@@ -1,25 +1,19 @@
/**
* Build config for electron 'Renderer Process' file
*/
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const merge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const baseConfig = require('./webpack.config.base');
module.exports = merge(baseConfig, {
devtool: 'cheap-module-source-map',
const { resolve } = require('./webpack/resolve');
const plugins = require('./webpack/plugins')();
entry: [
'./app/index'
],
output: {
path: path.join(__dirname, 'app/dist'),
publicPath: '../dist/'
},
module.exports = {
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
node: {
__dirname: false,
__filename: false
},
devtool: 'source-map',
module: {
rules: [
@@ -77,28 +71,9 @@ module.exports = merge(baseConfig, {
test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
use: 'url-loader',
}
]
],
},
plugins: [
// https://webpack.github.io/docs/list-of-plugins.html#occurrenceorderplugin
// https://github.com/webpack/webpack/issues/864
new webpack.optimize.OccurrenceOrderPlugin(),
// NODE_ENV should be production so that modules do not perform certain development checks
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new ExtractTextPlugin('style.css'),
new HtmlWebpackPlugin({
filename: '../app.html',
template: 'app/app.html',
inject: false
})
],
// https://github.com/chentsulin/webpack-target-electron-renderer#how-this-module-works
target: 'electron-renderer'
});
resolve,
plugins,
};

View File

@@ -1,42 +0,0 @@
/**
* Base webpack config used across other specific configs
*/
const path = require('path');
const {
dependencies: externals
} = require('./app/package.json');
module.exports = {
module: {
rules: [{
test: /\.tsx?$/,
loaders: ['react-hot-loader/webpack', 'ts-loader'],
exclude: /node_modules/
}, {
test: /\.json$/,
loader: 'json-loader'
}]
},
output: {
path: path.join(__dirname, 'app'),
filename: 'bundle.js',
// https://github.com/webpack/webpack/issues/1114
libraryTarget: 'commonjs2'
},
// https://webpack.github.io/docs/configuration.html#resolve
resolve: {
extensions: ['.js', '.ts', '.tsx', '.json'],
modules: [
path.join(__dirname, 'app'),
'node_modules',
]
},
plugins: [],
externals: Object.keys(externals || {})
};

View File

@@ -1,110 +0,0 @@
/* eslint-disable max-len */
/**
* Build config for development process that uses Hot-Module-Replacement
* https://webpack.github.io/docs/hot-module-replacement-with-webpack.html
*/
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.config.base');
const port = process.env.PORT || 3000;
module.exports = merge(baseConfig, {
devtool: 'inline-source-map',
mode: 'development',
entry: [
'react-hot-loader/patch',
`webpack-hot-middleware/client?path=http://localhost:${port}/__webpack_hmr&reload=true`,
'./app/index'
],
output: {
publicPath: `http://localhost:${port}/dist/`
},
module: {
// preLoaders: [
// {
// test: /\.js$/,
// loader: 'eslint-loader',
// exclude: /node_modules/
// }
// ],
rules: [
// WOFF Font
{
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff',
}
},
},
// WOFF2 Font
{
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff',
}
}
},
// TTF Font
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream'
}
}
},
// EOT Font
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: 'file-loader',
},
// SVG Font
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml',
}
}
},
// Common Image Formats
{
test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
use: 'url-loader',
}
]
},
plugins: [
// https://webpack.github.io/docs/hot-module-replacement-with-webpack.html
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// NODE_ENV should be production so that modules do not perform certain development checks
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
}),
new webpack.LoaderOptionsPlugin({
debug: true
}),
],
// https://github.com/chentsulin/webpack-target-electron-renderer#how-this-module-works
target: 'electron-renderer'
});

View File

@@ -1,50 +0,0 @@
/**
* Build config for electron 'Main Process' file
*/
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.config.base');
module.exports = merge(baseConfig, {
devtool: 'source-map',
mode: 'development',
entry: ['./app/main.development'],
// 'main.js' in root
output: {
path: __dirname,
filename: './app/main.js'
},
plugins: [
// Add source map support for stack traces in node
// https://github.com/evanw/node-source-map-support
// new webpack.BannerPlugin(
// 'require("source-map-support").install();',
// { raw: true, entryOnly: false }
// ),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
],
/**
* Set target to Electron specific node.js env.
* https://github.com/chentsulin/webpack-target-electron-renderer#how-this-module-works
*/
target: 'electron-main',
/**
* Disables webpack processing of __dirname and __filename.
* If you run the bundle in node.js it falls back to these values of node.js.
* https://github.com/webpack/webpack/issues/2010
*/
node: {
__dirname: false,
__filename: false
},
});

Some files were not shown because too many files have changed in this diff Show More