Adds a new template for the beginning of a new front end

This commit is contained in:
GloriousCode
2017-08-15 06:45:36 +10:00
parent e1c68e5ffb
commit f0a2793e8c
91 changed files with 11583 additions and 1317 deletions

60
web/.angular-cli.json Normal file
View File

@@ -0,0 +1,60 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
"name": "angular-electron",
"ejected": true
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.scss"
],
"scripts": [
],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"lint": [
{
"project": "src/tsconfig.app.json"
},
{
"project": "src/tsconfig.spec.json"
},
{
"project": "e2e/tsconfig.e2e.json"
}
],
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "scss",
"component": {
}
}
}

View File

@@ -1,3 +0,0 @@
{
"directory": "app/bower_components"
}

13
web/.editorconfig Normal file
View File

@@ -0,0 +1,13 @@
# Editor configuration, see http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

48
web/.gitignore vendored
View File

@@ -1,7 +1,43 @@
logs/*
!.gitkeep
node_modules/
bower_components/
tmp
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
/app-builds
# dependencies
/node_modules
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
testem.log
/typings
# e2e
/e2e/*.js
/e2e/*.map
# System Files
.DS_Store
.idea
Thumbs.db

View File

@@ -1,24 +0,0 @@
{
"strict": "global",
"globals": {
// Angular
"angular": false,
// Angular mocks
"module": false,
"inject": false,
// Jasmine
"jasmine": false,
"describe": false,
"beforeEach": false,
"afterEach": false,
"it": false,
"expect": false,
// Protractor
"browser": false,
"element": false,
"by": false
}
}

View File

@@ -1,14 +1,8 @@
language: node_js
node_js:
- '4.4'
before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm start > /dev/null &
- npm run update-webdriver
- sleep 1 # give server time to start
- "7"
- "6"
install:
- npm install
script:
- node_modules/.bin/karma start karma.conf.js --no-auto-watch --single-run --reporters=dots --browsers=Firefox
- node_modules/.bin/protractor e2e-tests/protractor.conf.js --browser=firefox
- npm run build

View File

@@ -1 +0,0 @@
FROM node:onbuild

View File

@@ -1,22 +0,0 @@
The MIT License
Copyright (c) 2010-2016 Google, Inc. http://angularjs.org
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.

194
web/LICENSE.md Normal file
View File

@@ -0,0 +1,194 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### Terms and Conditions for use, reproduction, and distribution
#### 1. Definitions
“License” shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
“Licensor” shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
“Legal Entity” shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, “control” means **(i)** the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the
outstanding shares, or **(iii)** beneficial ownership of such entity.
“You” (or “Your”) shall mean an individual or Legal Entity exercising
permissions granted by this License.
“Source” form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
“Object” form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
“Work” shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
“Derivative Works” shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
“Contribution” shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
“submitted” means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as “Not a Contribution.”
“Contributor” shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
#### 2. Grant of Copyright License
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
#### 3. Grant of Patent License
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
#### 4. Redistribution
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
* **(a)** You must give any other recipients of the Work or Derivative Works a copy of
this License; and
* **(b)** You must cause any modified files to carry prominent notices stating that You
changed the files; and
* **(c)** You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
#### 5. Submission of Contributions
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
#### 6. Trademarks
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
#### 7. Disclaimer of Warranty
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
#### 8. Limitation of Liability
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
#### 9. Accepting Warranty or Additional Liability
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
_END OF TERMS AND CONDITIONS_
### APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets `[]` replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same “printed page” as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -2,33 +2,72 @@
A website interface to interact with the main gocryptotrader application
## Current Features
+ Basic web views
+ Interaction between gocryptotrader and gocryptotraderweb
+ It can run... It is so incredibly basic right now
## Planned Features
You can track ideas, planned features and what's in progresss on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
### Prerequisites
Install dependencies with npm :
You can get git from [http://git-scm.com/](http://git-scm.com/).
You must have node.js and its package manager (npm) installed. You can get them from [http://nodejs.org/](http://nodejs.org/).
### Install Dependencies
```
``` bash
npm install
```
There is an issue with `yarn` and `node_modules` that are only used in electron on the backend when the application is built by the packager. Please use `npm` as dependencies manager.
### Run the Application
If you want to generate Angular components with Angular-cli , you **MUST** install `@angular/cli` in npm global context.
Please follow [Angular-cli documentation](https://github.com/angular/angular-cli) if you had installed a previous version of `angular-cli`.
The simplest way to start this server is:
```
npm start
``` bash
npm install -g @angular/cli
```
Now browse to the app at `http://localhost/`.
## To build for development
- **in a terminal window** -> npm start
- **in another terminal window** -> npm run electron:serve
Voila! You can use your Angular + Electron app in a local development environment with hot reload !
The application code is managed by `main.ts`. In this sample, the app runs with a simple Electron window and "Developer Tools" is open.
The Angular component contains an example of Electron and NodeJS native lib import. See [Use NodeJS Native libraries](#use-nodejs-native-libraries) charpter if you want to import other native libraries in your project.
You can desactivate "Developer Tools" by commenting `win.webContents.openDevTools();` in `main.ts`.
## To build for production
- Using development variables (environments/index.ts) : `npm run electron:dev`
- Using production variables (environments/index.prod.ts) : `npm run electron:prod`
Your built files are in the /dist folder.
## Included Commands
|Command|Description|
|--|--|
|`npm run start:web`| Execute the app in the brower |
|`npm run electron:linux`| Builds your application and creates an app consumable on linux system |
|`npm run electron:windows`| On a Windows OS, builds your application and creates an app consumable in windows 32/64 bit systems |
|`npm run electron:mac`| On a MAC OS, builds your application and generates a `.app` file of your application that can be run on Ma |
## Browser mode
Maybe you want to execute the application in the browser (WITHOUT HOT RELOAD ACTUALLY...) ? You can do it with `npm run start:web`.
Note that you can't use Electron or NodeJS native libraries in this case. Please check `providers/electron.service.ts` to watch how conditional import of electron/Native libraries is done.
## Execute E2E tests
You can find end-to-end tests in /e2e folder.
You can run tests with the command lines below :
- **in a terminal window** -> First, start a web server on port 4200 : `npm run start:web`
- **in another terminal window** -> Then, launch Protractor (E2E framework): `npm run e2e`
# Contributors
|[GloriousCode](https://github.com/gloriouscode)|
|[Shazbot](https://github.com/shazbert)|
|[Maxime GRIS](https://github.com/maximegris)|

1
web/_config.yml Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-architect

View File

@@ -1,45 +0,0 @@
/* app css stylesheet */
.menu {
list-style: none;
border-bottom: 0.1em solid black;
margin-bottom: 2em;
padding: 0 0 0.5em;
}
.menu:before {
content: "[";
}
.menu:after {
content: "]";
}
.menu>li {
display: inline;
}
.menu>li:before {
content: "|";
padding-right: 0.3em;
}
.menu>li:nth-child(1):before {
content: "";
padding: 0;
}
.animate-show-hide.ng-hide {
opacity: 0;
}
.animate-show-hide.ng-hide-add,
.animate-show-hide.ng-hide-remove {
transition: all linear 0.5s;
}
.check-element {
border: 1px solid black;
opacity: 1;
padding: 10px;
}

View File

@@ -1,33 +0,0 @@
'use strict';
// Declare app level module which depends on views, and components
angular.module('myApp', [
'ngRoute',
'ui-notification',
'myApp.home',
'myApp.wallets',
'myApp.settings',
'myApp.version',
'myApp.buy',
'myApp.sell',
'myApp.enabledExchanges',
'myApp.buyOrders',
'myApp.sellOrders',
'myApp.stringUtils',
'myApp.webSocket'
]).
config(['$locationProvider', '$routeProvider', 'NotificationProvider', function($locationProvider, $routeProvider, NotificationProvider) {
NotificationProvider.setOptions({
delay: 5000,
startTop: 60,
startRight: 10,
verticalSpacing: 10,
horizontalSpacing: 20,
positionX: 'right',
positionY: 'top'
});
$locationProvider.hashPrefix('!');
$routeProvider.otherwise({ redirectTo: '/' });
}]);

View File

@@ -1,12 +0,0 @@
.table-fixed-heading {
margin-bottom:0px;
}
.buy-order-table th,.buy-order-table td {
width:25%;
}
.buy-order-data {
max-height:200px;
overflow-y:scroll;
}

View File

@@ -1,25 +0,0 @@
<link rel="stylesheet" href="/components/buy-orders/buy-orders.css" />
<div class="col-md-12 buy-order-table">
<table class="table table-striped table-fixed-heading">
<thead>
<tr>
<th >Price</th>
<th >{{currencyOne}}</th>
<th >{{currencyTwo}}</th>
<th >Sum({{currencyTwo}})</th>
</tr>
</thead>
</table>
<div class="buy-order-data">
<table class="table table-striped">
<tbody>
<tr ng-repeat="buyOrder in buyOrders">
<td >{{buyOrder.price}}</td>
<td >{{buyOrder.currencyOneAmount}}</td>
<td >{{buyOrder.currencyTwoAmount}}</td>
<td >{{buyOrder.sum}}</td>
</tr>
</tbody>
</table>
<div>
</div>

View File

@@ -1,52 +0,0 @@
angular.module('myApp.buyOrders',[]).component('buyorders', {
templateUrl: '/components/buy-orders/buy-orders.html',
controller:'BuyOrdersController',
controller: function ($scope, $http, Notification, $rootScope) {
$scope.currency = {};
$scope.exchange = {};
$rootScope.$on('CurrencyChanged', function (event, args) {
$scope.currency = args.Currency;
$scope.exchange = args.Exchange;
$scope.currencyOne = $scope.currency.FirstCurrency;
$scope.currencyTwo = $scope.currency.SecondCurrency;
$scope.getRecentBuyOrders();
});
$scope.getRecentBuyOrders = function() {
var exchData = {params : {exchangeName: '', currencyPair:''}};
$http.get('/GetBuyOrdersForCurrencyPair' , exchData).success(function(data) {
$scope.buyOrders = data;
}).error(function() {
$scope.buyOrders = [
{price:12,currencyOneAmount:12,currencyTwoAmount:13,sum:1111},
{price:13,currencyOneAmount:15,currencyTwoAmount:13,sum:11231},
{price:14,currencyOneAmount:232,currencyTwoAmount:13,sum:4511},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
];
});
}
}
});

View File

@@ -1,25 +0,0 @@
<div class="col-md-12">
<div class="form col-md-12">
<div class="row">
<label>Exchange: {{exchange.exchangeName}}
</div>
<div class="row">
<label>Currency: </label>{{currency.CurrencyPair}}
</div>
<div class="row">
<label>Lowest Ask: </label><label>{{currency.Ask}}</label>
</div>
<div class="row">
<label>Price: </label><input pattern="\d*" class="form-control" ng-model="price" type="text" placeholder="How much?" />
</div>
<div class="row">
<label>Amount: </label><input pattern="\d*" ng-model="amount" class="form-control" type="text" placeholder="How much?" />
</div>
<div class="row">
<label>Total: </label><label ng-show="price > 0 && amount > 0">{{price * amount}}</label>
</div>
<div class="row">
<button ng-click="placeOrder()" class="form-control btn btn-success">Place Order</button>
</div>
</div>
<div>

View File

@@ -1,40 +0,0 @@
angular.module('myApp.buy',[]).component('buy', {
templateUrl: '/components/buy/buy.html',
controller:'BuyController',
controller: function ($scope, $http, Notification, $rootScope) {
$scope.currency = {};
$scope.exchange = {};
$rootScope.$on('CurrencyChanged', function (event, args) {
$scope.currency = args.Currency;
$scope.exchange = args.Exchange;
console.log($scope.currency);
$scope.GetLatestDataFromExchangeCurrency();
$scope.price = $scope.currency.Ask;
});
$scope.GetLatestDataFromExchangeCurrency = function () {
$http.get('/GetLatestDataFromExchangeCurrency?exhange=' + $scope.exchange.exchangeName + '&currency='+ $scope.currency.CurrencyPair).success(function (data) {
$scope.currency.Last = data.Last;
$scope.currency.Volume = data.Volume;
$scope.currency.Ask = data.Ask;
$scope.price = $scope.currency.Ask;
});
}
$scope.placeOrder = function () {
var obj = {};
obj.ExchangeName = $scope.exchange.exchangeName;
obj.Currency = $scope.currency;
obj.Price = $scope.price;
obj.Amount = $scope.amount;
$http.post('/Command/PlaceBuyOrder', obj).success(function (response) {
Notification.success("Successfully placed order");
});
};
}
});

View File

@@ -1,28 +0,0 @@
<h4>All enabled currencies</h4>
<div class="panel-group" id="accordion">
<div class="panel panel-default" ng-repeat="exchange in exchanges">
<div class="panel-heading">
<h4 class="panel-title">
<a href="javascript:;" data-toggle="collapse" data-parent="#accordion" data-target="#{{exchange.exchangeName | removeSpaces}}">
{{exchange.exchangeName}}
</a>
</h4>
</div>
<div id="{{exchange.exchangeName | removeSpaces}}" class="panel-collapse collapse" ng-class='{in:$first}'>
<div class="panel-body">
<table class="table table-striped">
<tr>
<th>Currency</th>
<th>Last</th>
<th>Volume</th>
</tr>
<tr ng-repeat="value in exchange.exchangeValues">
<td><a href="" ng-click="reloadDashboardWithExchangeCurrency(exchange,value)">{{value.CurrencyPair}}</a></td>
<td>{{value.Last | number: 6}}</td>
<td>{{value.Volume | number: 2}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>

View File

@@ -1,32 +0,0 @@
angular.module('myApp.enabledExchanges', []).component('enabledexchanges', {
templateUrl: '/components/enabled-exchanges/enabled-exchanges.html',
controller: 'EnabledExchangesController',
controller: function($scope, $http, Notification, $rootScope) {
$scope.selected = {};
$scope.getDashboardData = function() {
$http({
method: 'GET',
url: '/data/all-enabled-currencies'
}).
success(function(data, status, headers, config) {
$scope.exchanges = data.data;
$scope.reloadDashboardWithExchangeCurrency($scope.exchanges[0], $scope.exchanges[0].exchangeValues[0]);
Notification.info("Retrieved latest data");
}).
error(function(data, status, headers, config) {
console.log('error');
});
};
$scope.reloadDashboardWithExchangeCurrency = function(exchange, value) {
$scope.selected.Exchange = exchange;
$scope.selected.Currency = value;
$rootScope.$emit('CurrencyChanged', $scope.selected);
};
$scope.getDashboardData();
}
});

View File

@@ -1,9 +0,0 @@
angular.module('myApp.stringUtils', [])
.filter('removeSpaces', [function() {
return function(string) {
if (!angular.isString(string)) {
return string;
}
return string.replace(/[\s]/g, '');
};
}]);

View File

@@ -1,21 +0,0 @@
angular.module('myApp.webSocket', ['ngWebSocket'])
.factory('webSocket', function($websocket) {
// Open a WebSocket connection
var dataStream = $websocket('ws://localhost:9050/');
var collection = [];
dataStream.onMessage(function(message) {
collection.push(JSON.parse(message.data));
});
var methods = {
collection: collection,
get: function() {
dataStream.send(JSON.stringify({ action: 'get' }));
}
};
return methods;
})

View File

@@ -1,12 +0,0 @@
.table-fixed-heading {
margin-bottom:0px;
}
.buy-order-table th,.buy-order-table td {
width:25%;
}
.buy-order-data {
max-height:200px;
overflow-y:scroll;
}

View File

@@ -1,25 +0,0 @@
<link rel="stylesheet" href="/components/sell-orders/sell-orders.css" />
<div class="col-md-12 buy-order-table">
<table class="table table-striped table-fixed-heading">
<thead>
<tr>
<th >Price</th>
<th >{{currencyOne}}</th>
<th >{{currencyTwo}}</th>
<th >Sum({{currencyTwo}})</th>
</tr>
</thead>
</table>
<div class="buy-order-data">
<table class="table table-striped">
<tbody>
<tr ng-repeat="sellOrder in sellOrders">
<td >{{sellOrder.price}}</td>
<td >{{sellOrder.currencyOneAmount}}</td>
<td >{{sellOrder.currencyTwoAmount}}</td>
<td >{{sellOrder.sum}}</td>
</tr>
</tbody>
</table>
<div>
</div>

View File

@@ -1,52 +0,0 @@
angular.module('myApp.sellOrders',[]).component('sellorders', {
templateUrl: '/components/sell-orders/sell-orders.html',
controller:'SellOrdersController',
controller: function ($scope, $http, Notification, $rootScope) {
$scope.currency = {};
$scope.exchange = {};
$rootScope.$on('CurrencyChanged', function (event, args) {
$scope.currency = args.Currency;
$scope.exchange = args.Exchange;
$scope.currencyOne = $scope.currency.FirstCurrency;
$scope.currencyTwo = $scope.currency.SecondCurrency;
$scope.getRecentSellOrders();
});
$scope.getRecentSellOrders = function() {
var exchData = {params : {exchangeName: '', currencyPair:''}};
$http.get('/GetSellOrdersForCurrencyPair' , exchData).success(function(data) {
$scope.sellOrders = data;
}).error(function() {
$scope.sellOrders = [
{price:456,currencyOneAmount:12,currencyTwoAmount:13,sum:1111},
{price:234,currencyOneAmount:15,currencyTwoAmount:13,sum:11231},
{price:12344,currencyOneAmount:232,currencyTwoAmount:13,sum:4511},
{price:15467,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:6717,currencyOneAmount:2452,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:34522,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
{price:17,currencyOneAmount:22,currencyTwoAmount:13,sum:11212311},
];
});
}
}
});

View File

@@ -1,25 +0,0 @@
<div class="col-md-12">
<div class="form col-md-12">
<div class="row">
<label>Exchange: {{exchange.exchangeName}}
</div>
<div class="row">
<label>Currency: </label>{{currency.CurrencyPair}}
</div>
<div class="row">
<label>Bid: </label><label>{{currency.Bid}}</label>
</div>
<div class="row">
<label>Price: </label><input pattern="\d*" class="form-control" ng-model="price" type="text" placeholder="How much?" />
</div>
<div class="row">
<label>Amount: </label><input pattern="\d*" ng-model="amount" class="form-control" type="text" placeholder="How much?" />
</div>
<div class="row" >
<label>Total: </label><label ng-show="price > 0 && amount > 0">{{price * amount}}</label>
</div>
<div class="row">
<button ng-click="placeOrder()" class="form-control btn btn-success">Place Order</button>
</div>
</div>
<div>

View File

@@ -1,40 +0,0 @@
angular.module('myApp.sell',[]).component('sell', {
templateUrl: '/components/sell/sell.html',
controller:'SellController',
controller: function ($scope, $http, Notification, $rootScope) {
$scope.currency = {};
$scope.exchange = {};
$rootScope.$on('CurrencyChanged', function (event, args) {
$scope.currency = args.Currency;
$scope.exchange = args.Exchange;
console.log($scope.currency);
$scope.GetLatestDataFromExchangeCurrency();
$scope.price = $scope.currency.Bid;
});
$scope.GetLatestDataFromExchangeCurrency = function () {
$http.get('/GetLatestDataFromExchangeCurrency?exhange=' + $scope.exchange.exchangeName + '&currency='+ $scope.currency.CurrencyPair).success(function (data) {
$scope.currency.Last = data.Last;
$scope.currency.Volume = data.Volume;
$scope.currency.Bid = data.Bid;
$scope.price = $scope.currency.Bid;
});
}
$scope.placeOrder = function () {
var obj = {};
obj.ExchangeName = $scope.exchange.exchangeName;
obj.Currency = $scope.currency;
obj.Price = $scope.price;
obj.Amount = $scope.amount;
$http.post('/Command/PlaceSellOrder', obj).success(function (response) {
Notification.success("Successfully placed order");
});
};
}
});

View File

@@ -1,9 +0,0 @@
'use strict';
angular.module('myApp.version.interpolate-filter', [])
.filter('interpolate', ['version', function(version) {
return function(text) {
return String(text).replace(/\%VERSION\%/mg, version);
};
}]);

View File

@@ -1,15 +0,0 @@
'use strict';
describe('myApp.version module', function() {
beforeEach(module('myApp.version'));
describe('interpolate filter', function() {
beforeEach(module(function($provide) {
$provide.value('version', 'TEST_VER');
}));
it('should replace VERSION', inject(function(interpolateFilter) {
expect(interpolateFilter('before %VERSION% after')).toEqual('before TEST_VER after');
}));
});
});

View File

@@ -1,9 +0,0 @@
'use strict';
angular.module('myApp.version.version-directive', [])
.directive('appVersion', ['version', function(version) {
return function(scope, elm, attrs) {
elm.text(version);
};
}]);

View File

@@ -1,17 +0,0 @@
'use strict';
describe('myApp.version module', function() {
beforeEach(module('myApp.version'));
describe('app-version directive', function() {
it('should print current version', function() {
module(function($provide) {
$provide.value('version', 'TEST_VER');
});
inject(function($compile, $rootScope) {
var element = $compile('<span app-version></span>')($rootScope);
expect(element.text()).toEqual('TEST_VER');
});
});
});
});

View File

@@ -1,8 +0,0 @@
'use strict';
angular.module('myApp.version', [
'myApp.version.interpolate-filter',
'myApp.version.version-directive'
])
.value('version', '0.1');

View File

@@ -1,11 +0,0 @@
'use strict';
describe('myApp.version module', function() {
beforeEach(module('myApp.version'));
describe('version service', function() {
it('should return current version', inject(function(version) {
expect(version).toEqual('0.1');
}));
});
});

File diff suppressed because one or more lines are too long

View File

@@ -1,58 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="bower_components/html5-boilerplate/css/normalize.css">
<link rel="stylesheet" href="bower_components/html5-boilerplate/css/main.css">
<style>
[ng-cloak] {
display: none;
}
</style>
<script src="bower_components/html5-boilerplate/js/vendor/modernizr-2.6.2.min.js"></script>
<script>
// include angular loader, which allows the files to load in any order
//@@NG_LOADER_START@@
// You need to run `npm run update-index-async` to inject the angular async code here
//@@NG_LOADER_END@@
// include a third-party async loader library
/*!
* $script.js v1.3
* https://github.com/ded/script.js
* Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011
* Follow our software http://twitter.com/dedfat
* License: MIT
*/
!function(a,b,c){function t(a,c){var e=b.createElement("script"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName("head")[0],e={},f={},g={},h={},i="string",j=!1,k="push",l="DOMContentLoaded",m="readyState",n="addEventListener",o="onreadystatechange",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]="complete"},j),b[m]="loading");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split("|"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(""):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+".js":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];!q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join("|"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!="undefined"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)
// load all of the dependencies asynchronously.
$script([
'bower_components/angular/angular.js',
'bower_components/angular-route/angular-route.js',
'app.js',
'view1/view1.js',
'view2/view2.js',
'components/version/version.js',
'components/version/version-directive.js',
'components/version/interpolate-filter.js'
], function() {
// when all is done, execute bootstrap angular application
angular.bootstrap(document, ['myApp']);
});
</script>
<title>My AngularJS App</title>
<link rel="stylesheet" href="app.css">
</head>
<body ng-cloak>
<ul class="menu">
<li><a href="#!/view1">view1</a></li>
<li><a href="#!/view2">view2</a></li>
</ul>
<div ng-view></div>
<div>Angular seed app: v<span app-version></span></div>
</body>
</html>

View File

@@ -1,80 +0,0 @@
<!DOCTYPE html>
<!--[if lt IE 7]> <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html lang="en" ng-app="myApp" class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html lang="en" ng-app="myApp" class="no-js">
<!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>GoCrypto Trader</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/bower_components/html5-boilerplate/dist/css/normalize.css">
<link rel="stylesheet" href="/bower_components/html5-boilerplate/dist/css/main.css">
<link rel="stylesheet" href="/bower_components/angular-ui-notification/dist/angular-ui-notification.min.css">
<link rel="stylesheet" href="/app.css">
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="/darktheme.min.css">
<script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/html5-boilerplate/dist/js/vendor/modernizr-2.8.3.min.js"></script>
</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top navbar" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/">
GoCrypto Trader
</a>
</div>
<ul class="nav navbar-nav">
<li><a href="#!/">Dashboard</a></li>
<li><a href="#!/wallets">Wallets</a></li>
</ul>
<ul class="nav navbar-nav pull-right">
<li class=""><a href="#!/settings">Settings</a></li>
</ul>
</div>
</nav>
<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<div ng-view style="padding-top:60px;"></div>
<p class="text-center text-muted">Copyright 2016 GoCrypto Trader</p>
<!-- In production use:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script>
-->
<script src="/bower_components/angular/angular.js"></script>
<script src="/bower_components/angular-ui-notification/dist/angular-ui-notification.min.js"></script>
<script src="/bower_components/angular-route/angular-route.js"></script>
<script src="/bower_components/angular-websocket/dist/angular-websocket.js"></script>
<script src="/app.js"></script>
<script src="/views/settings/settings.js"></script>
<script src="/views/home/home.js"></script>
<script src="/views/wallets/wallets.js"></script>
<script src="/components/buy/buy.js"></script>
<script src="/components/sell/sell.js"></script>
<script src="/components/enabled-exchanges/enabled-exchanges.js"></script>
<script src="/components/version/version.js"></script>
<script src="/components/buy-orders/buy-orders.js"></script>
<script src="/components/sell-orders/sell-orders.js"></script>
<script src="/components/version/version-directive.js"></script>
<script src="/components/version/interpolate-filter.js"></script>
<script src="/components/helpers/stringUtils.js"></script>
<script src="/components/helpers/webSocket.js"></script>
</body>
</html>

View File

@@ -1,73 +0,0 @@
<div class="col-md-12">
<div ng-show="loaded">
<div class="col-md-12">
<h2>{{exchange.exchangeName}} Exchange</h2>
<h4>{{currency.CurrencyPair}}</h4>
</div>
<div class="col-md-8">
<div class="col-md-12">
<!-- This is to get a sense of scale, I don't intend on any hardcoded heights!' -->
<div class="col-md-6" style=" height: 300px;">
<h3>Sell orders</h3>
<!--plceholder-->
<sellorders></sellorders>
</div>
<div class="col-md-6" style=" height: 300px;">
<h3>Buy orders</h3>
<buyorders></buyorders>
</div>
</div>
<div class="col-md-12" style=" height: 300px;">
<h3>Market depth chart</h3>
</div>
<div class="col-md-4">
<h4>Buy</h4>
<buy></buy>
</div>
<div class="col-md-4" style=" height: 300px;">
<h4>Sell</h4>
<sell></sell>
</div>
<div class="col-md-4" style=" height: 300px;">
<h4>Wallet quick look</h4>
See current holding of selected currency
</div>
<div class="col-md-12">
<div class="col-md-6" style=" height: 400px;">
<h3>Trade History</h3>
</div>
<div class="col-md-6" style=" height: 400px;">
<h3>My Open Orders</h3>
</div>
</div>
</div>
<div class="col-md-4">
<enabledexchanges></enabledexchanges>
</div>
</div>
<div ng-show="!loaded && !loadFailed" class="col-md-12 text-center">
<br />
<br />
<br />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="120" height="120" fill="#40bfc0">
<path opacity=".25" d="M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4"/>
<path d="M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z">
<animateTransform attributeName="transform" type="rotate" from="0 16 16" to="360 16 16" dur="0.8s" repeatCount="indefinite" />
</path>
</svg>
<br />
<br />
<br />
</div>
<div ng-show="loadFailed">
<br />
<br />
<h1 class="text-center">D:</h1>
<br />
<h4 class="text-center">Something went wrong! Make sure Gocryptotrader is running. If things still aren't cool, open a ticket <a href="https://github.com/thrasher-/gocryptotrader/issues" target="blank">here</a></h4>
<br />
<br />
<br />
</div>
</div>

View File

@@ -1,28 +0,0 @@
'use strict';
angular.module('myApp.home', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {
templateUrl: '/views/home/home.html',
controller: 'HomeController'
});
}])
.controller('HomeController', function($scope, $rootScope, $timeout, webSocket) {
$scope.loaded = false;
$rootScope.$on('CurrencyChanged', function(event, args) {
$scope.currency = args.Currency;
$scope.exchange = args.Exchange;
$scope.loaded = true;
});
$timeout(function() {
if ($scope.currency) {
$scope.loaded = true;
} else {
$scope.loadFailed = true;
}
}, 10000);
});

View File

@@ -1,16 +0,0 @@
'use strict';
describe('myApp.view1 module', function() {
beforeEach(module('myApp.view1'));
describe('view1 controller', function(){
it('should ....', inject(function($controller) {
//spec body
var view1Ctrl = $controller('View1Ctrl');
expect(view1Ctrl).toBeDefined();
}));
});
});

View File

@@ -1,60 +0,0 @@
<h2>Settings</h2>
<div class="col-md-12">
<div class="col-md-10 container " >
<h4>Exchange config</h4>
<div ng-repeat="exchange in config.Exchanges">
<div class="row">
<h3>{{exchange.Name}}</h3>
</div>
<div class="row">
<div class="col-md-2">
<label class="input-form">Enabled:</label>
</div>
<div class="col-md-10">
<input type="checkbox" class="input-form" ng-model="exchange.Enabled"/>
</div>
</div>
<div ng-show="exchange.Enabled">
<div class="row">
<div class="col-md-2">
<label class="input-form">API Key:</label>
</div>
<div class="col-md-10">
<input type="text" class="input-form" ng-model="exchange.APIKey"/>
</div>
</div>
<div class="row">
<div class="col-md-2">
<label class="input-form">API Secret:</label>
</div>
<div class="col-md-10">
<input type="text" class="input-form" ng-model="exchange.APISecret"/>
</div>
</div>
<div class="row">
<div class="col-md-2">
<label class="input-form">Client ID:</label>
</div>
<div class="col-md-10">
<input type="text" class="input-form" ng-model="exchange.ClientID"/>
</div>
</div>
<div class="row">
<div class="col-md-2">
<label class="input-form">Currencies to check:</label>
</div>
<div class="col-md-10">
<div class="col-md-2" ng-repeat="availableCurrency in exchange.AvailablePairsSplit">
<div class="col-md-8">{{availableCurrency}}</div>
<div class="col-md-4"><input type="checkbox" class="input-form" ng-click="toggleCurrencyToEnabledCurrencies(availableCurrency, exchange)" ng-checked="exchange.EnabledPairsSplit.indexOf(availableCurrency) > -1"/></div>
</div>
</div>
</div>
<button class="btn btn-success btn-lg" ng-click="saveAllSettings()">Save</button>
</div>
</div>
</div>
<div class="col-md-2">
<button class="btn btn-success btn-lg" style="float:right;position:fixed;top:120px;right:60px;" ng-click="saveAllSettings()">Save</button>
</div>
</div>

View File

@@ -1,80 +0,0 @@
'use strict';
angular.module('myApp.settings', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/settings', {
templateUrl: '/views/settings/settings.html',
controller: 'SettingsController'
});
}])
.controller('SettingsController', function ($scope, $http, Notification) {
$scope.getconfigData = function() {
$http({
method: 'GET',
url: '/config/all'
}).
success(function (data, status, headers, config) {
for(var i=0; i<data.Exchanges.length;i++) {
data.Exchanges[i].AvailablePairsSplit = data.Exchanges[i].AvailablePairs.split(",");
data.Exchanges[i].EnabledPairsSplit = data.Exchanges[i].EnabledPairs.split(",");
}
$scope.config = data;
Notification.info('Settings loaded');
}).
error(function (data, status, headers, config) {
console.log('error');
});
};
$scope.getconfigData();
$scope.toggleCurrencyToEnabledCurrencies = function(currency, exchange) {
for(var i=0; i<$scope.config.Exchanges.length;i++) {
if($scope.config.Exchanges[i].Name == exchange.Name) {
if(exchange.EnabledPairsSplit.indexOf(currency) > -1) {
$scope.config.Exchanges[i].EnabledPairsSplit.splice($scope.config.Exchanges[i].EnabledPairsSplit.indexOf(currency),1);
//I feel there's a better way to do this, but for right now, whatever
$scope.config.Exchanges[i].EnabledPairs = $scope.config.Exchanges[i].EnabledPairs.replace(currency,"");
$scope.config.Exchanges[i].EnabledPairs = $scope.config.Exchanges[i].EnabledPairs.replace(",,","");
$scope.config.Exchanges[i].EnabledPairs = $scope.config.Exchanges[i].EnabledPairs.replace(/,\s*$/, "");
} else {
$scope.config.Exchanges[i].EnabledPairsSplit.push(currency);
$scope.config.Exchanges[i].EnabledPairs = $scope.config.Exchanges[i].EnabledPairs + "," + currency;
}
}
}
}
$scope.saveAllSettings = function() {
$scope.postObject = jQuery.extend(true, {}, $scope.config);
//Purge any unnecessary post data
delete $scope.postObject.Webserver;
for(var i=0; i<$scope.postObject.Exchanges.length;i++) {
delete $scope.postObject.Exchanges[i].AvailablePairsSplit;
delete $scope.postObject.Exchanges[i].AvailablePairs;
delete $scope.postObject.Exchanges[i].BaseCurrencies;
delete $scope.postObject.Exchanges[i].EnabledPairsSplit;
}
//Send to be saved
$http({
method: 'POST',
url: '/config/all/save',
data: $scope.postObject
}).
success(function (data) {
Notification.success('Saved settings');
for(var i=0; i<data.Exchanges.length;i++) {
data.Exchanges[i].AvailablePairsSplit = data.Exchanges[i].AvailablePairs.split(",");
data.Exchanges[i].EnabledPairsSplit = data.Exchanges[i].EnabledPairs.split(",");
}
$scope.config = data;
Notification.info('Settings loaded');
}).
error(function (data) {
Notification.error('Save failed');
});
}
});

View File

@@ -1,16 +0,0 @@
'use strict';
describe('myApp.view1 module', function() {
beforeEach(module('myApp.view1'));
describe('view1 controller', function(){
it('should ....', inject(function($controller) {
//spec body
var view1Ctrl = $controller('View1Ctrl');
expect(view1Ctrl).toBeDefined();
}));
});
});

View File

@@ -1,17 +0,0 @@
<h2>Wallets</h2>
<h3>All your currency, all in one place</h3>
<div ng-repeat="wallet in wallets">
<h4>{{wallet.ExchangeName}}</h4>
<table class="table table-striped">
<tr>
<th>Currency Name</th>
<th>Total</th>
<th>Hold</th>
</tr>
<tr ng-repeat="value in wallet.Currencies">
<td>{{value.CurrencyName}}</td>
<td>{{value.TotalValue}}</td>
<td>{{value.Hold}}</td>
</tr>
</table>
</div>

View File

@@ -1,29 +0,0 @@
'use strict';
angular.module('myApp.wallets', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/wallets', {
templateUrl: '/views/wallets/wallets.html',
controller: 'WalletsController'
});
}])
.controller('WalletsController', function ($scope, $http, Notification) {
$scope.getDashboardData = function() {
$http({
method: 'GET',
url: '/data/all-enabled-exchange-account-info'
}).
success(function (data, status, headers, config) {
$scope.wallets = data.data;
Notification.info("Got your wallet!");
}).
error(function (data, status, headers, config) {
console.log('error');
});
};
$scope.getDashboardData();
});

View File

@@ -1,16 +0,0 @@
'use strict';
describe('myApp.view1 module', function() {
beforeEach(module('myApp.view1'));
describe('view1 controller', function(){
it('should ....', inject(function($controller) {
//spec body
var view1Ctrl = $controller('View1Ctrl');
expect(view1Ctrl).toBeDefined();
}));
});
});

View File

@@ -1,18 +0,0 @@
{
"name": "angular-seed",
"description": "A starter project for AngularJS",
"version": "0.0.0",
"homepage": "https://github.com/angular/angular-seed",
"license": "MIT",
"private": true,
"dependencies": {
"angular": "~1.5.0",
"angular-route": "~1.5.0",
"angular-loader": "~1.5.0",
"angular-mocks": "~1.5.0",
"html5-boilerplate": "^5.3.0",
"angular-ui-notification":"latest",
"angular-websocket":"2.0.0",
"bootstrap":"3.3.7"
}
}

View File

@@ -1,22 +0,0 @@
//jshint strict: false
exports.config = {
allScriptsTimeout: 11000,
specs: [
'*.js'
],
capabilities: {
'browserName': 'chrome'
},
baseUrl: 'http://localhost:8000/',
framework: 'jasmine',
jasmineNodeOpts: {
defaultTimeoutInterval: 30000
}
};

View File

@@ -1,42 +0,0 @@
'use strict';
/* https://github.com/angular/protractor/blob/master/docs/toc.md */
describe('my app', function() {
it('should automatically redirect to /view1 when location hash/fragment is empty', function() {
browser.get('index.html');
expect(browser.getLocationAbsUrl()).toMatch("/view1");
});
describe('view1', function() {
beforeEach(function() {
browser.get('index.html#!/view1');
});
it('should render view1 when user navigates to /view1', function() {
expect(element.all(by.css('[ng-view] p')).first().getText()).
toMatch(/partial for view 1/);
});
});
describe('view2', function() {
beforeEach(function() {
browser.get('index.html#!/view2');
});
it('should render view2 when user navigates to /view2', function() {
expect(element.all(by.css('[ng-view] p')).first().getText()).
toMatch(/partial for view 2/);
});
});
});

14
web/e2e/app.e2e-spec.ts Normal file
View File

@@ -0,0 +1,14 @@
import { AngularElectronPage } from './app.po';
import { browser, element, by } from 'protractor';
describe('angular-electron App', () => {
let page: AngularElectronPage;
beforeEach(() => {
page = new AngularElectronPage();
});
it('should display message saying App works !', () => {
expect(element(by.css('app-home h1')).getText()).toMatch('App works !');
});
});

8
web/e2e/app.po.ts Normal file
View File

@@ -0,0 +1,8 @@
import { browser, element, by } from 'protractor';
/* tslint:disable */
export class AngularElectronPage {
navigateTo(route: string) {
return browser.get(route);
}
}

12
web/e2e/tsconfig.e2e.json Normal file
View File

@@ -0,0 +1,12 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types":[
"jasmine",
"node"
]
}
}

View File

@@ -1,34 +1,44 @@
//jshint strict: false
module.exports = function(config) {
// 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: './app',
files: [
'bower_components/angular/angular.js',
'bower_components/angular-route/angular-route.js',
'bower_components/angular-mocks/angular-mocks.js',
'components/**/*.js',
'view*/**/*.js'
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
basePath: '',
frameworks: ['jasmine', '@angular/cli'],
plugins: [
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-jasmine',
'karma-junit-reporter'
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular/cli/plugins/karma')
],
junitReporter: {
outputFile: 'test_out/unit.xml',
suite: 'unit'
}
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
files: [
{ pattern: './src/test.ts', watched: false }
],
preprocessors: {
'./src/test.ts': ['@angular/cli']
},
mime: {
'text/x-typescript': ['ts','tsx']
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: config.angularCli && config.angularCli.codeCoverage
? ['progress', 'coverage-istanbul']
: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};

BIN
web/logo-angular.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
web/logo-electron.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

71
web/main.ts Normal file
View File

@@ -0,0 +1,71 @@
import { app, BrowserWindow, screen } from 'electron';
import * as path from 'path';
let win, serve;
const args = process.argv.slice(1);
serve = args.some(val => val === '--serve');
if (serve) {
require('electron-reload')(__dirname, {
});
}
function createWindow() {
const electronScreen = screen;
const size = electronScreen.getPrimaryDisplay().workAreaSize;
// Create the browser window.
win = new BrowserWindow({
x: 0,
y: 0,
width: size.width,
height: size.height
});
// and load the index.html of the app.
win.loadURL('file://' + __dirname + '/index.html');
// Open the DevTools.
if (serve) {
win.webContents.openDevTools();
}
// 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;
});
}
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.
app.on('ready', createWindow);
// 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;
}

9906
web/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

60
web/package.js Normal file
View File

@@ -0,0 +1,60 @@
"use strict";
var packager = require('electron-packager');
const pkg = require('./package.json');
const argv = require('minimist')(process.argv.slice(1));
const appName = argv.name || pkg.name;
const buildVersion = pkg.version || '1.0';
const shouldUseAsar = argv.asar || false;
const shouldBuildAll = argv.all || false;
const arch = argv.arch || 'all';
const platform = argv.platform || 'darwin';
const DEFAULT_OPTS = {
dir: './dist',
name: appName,
asar: shouldUseAsar,
buildVersion: buildVersion
};
pack(platform, arch, function done(err, appPath) {
if (err) {
console.log(err);
} else {
console.log('Application packaged successfuly!', appPath);
}
});
function pack(plat, arch, cb) {
// there is no darwin ia32 electron
if (plat === 'darwin' && arch === 'ia32') return;
let icon = 'src/favicon';
if (icon) {
DEFAULT_OPTS.icon = icon + (() => {
let extension = '.png';
if (plat === 'darwin') {
extension = '.icns';
} else if (plat === 'win32') {
extension = '.ico';
}
return extension;
})();
}
const opts = Object.assign({}, DEFAULT_OPTS, {
platform: plat,
arch,
prune: true,
overwrite: true,
all: shouldBuildAll,
out: `app-builds`
});
console.log(opts)
packager(opts, cb);
}

View File

@@ -1,38 +1,103 @@
{
"name": "angular-seed",
"private": true,
"version": "0.0.0",
"description": "A starter project for AngularJS",
"repository": "https://github.com/angular/angular-seed",
"license": "MIT",
"devDependencies": {
"bower": "^1.7.7",
"http-server": "^0.9.0",
"jasmine-core": "^2.4.1",
"karma": "^0.13.22",
"karma-chrome-launcher": "^0.2.3",
"karma-firefox-launcher": "^0.1.7",
"karma-jasmine": "^0.3.8",
"karma-junit-reporter": "^0.4.1",
"protractor": "^3.2.2",
"express": "latest",
"requestify": "latest",
"body-parser": "latest"
"name": "angular-electron",
"version": "1.6.1",
"description": "Angular 4 with Electron (Typescript + SASS + Hot Reload)",
"homepage": "https://github.com/maximegris/angular-electron",
"author": {
"name": "Maxime GRIS",
"email": "maxime.gris@gmail.com"
},
"keywords": [
"angular",
"electron",
"typescript",
"sass"
],
"main": "main.js",
"private": true,
"scripts": {
"postinstall": "bower install",
"prestart": "npm install",
"start": "node server.js",
"pretest": "npm install",
"test": "karma start karma.conf.js",
"test-single-run": "karma start karma.conf.js --single-run",
"preupdate-webdriver": "npm install",
"update-webdriver": "webdriver-manager update",
"preprotractor": "npm run update-webdriver",
"protractor": "protractor e2e-tests/protractor.conf.js",
"update-index-async": "node -e \"var fs=require('fs'),indexFile='app/index-async.html',loaderFile='app/bower_components/angular-loader/angular-loader.min.js',loaderText=fs.readFileSync(loaderFile,'utf-8').split(/sourceMappingURL=angular-loader.min.js.map/).join('sourceMappingURL=bower_components/angular-loader/angular-loader.min.js.map'),indexText=fs.readFileSync(indexFile,'utf-8').split(/\\/\\/@@NG_LOADER_START@@[\\s\\S]*\\/\\/@@NG_LOADER_END@@/).join('//@@NG_LOADER_START@@\\n'+loaderText+' //@@NG_LOADER_END@@');fs.writeFileSync(indexFile,indexText);\""
"ng": "ng",
"lint": "ng lint",
"start": "webpack --watch",
"start:web": "webpack-dev-server --content-base . --port 4200 --inline",
"build:electron:main": "tsc main.ts --outDir dist && copyfiles package.json dist && cd dist && npm install --prod && cd ..",
"build": "webpack --display-error-details && npm run build:electron:main",
"build:prod": "cross-env NODE_ENV=production npm run build",
"electron:serve": "npm run build:electron:main && electron ./dist --serve",
"electron:test": "electron ./dist",
"electron:dev": "npm run build && electron ./dist",
"electron:prod": "npm run build:prod && electron ./dist",
"electron:linux": "npm run build:prod && node package.js --asar --platform=linux --arch=x64",
"electron:windows": "npm run build:prod && node package.js --asar --platform=win32 --arch=ia32",
"electron:mac": "npm run build:prod && node package.js --asar --platform=darwin --arch=x64",
"test": "karma start ./karma.conf.js",
"pree2e": "webdriver-manager update --standalone false --gecko false --quiet && npm run build",
"e2e": "protractor ./protractor.conf.js"
},
"dependencies": {
"request": "^2.74.0"
}
"@angular/common": "4.3.0",
"@angular/compiler": "4.3.0",
"@angular/core": "4.3.0",
"@angular/forms": "4.3.0",
"@angular/http": "4.3.0",
"@angular/platform-browser": "4.3.0",
"@angular/platform-browser-dynamic": "4.3.0",
"@angular/router": "4.3.0",
"core-js": "2.4.1",
"enhanced-resolve": "3.3.0",
"rxjs": "5.4.2",
"zone.js": "0.8.12"
},
"devDependencies": {
"@angular/cli": "1.2.1",
"@angular/compiler-cli": "4.3.0",
"@types/bluebird": "3.5.8",
"@types/core-js": "0.9.36",
"@types/jasmine": "2.5.53",
"@types/node": "7.0.7",
"autoprefixer": "7.1.1",
"codelyzer": "3.1.1",
"copyfiles": "1.2.0",
"cross-env": "5.0.1",
"css-loader": "0.28.4",
"cssnano": "3.10.0",
"electron": "1.6.11",
"electron-packager": "8.7.2",
"electron-reload": "1.2.1",
"exports-loader": "0.6.4",
"extract-zip": "=1.6.5",
"file-loader": "0.11.2",
"html-loader": "0.4.5",
"istanbul-instrumenter-loader": "2.0.0",
"jasmine-core": "2.6.4",
"jasmine-spec-reporter": "4.1.1",
"json-loader": "0.5.4",
"karma": "1.7.0",
"karma-chrome-launcher": "2.2.0",
"karma-cli": "1.0.1",
"karma-coverage-istanbul-reporter": "0.2.0",
"karma-jasmine": "1.1.0",
"karma-jasmine-html-reporter": "0.2.2",
"karma-sourcemap-loader": "0.3.7",
"less-loader": "4.0.4",
"minimist": "1.2.0",
"mkdirp": "0.5.1",
"postcss-loader": "1.3.3",
"postcss-url": "7.0.0",
"protractor": "5.1.2",
"raw-loader": "0.5.1",
"sass-loader": "6.0.6",
"script-loader": "0.7.0",
"source-map-loader": "0.2.1",
"style-loader": "0.18.2",
"stylus-loader": "3.0.1",
"ts-node": "3.1.0",
"tslint": "5.4.3",
"typescript": "2.4.1",
"url-loader": "0.5.9",
"webdriver-manager": "12.0.6",
"webpack": "3.3.0",
"webpack-dev-server": "2.5.0"
},
"license": "SEE LICENSE IN LICENSE.md"
}

36
web/protractor.conf.js Normal file
View File

@@ -0,0 +1,36 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 25000,
getPageTimeout: 15000,
delayBrowserTimeInSeconds: 0,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome',
chromeOptions: {
binary: './node_modules/electron/dist/electron.exe',
args: ['--test-type=webdriver', 'app=dist/main.js']
}
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine2',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function () { }
},
beforeLaunch: function () {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
},
onPrepare() {
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

View File

@@ -1,63 +0,0 @@
var express = require('express')
, app = express();
var requestify = require('requestify');
var bodyParser = require('body-parser')
var request = require('request');
var path = __dirname + '/app/';
app.use("/bower_components", express.static(path + '/bower_components'));
app.use( bodyParser.json() );
app.get("/",function(req,res){
res.sendFile(path + "index.html");
});
app.use("/", express.static(path + '/'));
app.get('/data/all-enabled-currencies', function (req, res) {
request({
url :'http://localhost:9050/exchanges/enabled/latest/all'
},function(err, resp, body){
res.send(body);
})
});
app.get('/data/all-enabled-exchange-account-info', function (req, res) {
request({
url :'http://localhost:9050/exchanges/enabled/accounts/all'
},function(err, resp, body){
res.send(body);
})
});
app.get('/config/all', function (req, res) {
request({
url :'http://localhost:9050/config/all'
},function(err, resp, body){
res.send(body);
})
});
////////////////////////////////////////////////////////
// Posts
///////////////////////////////////////////////////////
app.post('/config/all/save', function(req, res) {
requestify.post('http://localhost:9050/config/all/save', {
Data: req.body
})
.then(function(response) {
console.log(response);
res.send(response.body);
});
});
var port = process.env.GCT_WEB_PORT || 80;
app.listen(port, function(){
console.log(`GoCyptoTrader website running! Enter http://localhost:${port}/ into browser`);
});

View File

@@ -0,0 +1,21 @@
import { HomeComponent } from './components/home/home.component';
import { AboutComponent } from './components/about/about.component';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
{
path: '',
component: HomeComponent
},
{
path:'about',
component: AboutComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes, {useHash: true})],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@@ -0,0 +1 @@
<router-outlet></router-outlet>

View File

@@ -0,0 +1,24 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
import { ElectronService } from 'app/providers/electron.service';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
providers : [
ElectronService
],
imports: [RouterTestingModule]
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});

View File

@@ -0,0 +1,22 @@
import { Component } from '@angular/core';
import { ElectronService } from './providers/electron.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(public electronService: ElectronService) {
if (electronService.isElectron()) {
console.log('Mode electron');
// Check if electron is correctly injected (see externals in webpack.config.js)
console.log('c', electronService.ipcRenderer);
// Check if nodeJs childProcess is correctly injected (see externals in webpack.config.js)
console.log('c', electronService.childProcess);
} else {
console.log('Mode web');
}
}
}

32
web/src/app/app.module.ts Normal file
View File

@@ -0,0 +1,32 @@
import 'zone.js/dist/zone-mix';
import 'reflect-metadata';
import 'polyfills';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { HomeComponent } from './components/home/home.component';
import { AboutComponent } from './components/about/about.component';
import { AppRoutingModule } from './app-routing.module';
import { ElectronService } from './providers/electron.service';
@NgModule({
declarations: [
AppComponent,
HomeComponent,
AboutComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule
],
providers: [ElectronService],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@@ -0,0 +1,3 @@
<p>
about works!
</p>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AboutComponent } from './about.component';
describe('AboutComponent', () => {
let component: AboutComponent;
let fixture: ComponentFixture<AboutComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AboutComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AboutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-about',
templateUrl: './about.component.html',
styleUrls: ['./about.component.scss']
})
export class AboutComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

View File

@@ -0,0 +1,6 @@
<div class="container">
<h1 class="title">
{{title}}
</h1>
<a routerLink="/about" routerLinkActive="active" >hello</a>
</div>

View File

@@ -0,0 +1,17 @@
.container {
height: 100%;
display: flex;
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;
}
}

View File

@@ -0,0 +1,38 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HomeComponent } from './home.component';
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HomeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it(`should have as title 'App works !'`, async(() => {
fixture = TestBed.createComponent(HomeComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('App works !');
}));
it('should render title in a h1 tag', async(() => {
fixture = TestBed.createComponent(HomeComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('App works !');
}));
});

View File

@@ -0,0 +1,16 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
title = `App works !`;
constructor() { }
ngOnInit() {
}
}

View File

@@ -0,0 +1,26 @@
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 } from 'electron';
import * as childProcess from 'child_process';
@Injectable()
export class ElectronService {
ipcRenderer: typeof ipcRenderer;
childProcess: typeof childProcess;
constructor() {
// Conditional imports
if (this.isElectron()) {
this.ipcRenderer = window.require('electron').ipcRenderer;
this.childProcess = window.require('child_process');
}
}
isElectron = () => {
return window && window.process && window.process.type;
}
}

0
web/src/assets/.gitkeep Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

View File

@@ -0,0 +1,5 @@
// This file contains production variables. (When you work in PROD MODE)
// This file is use by webpack. Please don't rename it and don't move it to another directory.
export const environment = {
production: true
};

View File

@@ -0,0 +1,5 @@
// This file contains development variables. (When you work in DEV MODE)
// This file is use by webpack. Please don't rename it and don't move it to another directory.
export const environment = {
production: false
};

BIN
web/src/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

14
web/src/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>AngularElectron</title>
<base href="./">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root>Loading...</app-root>
</body>
</html>

11
web/src/main.ts Normal file
View File

@@ -0,0 +1,11 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from 'environments';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);

67
web/src/polyfills.ts Normal file
View File

@@ -0,0 +1,67 @@
/**
* 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/docs/ts/latest/guide/browser-support.html
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/set';
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/** IE10 and IE11 requires the following to support `@angular/animation`. */
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/** Evergreen browsers require these. **/
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
/** ALL Firefox browsers require the following to support `@angular/animation`. **/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/***************************************************************************************************
* Zone JS is required by Angular itself.
*/
import 'zone.js/dist/zone-mix'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/
/**
* Date, currency, decimal and percent pipes.
* Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
*/
// import 'intl'; // Run `npm install --save intl`.

7
web/src/styles.scss Normal file
View File

@@ -0,0 +1,7 @@
/* You can add global styles to this file, and also import other style files */
html, body {
margin: 0;
padding: 0;
height: 100%;
}

32
web/src/test.ts Normal file
View File

@@ -0,0 +1,32 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/jasmine-patch';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async-test';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
declare const __karma__: any;
declare const require: any;
// Prevent Karma from running prematurely.
__karma__.loaded = function () {};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);
// Finally, start Karma to run the tests.
__karma__.start();

16
web/src/tsconfig.app.json Normal file
View File

@@ -0,0 +1,16 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "es2015",
"baseUrl": "",
"types": []
},
"exclude": [
"test.ts",
"**/*.spec.ts",
"dist",
"app-builds",
"node_modules"
]
}

View File

@@ -0,0 +1,25 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"module": "commonjs",
"target": "es5",
"baseUrl": "",
"types": [
"jasmine",
"node"
]
},
"files": [
"test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
],
"exclude": [
"dist",
"app-builds",
"node_modules"
]
}

11
web/src/typings.d.ts vendored Normal file
View File

@@ -0,0 +1,11 @@
/* SystemJS module definition */
declare var nodeModule: NodeModule;
interface NodeModule {
id: string;
}
declare var window: Window;
interface Window {
process: any;
require: any;
}

30
web/tsconfig.json Normal file
View File

@@ -0,0 +1,30 @@
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"baseUrl": "src",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowJs": true,
"target": "es5",
"paths": {
"environments": [
"./environments"
]
},
"types": [
"node",
"jasmine"
],
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2016",
"dom"
]
}
}

116
web/tslint.json Normal file
View File

@@ -0,0 +1,116 @@
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"eofline": true,
"forin": true,
"import-blacklist": [true, "rxjs"],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
"static-before-instance",
"variables-before-functions"
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-variable": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [true, "ignore-params"],
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"typeof-compare": true,
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"directive-selector": [true, "attribute", "app", "camelCase"],
"component-selector": [true, "element", "app", "kebab-case"],
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"use-host-property-decorator": true,
"no-input-rename": true,
"no-output-rename": true,
"use-life-cycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true,
"no-access-missing-member": true,
"templates-use-public": true,
"invoke-injectable": true
}
}

386
web/webpack.config.js Normal file
View File

@@ -0,0 +1,386 @@
const path = require('path');
const webpack = require('webpack');
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
const postcssUrl = require('postcss-url');
const { NoEmitOnErrorsPlugin, LoaderOptionsPlugin, DefinePlugin, HashedModuleIdsPlugin } = require('webpack');
const { GlobCopyWebpackPlugin, BaseHrefWebpackPlugin } = require('@angular/cli/plugins/webpack');
const { CommonsChunkPlugin, UglifyJsPlugin } = require('webpack').optimize;
const { AotPlugin } = require('@ngtools/webpack');
const nodeModules = path.join(process.cwd(), 'node_modules');
const entryPoints = ["inline", "polyfills", "sw-register", "styles", "vendor", "main"];
const baseHref = "";
const deployUrl = "";
const isProd = (process.env.NODE_ENV === 'production');
function getPlugins() {
var plugins = [];
// Always expose NODE_ENV to webpack, you can now use `process.env.NODE_ENV`
// inside your code for any environment checks; UglifyJS will automatically
// drop any unreachable code.
plugins.push(new DefinePlugin({
"process.env.NODE_ENV": "\"production\""
}));
plugins.push(new NoEmitOnErrorsPlugin());
plugins.push(new GlobCopyWebpackPlugin({
"patterns": [
"assets",
"favicon.ico"
],
"globOptions": {
"cwd": process.cwd() + "/src",
"dot": true,
"ignore": "**/.gitkeep"
}
}));
plugins.push(new ProgressPlugin());
plugins.push(new HtmlWebpackPlugin({
"template": "./src/index.html",
"filename": "./index.html",
"hash": false,
"inject": true,
"compile": true,
"favicon": false,
"minify": false,
"cache": true,
"showErrors": true,
"chunks": "all",
"excludeChunks": [],
"title": "Webpack App",
"xhtml": true,
"chunksSortMode": function sort(left, right) {
let leftIndex = entryPoints.indexOf(left.names[0]);
let rightindex = entryPoints.indexOf(right.names[0]);
if (leftIndex > rightindex) {
return 1;
}
else if (leftIndex < rightindex) {
return -1;
}
else {
return 0;
}
}
}));
plugins.push(new BaseHrefWebpackPlugin({}));
plugins.push(new CommonsChunkPlugin({
"name": "inline",
"minChunks": null
}));
plugins.push(new CommonsChunkPlugin({
"name": "vendor",
"minChunks": (module) => module.resource && module.resource.startsWith(nodeModules),
"chunks": [
"main"
]
}));
plugins.push(new ExtractTextPlugin({
"filename": "[name].bundle.css",
"disable": true
}));
plugins.push(new LoaderOptionsPlugin({
"sourceMap": false,
"options": {
"postcss": [
autoprefixer(),
postcssUrl({
"url": (obj) => {
// Only convert root relative URLs, which CSS-Loader won't process into require().
if (!obj.url.startsWith('/') || obj.url.startsWith('//')) {
return obj.url;
}
if (deployUrl.match(/:\/\//)) {
// If deployUrl contains a scheme, ignore baseHref use deployUrl as is.
return `${deployUrl.replace(/\/$/, '')}${obj.url}`;
}
else if (baseHref.match(/:\/\//)) {
// If baseHref contains a scheme, include it as is.
return baseHref.replace(/\/$/, '') +
`/${deployUrl}/${obj.url}`.replace(/\/\/+/g, '/');
}
else {
// Join together base-href, deploy-url and the original URL.
// Also dedupe multiple slashes into single ones.
return `/${baseHref}/${deployUrl}/${obj.url}`.replace(/\/\/+/g, '/');
}
}
})
],
"sassLoader": {
"sourceMap": false,
"includePaths": []
},
"lessLoader": {
"sourceMap": false
},
"context": ""
}
}));
if (isProd) {
plugins.push(new HashedModuleIdsPlugin({
"hashFunction": "md5",
"hashDigest": "base64",
"hashDigestLength": 4
}));
plugins.push(new AotPlugin({
"mainPath": "main.ts",
"hostReplacementPaths": {
"environments/index.ts": "environments/index.prod.ts"
},
"exclude": [],
"tsConfigPath": "src/tsconfig.app.json"
}));
plugins.push(new UglifyJsPlugin({
"mangle": {
"screw_ie8": true
},
"compress": {
"screw_ie8": true,
"warnings": false
},
"sourceMap": false
}));
} else {
plugins.push(new AotPlugin({
"mainPath": "main.ts",
"hostReplacementPaths": {
"environments/index.ts": "environments/index.ts"
},
"exclude": [],
"tsConfigPath": "src/tsconfig.app.json",
"skipCodeGeneration": true
}));
}
return plugins;
}
module.exports = {
"devtool": "source-map",
"externals": {
"electron": "require('electron')",
"child_process": "require('child_process')",
"crypto": "require('crypto')",
"events": "require('events')",
"fs": "require('fs')",
"http": "require('http')",
"https": "require('https')",
"assert": "require('assert')",
"dns": "require('dns')",
"net": "require('net')",
"os": "require('os')",
"path": "require('path')",
"querystring": "require('querystring')",
"readline": "require('readline')",
"repl": "require('repl')",
"stream": "require('stream')",
"string_decoder": "require('string_decoder')",
"url": "require('url')",
"util": "require('util')",
"zlib": "require('zlib')"
},
"resolve": {
"extensions": [
".ts",
".js",
".scss",
".json"
],
"aliasFields": [],
"alias": { // WORKAROUND See. angular-cli/issues/5433
"environments": isProd ? path.resolve(__dirname, 'src/environments/index.prod.ts') : path.resolve(__dirname, 'src/environments/index.ts')
},
"modules": [
"./node_modules"
]
},
"resolveLoader": {
"modules": [
"./node_modules"
]
},
"entry": {
"main": [
"./src/main.ts"
],
"polyfills": [
"./src/polyfills.ts"
],
"styles": [
"./src/styles.scss"
]
},
"output": {
"path": path.join(process.cwd(), "dist"),
"filename": "[name].bundle.js",
"chunkFilename": "[id].chunk.js"
},
"module": {
"rules": [
{
"enforce": "pre",
"test": /\.(js|ts)$/,
"loader": "source-map-loader",
"exclude": [
/\/node_modules\//,
path.join(__dirname, 'node_modules', '@angular/compiler')
]
},
{
"test": /\.html$/,
"loader": "html-loader"
},
{
"test": /\.(eot|svg)$/,
"loader": "file-loader?name=[name].[hash:20].[ext]"
},
{
"test": /\.(jpg|png|gif|otf|ttf|woff|woff2|cur|ani)$/,
"loader": "url-loader?name=[name].[hash:20].[ext]&limit=10000"
},
{
"exclude": [
path.join(process.cwd(), "src/styles.scss")
],
"test": /\.css$/,
"loaders": [
"exports-loader?module.exports.toString()",
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader"
]
},
{
"exclude": [
path.join(process.cwd(), "src/styles.scss")
],
"test": /\.scss$|\.sass$/,
"loaders": [
"exports-loader?module.exports.toString()",
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader",
"sass-loader"
]
},
{
"exclude": [
path.join(process.cwd(), "src/styles.scss")
],
"test": /\.less$/,
"loaders": [
"exports-loader?module.exports.toString()",
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader",
"less-loader"
]
},
{
"exclude": [
path.join(process.cwd(), "src/styles.scss")
],
"test": /\.styl$/,
"loaders": [
"exports-loader?module.exports.toString()",
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader",
"stylus-loader?{\"sourceMap\":false,\"paths\":[]}"
]
},
{
"include": [
path.join(process.cwd(), "src/styles.scss")
],
"test": /\.css$/,
"loaders": ExtractTextPlugin.extract({
"use": [
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader"
],
"fallback": "style-loader",
"publicPath": ""
})
},
{
"include": [
path.join(process.cwd(), "src/styles.scss")
],
"test": /\.scss$|\.sass$/,
"loaders": ExtractTextPlugin.extract({
"use": [
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader",
"sass-loader"
],
"fallback": "style-loader",
"publicPath": ""
})
},
{
"include": [
path.join(process.cwd(), "src/styles.scss")
],
"test": /\.less$/,
"loaders": ExtractTextPlugin.extract({
"use": [
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader",
"less-loader"
],
"fallback": "style-loader",
"publicPath": ""
})
},
{
"include": [
path.join(process.cwd(), "src/styles.scss")
],
"test": /\.styl$/,
"loaders": ExtractTextPlugin.extract({
"use": [
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader",
"stylus-loader?{\"sourceMap\":false,\"paths\":[]}"
],
"fallback": "style-loader",
"publicPath": ""
})
},
{
"test": /\.ts$/,
"loader": "@ngtools/webpack"
}
]
},
"plugins": getPlugins(),
"node": {
fs: "empty",
global: true,
crypto: "empty",
tls: "empty",
net: "empty",
process: true,
module: false,
clearImmediate: false,
setImmediate: false,
__dirname: false,
__filename: false
}
};