init
39
HOW_TO.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
###*First check it exists a version of your library compatible with the version of Angular defined in package.json.*
|
||||||
|
|
||||||
|
### How to install ng-bootstrap
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
ng add @ng-bootstrap/ng-bootstrap
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to install ngx-bootstrap
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
ng add ngx-bootstrap
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to install Angular Material
|
||||||
|
|
||||||
|
Add Angular Material using `ng add` command:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
ng add @angular/material
|
||||||
|
```
|
||||||
|
You will get the following questions:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
? Choose a prebuilt theme name, or "custom" for a custom theme: *Choose any theme you like here*
|
||||||
|
? Set up global Angular Material typography styles? *Yes*
|
||||||
|
? Set up browser animations for Angular Material? *Yes*
|
||||||
|
```
|
||||||
|
Angular Material will start installing, but you will get the following error after installation:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
Your project is not using the default builders for "build". The Angular Material schematics cannot add a theme to the workspace configuration if the builder has been changed.
|
||||||
|
```
|
||||||
|
*No need to Panic!* Just add your desired theme in style.scss:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
@import '@angular/material/prebuilt-themes/indigo-pink.css'
|
||||||
|
```
|
||||||
|
Angular Material Library is now installed in your project.
|
1
_config.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
theme: jekyll-theme-architect
|
188
angular.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"cli": {
|
||||||
|
"defaultCollection": "@angular-eslint/schematics",
|
||||||
|
"analytics": false
|
||||||
|
},
|
||||||
|
"version": 1,
|
||||||
|
"newProjectRoot": "projects",
|
||||||
|
"projects": {
|
||||||
|
"angular-electron": {
|
||||||
|
"root": "",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"projectType": "application",
|
||||||
|
"schematics": {
|
||||||
|
"@schematics/angular:application": {
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"@schematics/angular:component": {
|
||||||
|
"style": "scss"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prefix": "app",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-builders/custom-webpack:browser",
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist",
|
||||||
|
"index": "src/index.html",
|
||||||
|
"main": "src/main.ts",
|
||||||
|
"tsConfig": "src/tsconfig.app.json",
|
||||||
|
"polyfills": "src/polyfills.ts",
|
||||||
|
"inlineStyleLanguage": "scss",
|
||||||
|
"assets": [
|
||||||
|
"src/favicon.ico",
|
||||||
|
"src/assets"
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"src/styles.scss"
|
||||||
|
],
|
||||||
|
"scripts": [],
|
||||||
|
"customWebpackConfig": {
|
||||||
|
"path": "./angular.webpack.js",
|
||||||
|
"replaceDuplicatePlugins": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"dev": {
|
||||||
|
"optimization": false,
|
||||||
|
"outputHashing": "none",
|
||||||
|
"sourceMap": true,
|
||||||
|
"namedChunks": false,
|
||||||
|
"aot": false,
|
||||||
|
"extractLicenses": true,
|
||||||
|
"vendorChunk": false,
|
||||||
|
"buildOptimizer": false,
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "src/environments/environment.ts",
|
||||||
|
"with": "src/environments/environment.dev.ts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"optimization": true,
|
||||||
|
"outputHashing": "all",
|
||||||
|
"sourceMap": false,
|
||||||
|
"namedChunks": false,
|
||||||
|
"aot": true,
|
||||||
|
"extractLicenses": true,
|
||||||
|
"vendorChunk": false,
|
||||||
|
"buildOptimizer": true,
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "src/environments/environment.ts",
|
||||||
|
"with": "src/environments/environment.prod.ts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"optimization": false,
|
||||||
|
"outputHashing": "none",
|
||||||
|
"sourceMap": true,
|
||||||
|
"namedChunks": false,
|
||||||
|
"aot": false,
|
||||||
|
"extractLicenses": true,
|
||||||
|
"vendorChunk": false,
|
||||||
|
"buildOptimizer": false,
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "src/environments/environment.ts",
|
||||||
|
"with": "src/environments/environment.web.ts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"web-production": {
|
||||||
|
"optimization": true,
|
||||||
|
"outputHashing": "all",
|
||||||
|
"sourceMap": false,
|
||||||
|
"namedChunks": false,
|
||||||
|
"aot": true,
|
||||||
|
"extractLicenses": true,
|
||||||
|
"vendorChunk": false,
|
||||||
|
"buildOptimizer": true,
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "src/environments/environment.ts",
|
||||||
|
"with": "src/environments/environment.web.prod.ts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"builder": "@angular-builders/custom-webpack:dev-server",
|
||||||
|
"options": {
|
||||||
|
"browserTarget": "angular-electron:build"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"dev": {
|
||||||
|
"browserTarget": "angular-electron:build:dev"
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"browserTarget": "angular-electron:build:production"
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"browserTarget": "angular-electron:build:web"
|
||||||
|
},
|
||||||
|
"web-production": {
|
||||||
|
"browserTarget": "angular-electron:build:web-production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||||
|
"options": {
|
||||||
|
"browserTarget": "angular-electron:build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-builders/custom-webpack:karma",
|
||||||
|
"options": {
|
||||||
|
"main": "src/test.ts",
|
||||||
|
"polyfills": "src/polyfills-test.ts",
|
||||||
|
"tsConfig": "src/tsconfig.spec.json",
|
||||||
|
"karmaConfig": "src/karma.conf.js",
|
||||||
|
"inlineStyleLanguage": "scss",
|
||||||
|
"scripts": [],
|
||||||
|
"styles": [
|
||||||
|
"src/styles.scss"
|
||||||
|
],
|
||||||
|
"assets": [
|
||||||
|
"src/favicon.ico",
|
||||||
|
"src/assets"
|
||||||
|
],
|
||||||
|
"customWebpackConfig": {
|
||||||
|
"path": "./angular.webpack.js",
|
||||||
|
"replaceDuplicatePlugins": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-eslint/builder:lint",
|
||||||
|
"options": {
|
||||||
|
"lintFilePatterns": [
|
||||||
|
"src/**/*.ts",
|
||||||
|
"src/**/*.html"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"angular-electron-e2e": {
|
||||||
|
"root": "e2e",
|
||||||
|
"projectType": "application",
|
||||||
|
"architect": {
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-eslint/builder:lint",
|
||||||
|
"options": {
|
||||||
|
"lintFilePatterns": [
|
||||||
|
"e2e/**/*.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultProject": "angular-electron"
|
||||||
|
}
|
32
angular.webpack.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//Polyfill Node.js core modules in Webpack. This module is only needed for webpack 5+.
|
||||||
|
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom angular webpack configuration
|
||||||
|
*/
|
||||||
|
module.exports = (config, options) => {
|
||||||
|
config.target = 'electron-renderer';
|
||||||
|
|
||||||
|
if (options.fileReplacements) {
|
||||||
|
for(let fileReplacement of options.fileReplacements) {
|
||||||
|
if (fileReplacement.replace !== 'src/environments/environment.ts') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fileReplacementParts = fileReplacement['with'].split('.');
|
||||||
|
if (fileReplacementParts.length > 1 && ['web'].indexOf(fileReplacementParts[1]) >= 0) {
|
||||||
|
config.target = 'web';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.plugins = [
|
||||||
|
...config.plugins,
|
||||||
|
new NodePolyfillPlugin({
|
||||||
|
excludeAliases: ["console"]
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
73
app/main.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const electron_1 = require("electron");
|
||||||
|
const path = require("path");
|
||||||
|
const fs = require("fs");
|
||||||
|
let win = null;
|
||||||
|
const args = process.argv.slice(1), serve = args.some(val => val === '--serve');
|
||||||
|
function createWindow() {
|
||||||
|
const size = electron_1.screen.getPrimaryDisplay().workAreaSize;
|
||||||
|
// Create the browser window.
|
||||||
|
win = new electron_1.BrowserWindow({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: size.width,
|
||||||
|
height: size.height,
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
allowRunningInsecureContent: (serve),
|
||||||
|
contextIsolation: false, // false if you want to run e2e test with Spectron
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (serve) {
|
||||||
|
const debug = require('electron-debug');
|
||||||
|
debug();
|
||||||
|
require('electron-reloader')(module);
|
||||||
|
win.loadURL('http://localhost:4200');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Path when running electron executable
|
||||||
|
let pathIndex = './index.html';
|
||||||
|
if (fs.existsSync(path.join(__dirname, '../dist/index.html'))) {
|
||||||
|
// Path when running electron in local folder
|
||||||
|
pathIndex = '../dist/index.html';
|
||||||
|
}
|
||||||
|
const url = new URL(path.join('file:', __dirname, pathIndex));
|
||||||
|
win.loadURL(url.href);
|
||||||
|
}
|
||||||
|
// Emitted when the window is closed.
|
||||||
|
win.on('closed', () => {
|
||||||
|
// Dereference the window object, usually you would store window
|
||||||
|
// in an array if your app supports multi windows, this is the time
|
||||||
|
// when you should delete the corresponding element.
|
||||||
|
win = null;
|
||||||
|
});
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// This method will be called when Electron has finished
|
||||||
|
// initialization and is ready to create browser windows.
|
||||||
|
// Some APIs can only be used after this event occurs.
|
||||||
|
// Added 400 ms to fix the black background issue while using transparent window. More detais at https://github.com/electron/electron/issues/15947
|
||||||
|
electron_1.app.on('ready', () => setTimeout(createWindow, 400));
|
||||||
|
// Quit when all windows are closed.
|
||||||
|
electron_1.app.on('window-all-closed', () => {
|
||||||
|
// On OS X it is common for applications and their menu bar
|
||||||
|
// to stay active until the user quits explicitly with Cmd + Q
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
electron_1.app.quit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
electron_1.app.on('activate', () => {
|
||||||
|
// On OS X it's common to re-create a window in the app when the
|
||||||
|
// dock icon is clicked and there are no other windows open.
|
||||||
|
if (win === null) {
|
||||||
|
createWindow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// Catch Error
|
||||||
|
// throw e;
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=main.js.map
|
1
app/main.js.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":";;AAAA,uCAAoD;AACpD,6BAA6B;AAC7B,yBAAyB;AAEzB,IAAI,GAAG,GAAkB,IAAI,CAAC;AAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAChC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC;AAE9C,SAAS,YAAY;IAEnB,MAAM,IAAI,GAAG,iBAAM,CAAC,iBAAiB,EAAE,CAAC,YAAY,CAAC;IAErD,6BAA6B;IAC7B,GAAG,GAAG,IAAI,wBAAa,CAAC;QACtB,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,cAAc,EAAE;YACd,eAAe,EAAE,IAAI;YACrB,2BAA2B,EAAE,CAAC,KAAK,CAAC;YACpC,gBAAgB,EAAE,KAAK,EAAG,kDAAkD;SAC7E;KACF,CAAC,CAAC;IAEH,IAAI,KAAK,EAAE;QACT,MAAM,KAAK,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACxC,KAAK,EAAE,CAAC;QAER,OAAO,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;QACrC,GAAG,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;KACtC;SAAM;QACL,wCAAwC;QACxC,IAAI,SAAS,GAAG,cAAc,CAAC;QAE/B,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC,EAAE;YAC5D,6CAA6C;YAC9C,SAAS,GAAG,oBAAoB,CAAC;SAClC;QAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QAC9D,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KACvB;IAED,qCAAqC;IACrC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACpB,gEAAgE;QAChE,mEAAmE;QACnE,oDAAoD;QACpD,GAAG,GAAG,IAAI,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,IAAI;IACF,wDAAwD;IACxD,yDAAyD;IACzD,sDAAsD;IACtD,kJAAkJ;IAClJ,cAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC;IAErD,oCAAoC;IACpC,cAAG,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC/B,2DAA2D;QAC3D,8DAA8D;QAC9D,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE;YACjC,cAAG,CAAC,IAAI,EAAE,CAAC;SACZ;IACH,CAAC,CAAC,CAAC;IAEH,cAAG,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;QACtB,gEAAgE;QAChE,4DAA4D;QAC5D,IAAI,GAAG,KAAK,IAAI,EAAE;YAChB,YAAY,EAAE,CAAC;SAChB;IACH,CAAC,CAAC,CAAC;CAEJ;AAAC,OAAO,CAAC,EAAE;IACV,cAAc;IACd,WAAW;CACZ"}
|
83
app/main.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import {app, BrowserWindow, screen} from 'electron';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
let win: BrowserWindow = null;
|
||||||
|
const args = process.argv.slice(1),
|
||||||
|
serve = args.some(val => val === '--serve');
|
||||||
|
|
||||||
|
function createWindow(): BrowserWindow {
|
||||||
|
|
||||||
|
const size = screen.getPrimaryDisplay().workAreaSize;
|
||||||
|
|
||||||
|
// Create the browser window.
|
||||||
|
win = new BrowserWindow({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: size.width,
|
||||||
|
height: size.height,
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
allowRunningInsecureContent: (serve),
|
||||||
|
contextIsolation: false, // false if you want to run e2e test with Spectron
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (serve) {
|
||||||
|
const debug = require('electron-debug');
|
||||||
|
debug();
|
||||||
|
|
||||||
|
require('electron-reloader')(module);
|
||||||
|
win.loadURL('http://localhost:4200');
|
||||||
|
} else {
|
||||||
|
// Path when running electron executable
|
||||||
|
let pathIndex = './index.html';
|
||||||
|
|
||||||
|
if (fs.existsSync(path.join(__dirname, '../dist/index.html'))) {
|
||||||
|
// Path when running electron in local folder
|
||||||
|
pathIndex = '../dist/index.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(path.join('file:', __dirname, pathIndex));
|
||||||
|
win.loadURL(url.href);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emitted when the window is closed.
|
||||||
|
win.on('closed', () => {
|
||||||
|
// Dereference the window object, usually you would store window
|
||||||
|
// in an array if your app supports multi windows, this is the time
|
||||||
|
// when you should delete the corresponding element.
|
||||||
|
win = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// This method will be called when Electron has finished
|
||||||
|
// initialization and is ready to create browser windows.
|
||||||
|
// Some APIs can only be used after this event occurs.
|
||||||
|
// Added 400 ms to fix the black background issue while using transparent window. More detais at https://github.com/electron/electron/issues/15947
|
||||||
|
app.on('ready', () => setTimeout(createWindow, 400));
|
||||||
|
|
||||||
|
// Quit when all windows are closed.
|
||||||
|
app.on('window-all-closed', () => {
|
||||||
|
// On OS X it is common for applications and their menu bar
|
||||||
|
// to stay active until the user quits explicitly with Cmd + Q
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.on('activate', () => {
|
||||||
|
// On OS X it's common to re-create a window in the app when the
|
||||||
|
// dock icon is clicked and there are no other windows open.
|
||||||
|
if (win === null) {
|
||||||
|
createWindow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
// Catch Error
|
||||||
|
// throw e;
|
||||||
|
}
|
12
app/package-lock.json
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "angular-electron",
|
||||||
|
"version": "11.1.0",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "angular-electron",
|
||||||
|
"version": "11.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
app/package.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "angular-electron",
|
||||||
|
"description": "Angular Electron sample",
|
||||||
|
"author": {
|
||||||
|
"name": "Maxime GRIS",
|
||||||
|
"email": "maxime.gris@gmail.com"
|
||||||
|
},
|
||||||
|
"version": "11.1.0",
|
||||||
|
"main": "main.js",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
}
|
||||||
|
}
|
59
e2e/main.spec.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { BrowserContext, ElectronApplication, Page, _electron as electron } from 'playwright';
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
const PATH = require('path');
|
||||||
|
|
||||||
|
test.describe('Check Home Page', async () => {
|
||||||
|
let app: ElectronApplication;
|
||||||
|
let firstWindow: Page;
|
||||||
|
let context: BrowserContext;
|
||||||
|
|
||||||
|
test.beforeAll( async () => {
|
||||||
|
app = await electron.launch({ args: [PATH.join(__dirname, '../app/main.js'), PATH.join(__dirname, '../app/package.json')] });
|
||||||
|
context = app.context();
|
||||||
|
await context.tracing.start({ screenshots: true, snapshots: true });
|
||||||
|
firstWindow = await app.firstWindow();
|
||||||
|
await firstWindow.waitForLoadState('domcontentloaded');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Launch electron app', async () => {
|
||||||
|
|
||||||
|
const windowState: { isVisible: boolean; isDevToolsOpened: boolean; isCrashed: boolean } = await app.evaluate(async (process) => {
|
||||||
|
const mainWindow = process.BrowserWindow.getAllWindows()[0];
|
||||||
|
|
||||||
|
const getState = () => ({
|
||||||
|
isVisible: mainWindow.isVisible(),
|
||||||
|
isDevToolsOpened: mainWindow.webContents.isDevToolsOpened(),
|
||||||
|
isCrashed: mainWindow.webContents.isCrashed(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (mainWindow.isVisible()) {
|
||||||
|
resolve(getState());
|
||||||
|
} else {
|
||||||
|
mainWindow.once('ready-to-show', () => setTimeout(() => resolve(getState()), 0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(windowState.isVisible).toBeTruthy();
|
||||||
|
expect(windowState.isDevToolsOpened).toBeFalsy();
|
||||||
|
expect(windowState.isCrashed).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
// test('Check Home Page design', async ({ browserName}) => {
|
||||||
|
// // Uncomment if you change the design of Home Page in order to create a new screenshot
|
||||||
|
// const screenshot = await firstWindow.screenshot({ path: '/tmp/home.png' });
|
||||||
|
// expect(screenshot).toMatchSnapshot(`home-${browserName}.png`);
|
||||||
|
// });
|
||||||
|
|
||||||
|
test('Check title', async () => {
|
||||||
|
const elem = await firstWindow.$('app-home h1');
|
||||||
|
const text = await elem.innerText();
|
||||||
|
expect(text).toBe('App works !');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.afterAll( async () => {
|
||||||
|
await context.tracing.stop({ path: 'e2e/tracing/trace.zip' });
|
||||||
|
await app.close();
|
||||||
|
});
|
||||||
|
});
|
19
e2e/playwright.config.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
||||||
|
const config = {
|
||||||
|
testDir: '.',
|
||||||
|
timeout: 45000,
|
||||||
|
outputDir: './screenshots',
|
||||||
|
use: {
|
||||||
|
headless: false,
|
||||||
|
viewport: { width: 1280, height: 720 },
|
||||||
|
launchOptions: {
|
||||||
|
slowMo: 1000,
|
||||||
|
},
|
||||||
|
trace: 'on',
|
||||||
|
},
|
||||||
|
expect: {
|
||||||
|
toMatchSnapshot: { threshold: 0.2 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = config;
|
13
e2e/tsconfig.e2e.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/e2e",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": [
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**.spec.ts"
|
||||||
|
],
|
||||||
|
}
|
38
electron-builder.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"asar": true,
|
||||||
|
"directories": {
|
||||||
|
"output": "release/"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"**/*",
|
||||||
|
"!**/*.ts",
|
||||||
|
"!*.map",
|
||||||
|
"!package.json",
|
||||||
|
"!package-lock.json",
|
||||||
|
{
|
||||||
|
"from": "../dist",
|
||||||
|
"filter": ["**/*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"win": {
|
||||||
|
"icon": "dist/assets/icons",
|
||||||
|
"target": [
|
||||||
|
"portable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"portable": {
|
||||||
|
"splashImage": "dist/assets/icons/electron.bmp"
|
||||||
|
},
|
||||||
|
"mac": {
|
||||||
|
"icon": "dist/assets/icons",
|
||||||
|
"target": [
|
||||||
|
"dmg"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"linux": {
|
||||||
|
"icon": "dist/assets/icons",
|
||||||
|
"target": [
|
||||||
|
"AppImage"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
37082
package-lock.json
generated
Normal file
108
package.json
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"name": "skirda-launcher",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "no text",
|
||||||
|
"homepage": "https://github.com/maximegris/angular-electron",
|
||||||
|
"author": {
|
||||||
|
"name": "Greg Brzezinski",
|
||||||
|
"email": "gregory_brzezinski@protonmail.com"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"angular",
|
||||||
|
"angular 14",
|
||||||
|
"electron",
|
||||||
|
"electron 19",
|
||||||
|
"nodejs",
|
||||||
|
"typescript",
|
||||||
|
"playwright",
|
||||||
|
"eslint",
|
||||||
|
"sass",
|
||||||
|
"windows",
|
||||||
|
"mac",
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"main": "app/main.js",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "electron-builder install-app-deps",
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "npm-run-all -p electron:serve ng:serve",
|
||||||
|
"ng:serve": "ng serve -c web -o",
|
||||||
|
"build": "npm run electron:serve-tsc && ng build --base-href ./",
|
||||||
|
"build:dev": "npm run build -- -c dev",
|
||||||
|
"build:prod": "npm run build -- -c production",
|
||||||
|
"web:build": "npm run build -- -c web-production",
|
||||||
|
"electron": "electron",
|
||||||
|
"electron:serve-tsc": "tsc -p tsconfig.serve.json",
|
||||||
|
"electron:serve": "wait-on tcp:4200 && npm run electron:serve-tsc && electron . --serve",
|
||||||
|
"electron:local": "npm run build:prod && electron .",
|
||||||
|
"electron:build": "npm run build:prod && electron-builder build --publish=never",
|
||||||
|
"test": "ng test --watch=false",
|
||||||
|
"test:watch": "ng test",
|
||||||
|
"e2e": "npm run build:prod && playwright test -c e2e/playwright.config.ts e2e/",
|
||||||
|
"e2e:show-trace": "playwright show-trace e2e/tracing/trace.zip",
|
||||||
|
"version": "conventional-changelog -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
|
||||||
|
"lint": "ng lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/common": "14.0.6",
|
||||||
|
"@angular/compiler": "14.0.6",
|
||||||
|
"@angular/core": "14.0.6",
|
||||||
|
"@angular/forms": "14.0.6",
|
||||||
|
"@angular/language-service": "14.0.6",
|
||||||
|
"@angular/platform-browser": "14.0.6",
|
||||||
|
"@angular/platform-browser-dynamic": "14.0.6",
|
||||||
|
"@angular/router": "14.0.6",
|
||||||
|
"rxjs": "7.5.6",
|
||||||
|
"tslib": "^2.4.0",
|
||||||
|
"zone.js": "~0.11.6"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular-builders/custom-webpack": "14.0.0",
|
||||||
|
"@angular-devkit/build-angular": "14.0.6",
|
||||||
|
"@angular-eslint/builder": "14.0.2",
|
||||||
|
"@angular-eslint/eslint-plugin": "14.0.2",
|
||||||
|
"@angular-eslint/eslint-plugin-template": "14.0.2",
|
||||||
|
"@angular-eslint/schematics": "14.0.2",
|
||||||
|
"@angular-eslint/template-parser": "14.0.2",
|
||||||
|
"@angular/cli": "14.0.6",
|
||||||
|
"@angular/compiler-cli": "14.0.6",
|
||||||
|
"@ngx-translate/core": "14.0.0",
|
||||||
|
"@ngx-translate/http-loader": "7.0.0",
|
||||||
|
"@playwright/test": "1.23.4",
|
||||||
|
"@types/jasmine": "4.0.3",
|
||||||
|
"@types/jasminewd2": "2.0.10",
|
||||||
|
"@types/node": "18.0.6",
|
||||||
|
"@typescript-eslint/eslint-plugin": "5.30.7",
|
||||||
|
"@typescript-eslint/parser": "5.30.7",
|
||||||
|
"conventional-changelog-cli": "2.2.2",
|
||||||
|
"electron": "19.0.8",
|
||||||
|
"electron-builder": "23.1.0",
|
||||||
|
"electron-debug": "3.2.0",
|
||||||
|
"electron-reloader": "1.2.3",
|
||||||
|
"eslint": "8.20.0",
|
||||||
|
"eslint-plugin-import": "2.26.0",
|
||||||
|
"eslint-plugin-jsdoc": "39.3.3",
|
||||||
|
"eslint-plugin-prefer-arrow": "1.2.3",
|
||||||
|
"jasmine-core": "4.2.0",
|
||||||
|
"jasmine-spec-reporter": "7.0.0",
|
||||||
|
"karma": "6.4.0",
|
||||||
|
"karma-coverage-istanbul-reporter": "3.0.3",
|
||||||
|
"karma-electron": "7.2.0",
|
||||||
|
"karma-jasmine": "5.1.0",
|
||||||
|
"karma-jasmine-html-reporter": "2.0.0",
|
||||||
|
"node-polyfill-webpack-plugin": "2.0.0",
|
||||||
|
"npm-run-all": "4.1.5",
|
||||||
|
"playwright": "1.23.4",
|
||||||
|
"ts-node": "10.9.1",
|
||||||
|
"typescript": "~4.7.4",
|
||||||
|
"wait-on": "6.0.1",
|
||||||
|
"webdriver-manager": "12.1.8"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14.15.0"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"chrome 100"
|
||||||
|
]
|
||||||
|
}
|
28
src/app/app-routing.module.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { PageNotFoundComponent } from './shared/components';
|
||||||
|
|
||||||
|
import { HomeRoutingModule } from './home/home-routing.module';
|
||||||
|
import { DetailRoutingModule } from './detail/detail-routing.module';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
redirectTo: 'home',
|
||||||
|
pathMatch: 'full'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '**',
|
||||||
|
component: PageNotFoundComponent
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' }),
|
||||||
|
HomeRoutingModule,
|
||||||
|
DetailRoutingModule
|
||||||
|
],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class AppRoutingModule { }
|
1
src/app/app.component.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<router-outlet></router-outlet>
|
3
src/app/app.component.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
:host {
|
||||||
|
|
||||||
|
}
|
21
src/app/app.component.spec.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { ElectronService } from './core/services';
|
||||||
|
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [AppComponent],
|
||||||
|
providers: [ElectronService],
|
||||||
|
imports: [RouterTestingModule, TranslateModule.forRoot()]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should create the app', waitForAsync(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
28
src/app/app.component.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { ElectronService } from './core/services';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { APP_CONFIG } from '../environments/environment';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.scss']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
constructor(
|
||||||
|
private electronService: ElectronService,
|
||||||
|
private translate: TranslateService
|
||||||
|
) {
|
||||||
|
this.translate.setDefaultLang('en');
|
||||||
|
console.log('APP_CONFIG', APP_CONFIG);
|
||||||
|
|
||||||
|
if (electronService.isElectron) {
|
||||||
|
console.log(process.env);
|
||||||
|
console.log('Run in electron');
|
||||||
|
console.log('Electron ipcRenderer', this.electronService.ipcRenderer);
|
||||||
|
console.log('NodeJS childProcess', this.electronService.childProcess);
|
||||||
|
} else {
|
||||||
|
console.log('Run in browser');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
src/app/app.module.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule, HttpClient } from '@angular/common/http';
|
||||||
|
import { CoreModule } from './core/core.module';
|
||||||
|
import { SharedModule } from './shared/shared.module';
|
||||||
|
|
||||||
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
|
||||||
|
// NG Translate
|
||||||
|
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||||
|
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||||
|
|
||||||
|
import { HomeModule } from './home/home.module';
|
||||||
|
import { DetailModule } from './detail/detail.module';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
// AoT requires an exported function for factories
|
||||||
|
const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [AppComponent],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
FormsModule,
|
||||||
|
HttpClientModule,
|
||||||
|
CoreModule,
|
||||||
|
SharedModule,
|
||||||
|
HomeModule,
|
||||||
|
DetailModule,
|
||||||
|
AppRoutingModule,
|
||||||
|
TranslateModule.forRoot({
|
||||||
|
loader: {
|
||||||
|
provide: TranslateLoader,
|
||||||
|
useFactory: httpLoaderFactory,
|
||||||
|
deps: [HttpClient]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
providers: [],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule {}
|
10
src/app/core/core.module.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
imports: [
|
||||||
|
CommonModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class CoreModule { }
|
12
src/app/core/services/electron/electron.service.spec.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ElectronService } from './electron.service';
|
||||||
|
|
||||||
|
describe('ElectronService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: ElectronService = TestBed.get(ElectronService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
56
src/app/core/services/electron/electron.service.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
// If you import a module but never use any of the imported values other than as TypeScript types,
|
||||||
|
// the resulting javascript file will look as if you never imported the module at all.
|
||||||
|
import { ipcRenderer, webFrame } from 'electron';
|
||||||
|
import * as childProcess from 'child_process';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ElectronService {
|
||||||
|
ipcRenderer: typeof ipcRenderer;
|
||||||
|
webFrame: typeof webFrame;
|
||||||
|
childProcess: typeof childProcess;
|
||||||
|
fs: typeof fs;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// Conditional imports
|
||||||
|
if (this.isElectron) {
|
||||||
|
this.ipcRenderer = window.require('electron').ipcRenderer;
|
||||||
|
this.webFrame = window.require('electron').webFrame;
|
||||||
|
|
||||||
|
this.fs = window.require('fs');
|
||||||
|
|
||||||
|
this.childProcess = window.require('child_process');
|
||||||
|
this.childProcess.exec('node -v', (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(`error: ${error.message}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (stderr) {
|
||||||
|
console.error(`stderr: ${stderr}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`stdout:\n${stdout}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Notes :
|
||||||
|
// * A NodeJS's dependency imported with 'window.require' MUST BE present in `dependencies` of both `app/package.json`
|
||||||
|
// and `package.json (root folder)` in order to make it work here in Electron's Renderer process (src folder)
|
||||||
|
// because it will loaded at runtime by Electron.
|
||||||
|
// * A NodeJS's dependency imported with TS module import (ex: import { Dropbox } from 'dropbox') CAN only be present
|
||||||
|
// in `dependencies` of `package.json (root folder)` because it is loaded during build phase and does not need to be
|
||||||
|
// in the final bundle. Reminder : only if not used in Electron's Main process (app folder)
|
||||||
|
|
||||||
|
// If you want to use a NodeJS 3rd party deps in Renderer process,
|
||||||
|
// ipcRenderer.invoke can serve many common use cases.
|
||||||
|
// https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererinvokechannel-args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get isElectron(): boolean {
|
||||||
|
return !!(window && window.process && window.process.type);
|
||||||
|
}
|
||||||
|
}
|
1
src/app/core/services/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './electron/electron.service';
|
18
src/app/detail/detail-routing.module.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { DetailComponent } from './detail.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: 'detail',
|
||||||
|
component: DetailComponent
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
imports: [CommonModule, RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class DetailRoutingModule {}
|
7
src/app/detail/detail.component.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<div class="container">
|
||||||
|
<h1 class="title">
|
||||||
|
{{ 'PAGES.DETAIL.TITLE' | translate }}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<a routerLink="/">{{ 'PAGES.DETAIL.BACK_TO_HOME' | translate }}</a>
|
||||||
|
</div>
|
3
src/app/detail/detail.component.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
:host {
|
||||||
|
|
||||||
|
}
|
33
src/app/detail/detail.component.spec.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { DetailComponent } from './detail.component';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
|
||||||
|
describe('DetailComponent', () => {
|
||||||
|
let component: DetailComponent;
|
||||||
|
let fixture: ComponentFixture<DetailComponent>;
|
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [DetailComponent],
|
||||||
|
imports: [TranslateModule.forRoot(), RouterTestingModule]
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(DetailComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title in a h1 tag', waitForAsync(() => {
|
||||||
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelector('h1').textContent).toContain(
|
||||||
|
'PAGES.DETAIL.TITLE'
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
});
|
16
src/app/detail/detail.component.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-detail',
|
||||||
|
templateUrl: './detail.component.html',
|
||||||
|
styleUrls: ['./detail.component.scss']
|
||||||
|
})
|
||||||
|
export class DetailComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
console.log('DetailComponent INIT');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
src/app/detail/detail.module.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { DetailRoutingModule } from './detail-routing.module';
|
||||||
|
|
||||||
|
import { DetailComponent } from './detail.component';
|
||||||
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [DetailComponent],
|
||||||
|
imports: [CommonModule, SharedModule, DetailRoutingModule]
|
||||||
|
})
|
||||||
|
export class DetailModule {}
|
18
src/app/home/home-routing.module.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { HomeComponent } from './home.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: 'home',
|
||||||
|
component: HomeComponent
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
imports: [CommonModule, RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class HomeRoutingModule {}
|
7
src/app/home/home.component.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<div class="container">
|
||||||
|
<h1 class="title">
|
||||||
|
{{ 'PAGES.HOME.TITLE' | translate }}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<a routerLink="/detail">{{ 'PAGES.HOME.GO_TO_DETAIL' | translate }}</a>
|
||||||
|
</div>
|
3
src/app/home/home.component.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
:host {
|
||||||
|
|
||||||
|
}
|
32
src/app/home/home.component.spec.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { HomeComponent } from './home.component';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
|
||||||
|
describe('HomeComponent', () => {
|
||||||
|
let component: HomeComponent;
|
||||||
|
let fixture: ComponentFixture<HomeComponent>;
|
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [HomeComponent],
|
||||||
|
imports: [TranslateModule.forRoot(), RouterTestingModule]
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(HomeComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title in a h1 tag', waitForAsync(() => {
|
||||||
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelector('h1').textContent).toContain(
|
||||||
|
'PAGES.HOME.TITLE'
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
});
|
17
src/app/home/home.component.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-home',
|
||||||
|
templateUrl: './home.component.html',
|
||||||
|
styleUrls: ['./home.component.scss']
|
||||||
|
})
|
||||||
|
export class HomeComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor(private router: Router) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
console.log('HomeComponent INIT');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
src/app/home/home.module.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { HomeRoutingModule } from './home-routing.module';
|
||||||
|
|
||||||
|
import { HomeComponent } from './home.component';
|
||||||
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [HomeComponent],
|
||||||
|
imports: [CommonModule, SharedModule, HomeRoutingModule]
|
||||||
|
})
|
||||||
|
export class HomeModule {}
|
1
src/app/shared/components/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './page-not-found/page-not-found.component';
|
@ -0,0 +1,3 @@
|
|||||||
|
<p>
|
||||||
|
page-not-found works!
|
||||||
|
</p>
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PageNotFoundComponent } from './page-not-found.component';
|
||||||
|
|
||||||
|
describe('PageNotFoundComponent', () => {
|
||||||
|
let component: PageNotFoundComponent;
|
||||||
|
let fixture: ComponentFixture<PageNotFoundComponent>;
|
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [PageNotFoundComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PageNotFoundComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,14 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-page-not-found',
|
||||||
|
templateUrl: './page-not-found.component.html',
|
||||||
|
styleUrls: ['./page-not-found.component.scss']
|
||||||
|
})
|
||||||
|
export class PageNotFoundComponent implements OnInit {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
console.log('PageNotFoundComponent INIT');
|
||||||
|
}
|
||||||
|
}
|
1
src/app/shared/directives/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './webview/webview.directive';
|
@ -0,0 +1,8 @@
|
|||||||
|
import { WebviewDirective } from './webview.directive';
|
||||||
|
|
||||||
|
describe('WebviewDirective', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
const directive = new WebviewDirective();
|
||||||
|
expect(directive).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
8
src/app/shared/directives/webview/webview.directive.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { Directive } from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: 'webview'
|
||||||
|
})
|
||||||
|
export class WebviewDirective {
|
||||||
|
constructor() { }
|
||||||
|
}
|
15
src/app/shared/shared.module.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { PageNotFoundComponent } from './components/';
|
||||||
|
import { WebviewDirective } from './directives/';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [PageNotFoundComponent, WebviewDirective],
|
||||||
|
imports: [CommonModule, TranslateModule, FormsModule],
|
||||||
|
exports: [TranslateModule, WebviewDirective, FormsModule]
|
||||||
|
})
|
||||||
|
export class SharedModule {}
|
0
src/assets/.gitkeep
Normal file
BIN
src/assets/background.jpg
Normal file
After Width: | Height: | Size: 227 KiB |
12
src/assets/i18n/en.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"PAGES": {
|
||||||
|
"HOME": {
|
||||||
|
"TITLE": "App works !",
|
||||||
|
"GO_TO_DETAIL": "Go to Detail"
|
||||||
|
},
|
||||||
|
"DETAIL": {
|
||||||
|
"TITLE": "Detail page !",
|
||||||
|
"BACK_TO_HOME": "Back to Home"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
src/assets/icons/electron.bmp
Normal file
After Width: | Height: | Size: 446 KiB |
BIN
src/assets/icons/favicon.256x256.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/icons/favicon.512x512.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
src/assets/icons/favicon.icns
Normal file
BIN
src/assets/icons/favicon.ico
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/icons/favicon.png
Normal file
After Width: | Height: | Size: 14 KiB |
4
src/environments/environment.dev.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const APP_CONFIG = {
|
||||||
|
production: false,
|
||||||
|
environment: 'DEV'
|
||||||
|
};
|
4
src/environments/environment.prod.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const APP_CONFIG = {
|
||||||
|
production: true,
|
||||||
|
environment: 'PROD'
|
||||||
|
};
|
4
src/environments/environment.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const APP_CONFIG = {
|
||||||
|
production: false,
|
||||||
|
environment: 'LOCAL'
|
||||||
|
};
|
4
src/environments/environment.web.prod.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const APP_CONFIG = {
|
||||||
|
production: true,
|
||||||
|
environment: 'WEB-PROD'
|
||||||
|
};
|
4
src/environments/environment.web.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const APP_CONFIG = {
|
||||||
|
production: false,
|
||||||
|
environment: 'WEB'
|
||||||
|
};
|
BIN
src/favicon.ico
Normal file
After Width: | Height: | Size: 948 B |
14
src/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Angular Electron</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="assets/icons/favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root>Loading...</app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
45
src/karma.conf.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Karma configuration file, see link for more information
|
||||||
|
// https://karma-runner.github.io/0.13/config/configuration-file.html
|
||||||
|
|
||||||
|
module.exports = function (config) {
|
||||||
|
config.set({
|
||||||
|
basePath: '',
|
||||||
|
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||||
|
plugins: [
|
||||||
|
require('karma-jasmine'),
|
||||||
|
require('karma-electron'),
|
||||||
|
require('karma-jasmine-html-reporter'),
|
||||||
|
require('karma-coverage-istanbul-reporter'),
|
||||||
|
require('@angular-devkit/build-angular/plugins/karma')
|
||||||
|
],
|
||||||
|
client:{
|
||||||
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
|
},
|
||||||
|
coverageIstanbulReporter: {
|
||||||
|
dir: require('path').join(__dirname, '../coverage'),
|
||||||
|
reports: [ 'html', 'lcovonly' ],
|
||||||
|
fixWebpackSourcePaths: true
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
browsers: ['AngularElectron'],
|
||||||
|
customLaunchers: {
|
||||||
|
AngularElectron: {
|
||||||
|
base: 'Electron',
|
||||||
|
flags: [
|
||||||
|
'--remote-debugging-port=9222'
|
||||||
|
],
|
||||||
|
browserWindowOptions: {
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
nodeIntegrationInSubFrames: true,
|
||||||
|
allowRunningInsecureContent: true,
|
||||||
|
contextIsolation: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
15
src/main.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
import { APP_CONFIG } from './environments/environment';
|
||||||
|
|
||||||
|
if (APP_CONFIG.production) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
platformBrowserDynamic()
|
||||||
|
.bootstrapModule(AppModule, {
|
||||||
|
preserveWhitespaces: false
|
||||||
|
})
|
||||||
|
.catch(err => console.error(err));
|
1
src/polyfills-test.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
import 'zone.js';
|
53
src/polyfills.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* This file includes polyfills needed by Angular and is loaded before the app.
|
||||||
|
* You can add your own extra polyfills to this file.
|
||||||
|
*
|
||||||
|
* This file is divided into 2 sections:
|
||||||
|
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
||||||
|
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
||||||
|
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||||
|
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||||||
|
*
|
||||||
|
* Learn more in https://angular.io/guide/browser-support
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* BROWSER POLYFILLS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||||
|
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||||||
|
* because those flags need to be set before `zone.js` being loaded, and webpack
|
||||||
|
* will put import in the top of bundle, so user need to create a separate file
|
||||||
|
* in this directory (for example: zone-flags.ts), and put the following flags
|
||||||
|
* into that file, and then add the following code before importing zone.js.
|
||||||
|
* import './zone-flags.ts';
|
||||||
|
*
|
||||||
|
* The flags allowed in zone-flags.ts are listed here.
|
||||||
|
*
|
||||||
|
* The following flags will work for all browsers.
|
||||||
|
*
|
||||||
|
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
|
||||||
|
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||||||
|
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
|
||||||
|
*
|
||||||
|
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||||||
|
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||||||
|
*
|
||||||
|
* (window as any).__Zone_enable_cross_context_check = true;
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Zone JS is required by default for Angular itself.
|
||||||
|
*/
|
||||||
|
import 'zone.js'; // Included with Angular CLI.
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* APPLICATION IMPORTS
|
||||||
|
*/
|
50
src/styles.scss
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* You can add global styles to this file, and also import other style files */
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CAN (MUST) BE REMOVED ! Sample Global style */
|
||||||
|
.container {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
background: url(./assets/background.jpg) no-repeat center fixed;
|
||||||
|
-webkit-background-size: cover; /* pour anciens Chrome et Safari */
|
||||||
|
background-size: cover; /* version standardisée */
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: white;
|
||||||
|
margin: 0;
|
||||||
|
padding: 50px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #fff !important;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-decoration: none;
|
||||||
|
background: #ed3330;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
display: inline-block;
|
||||||
|
border: none;
|
||||||
|
transition: all 0.4s ease 0s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #fff;
|
||||||
|
color: #ed3330 !important;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
-webkit-box-shadow: 0px 5px 40px -10px rgba(0,0,0,0.57);
|
||||||
|
-moz-box-shadow: 0px 5px 40px -10px rgba(0,0,0,0.57);
|
||||||
|
box-shadow: 5px 40px -10px rgba(0,0,0,0.57);
|
||||||
|
transition: all 0.4s ease 0s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
22
src/test.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
|
|
||||||
|
import 'zone.js/testing';
|
||||||
|
import { getTestBed } from '@angular/core/testing';
|
||||||
|
import {
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting
|
||||||
|
} from '@angular/platform-browser-dynamic/testing';
|
||||||
|
|
||||||
|
declare const require: any;
|
||||||
|
|
||||||
|
// First, initialize the Angular testing environment.
|
||||||
|
getTestBed().initTestEnvironment(
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting(), {
|
||||||
|
teardown: { destroyAfterEach: false }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// Then we find all the tests.
|
||||||
|
const context = require.context('./', true, /\.spec\.ts$/);
|
||||||
|
// And load the modules.
|
||||||
|
context.keys().map(context);
|
20
src/tsconfig.app.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/app",
|
||||||
|
"baseUrl": "",
|
||||||
|
"types": [
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"main.ts",
|
||||||
|
"polyfills.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.d.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
23
src/tsconfig.spec.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"test.ts",
|
||||||
|
"polyfills-test.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"dist",
|
||||||
|
"release",
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
9
src/typings.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/* SystemJS module definition */
|
||||||
|
declare const nodeModule: NodeModule;
|
||||||
|
interface NodeModule {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
interface Window {
|
||||||
|
process: any;
|
||||||
|
require: any;
|
||||||
|
}
|
36
tsconfig.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist/out-tsc",
|
||||||
|
"module": "es2020",
|
||||||
|
"sourceMap": true,
|
||||||
|
"declaration": false,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"target": "es2015",
|
||||||
|
"typeRoots": [
|
||||||
|
"node_modules/@types"
|
||||||
|
],
|
||||||
|
"lib": [
|
||||||
|
"es2017",
|
||||||
|
"es2016",
|
||||||
|
"es2015",
|
||||||
|
"dom"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
],
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"strictTemplates": true,
|
||||||
|
"fullTemplateTypeCheck": true,
|
||||||
|
"annotateForClosureCompiler": true,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"skipTemplateCodegen": false,
|
||||||
|
"preserveWhitespaces": true,
|
||||||
|
"skipMetadataEmit": false,
|
||||||
|
"disableTypeScriptVersionCheck": true
|
||||||
|
}
|
||||||
|
}
|
27
tsconfig.serve.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"sourceMap": true,
|
||||||
|
"declaration": false,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es2015",
|
||||||
|
"types": [
|
||||||
|
"node"
|
||||||
|
],
|
||||||
|
"lib": [
|
||||||
|
"es2017",
|
||||||
|
"es2016",
|
||||||
|
"es2015",
|
||||||
|
"dom"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"app/main.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|