Fixed conflicts

This commit is contained in:
Aleksander Rem 2022-09-20 00:17:20 +02:00
commit 8473c648b0
89 changed files with 35960 additions and 25967 deletions

54
.eslintrc.json Normal file
View file

@ -0,0 +1,54 @@
{
"root": true,
"ignorePatterns": [
"projects/**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"tsconfig.json",
"e2e/tsconfig.json"
],
"createDefaultProgram": true
},
"extends": [
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
"@angular-eslint/component-selector": [
"error",
{
"prefix": "app",
"style": "kebab-case",
"type": "element"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"prefix": "app",
"style": "camelCase",
"type": "attribute"
}
],
"@angular-eslint/no-empty-lifecycle-method": "off"
}
},
{
"files": [
"*.html"
],
"extends": [
"plugin:@angular-eslint/template/recommended"
],
"rules": {
"@angular-eslint/template/eqeqeq": "off"
}
}
]
}

View file

@ -7,7 +7,7 @@ on:
jobs:
# Release draft and share app version via package.json
pre_build:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
outputs:
output1: ${{ steps.release_drafter.outputs.upload_url }}
output2: ${{ steps.package-version.outputs.current-version }}
@ -38,17 +38,17 @@ jobs:
strategy:
matrix:
include:
- os: ubuntu-latest
- os: ubuntu-20.04
artifact_name: checksums
asset_name: checksums
app_ext: AppImage
app_os: linux
- os: macos-latest
- os: macos-11
artifact_name: checksums
asset_name: checksums
app_ext: dmg
app_os: mac
- os: windows-latest
- os: windows-2022
artifact_name: checksums
asset_name: checksums
app_ext: exe
@ -60,12 +60,13 @@ jobs:
uses: actions/checkout@v1
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: 14
node-version: 16
cache: 'npm'
- name: Install APT dependencies
if: matrix.os == 'ubuntu-latest'
if: matrix.os == 'ubuntu-20.04'
run: |
sudo apt-get update
sudo apt-get install build-essential git -y
@ -74,35 +75,13 @@ jobs:
- name: Install and Build Desktop App
run: |
npm install -g @angular/cli
npm install
npm run desktop:build
- name: Temporarily fix electron-builder
# https://github.com/electron-userland/electron-builder/issues/4176
if: matrix.os != 'macos-latest'
- name: Build Electron app
run: |
sed -i 's/\^\[\\w/\^\[.\\w/g' node_modules/builder-util/out/util.js
shell: bash
- name: Temporarily fix electron-builder (MacOS)
# https://github.com/electron-userland/electron-builder/issues/4176
if: matrix.os == 'macos-latest'
run: |
sed -i '' 's/\^\[\\w/\^\[.\\w/g' node_modules/builder-util/out/util.js
shell: bash
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
# GitHub token, automatically provided to the action
# (No need to define this secret in the repo settings)
github_token: ${{ secrets.GITHUB_TOKEN }}
# is already built
skip_build: true
release: false
args: "-p never" # Do not publish, done in the next step instead
npm run desktop:local
- name: Create Hashes
if: startsWith(github.ref, 'refs/tags/')
@ -116,27 +95,27 @@ jobs:
shell: bash
- name: Rename file paths in .yml (Linux)
if: matrix.os == 'ubuntu-latest' && startsWith(github.ref, 'refs/tags/')
if: matrix.os == 'ubuntu-20.04' && startsWith(github.ref, 'refs/tags/')
run: |
sed -i '/.AppImage/ s//-Linux.AppImage/g' desktop-app/build/latest-linux.yml | bash
shell: bash
# Special sed command for mac
- name: Rename file paths in .yml (Mac)
if: matrix.os == 'macos-latest' && startsWith(github.ref, 'refs/tags/')
if: matrix.os == 'macos-11' && startsWith(github.ref, 'refs/tags/')
run: |
sed -i '' '/.dmg/ s//-Mac.dmg/g' desktop-app/build/latest-mac.yml
shell: bash
- name: Rename file paths in .yml (Windows)
if: matrix.os == 'windows-latest' && startsWith(github.ref, 'refs/tags/')
if: matrix.os == 'windows-2022' && startsWith(github.ref, 'refs/tags/')
run: |
sed -i '/.exe/ s//-Windows.exe/g' desktop-app/build/latest.yml | bash
shell: bash
# Upload binaries separately for better control which release draft they go into
- name: Upload Binaries Linux
if: matrix.os == 'ubuntu-latest' && startsWith(github.ref, 'refs/tags/')
if: matrix.os == 'ubuntu-20.04' && startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -147,7 +126,7 @@ jobs:
asset_content_type: application/octet-stream
- name: Upload Binaries Mac
if: matrix.os == 'macos-latest' && startsWith(github.ref, 'refs/tags/')
if: matrix.os == 'macos-11' && startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -158,7 +137,7 @@ jobs:
asset_content_type: application/octet-stream
- name: Upload Binaries Windows
if: matrix.os == 'windows-latest' && startsWith(github.ref, 'refs/tags/')
if: matrix.os == 'windows-2022' && startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -180,7 +159,7 @@ jobs:
asset_content_type: application/octet-stream
- name: Upload yml Linux
if: matrix.os == 'ubuntu-latest' && startsWith(github.ref, 'refs/tags/')
if: matrix.os == 'ubuntu-20.04' && startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -191,7 +170,7 @@ jobs:
asset_content_type: application/octet-stream
- name: Upload yml Mac
if: matrix.os == 'macos-latest' && startsWith(github.ref, 'refs/tags/')
if: matrix.os == 'macos-11' && startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -202,7 +181,7 @@ jobs:
asset_content_type: application/octet-stream
- name: Upload yml Windows
if: matrix.os == 'windows-latest' && startsWith(github.ref, 'refs/tags/')
if: matrix.os == 'windows-2022' && startsWith(github.ref, 'refs/tags/')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -16,7 +16,7 @@ jobs:
- name: Setup NodeJS
uses: actions/setup-node@v1
with:
node-version: 14
node-version: 16
- name: Install APT dependencies
run: |

View file

@ -12,9 +12,9 @@ jobs:
uses: actions/checkout@v1
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
uses: actions/setup-node@v2
with:
node-version: 14
node-version: '16'
- name: Install APT dependencies
run: |

1
.gitignore vendored
View file

@ -28,6 +28,7 @@
!.vscode/extensions.json
# misc
/.angular/cache
/.sass-cache
/connect.lock
/coverage

View file

@ -6,7 +6,7 @@
- Communication with the network is done via nano RPC and Websocket protocols, private or public on any nano network.
## Development Prerequisites
- [NodeJS](https://nodejs.org) v14.x + NPM v6.x
- [NodeJS](https://nodejs.org) v16.x + NPM v8.x
- Angular CLI: `npm install -g @angular/cli`
## Development Guide

View file

@ -1,5 +1,5 @@
# build the angular app
FROM node:14 AS build
FROM node:16 AS build
WORKDIR /usr/src/app
RUN apt-get update && apt-get install -y \
libudev-dev \

View file

@ -11,7 +11,6 @@
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"aot": true,
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
@ -28,27 +27,33 @@
],
"scripts": [],
"allowedCommonJsDependencies": [
"qrcode",
"bip39",
"@zxing/library",
"bignumber.js",
"nanocurrency",
"hw-app-nano",
"crypto-js",
"blakejs",
"nanocurrency-web",
"bignumber.js",
"u2f-api",
"create-hash",
"randombytes",
"pbkdf2",
"zxcvbn",
"url",
"punycode",
"querystring",
"hw-transport-webusb",
"hw-transport-web-ble"
]
"qrcode",
"bip39",
"@zxing/library",
"bignumber.js",
"nanocurrency",
"hw-app-nano",
"crypto-js",
"blakejs",
"nanocurrency-web",
"bignumber.js",
"u2f-api",
"create-hash",
"randombytes",
"pbkdf2",
"zxcvbn",
"url",
"punycode",
"querystring",
"hw-transport-webusb",
"hw-transport-web-ble"
],
"vendorChunk": true,
"extractLicenses": false,
"buildOptimizer": false,
"sourceMap": true,
"optimization": false,
"namedChunks": true
},
"configurations": {
"production": {
@ -61,9 +66,7 @@
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
@ -86,9 +89,7 @@
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
@ -99,7 +100,8 @@
}
]
}
}
},
"defaultConfiguration": ""
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
@ -140,14 +142,11 @@
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"builder": "@angular-eslint/builder:lint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
"lintFilePatterns": [
"src/**/*.ts",
"src/**/*.html"
]
}
}
@ -164,17 +163,6 @@
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "nault:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
@ -188,5 +176,8 @@
"@schematics/angular:directive": {
"prefix": "app"
}
},
"cli": {
"defaultCollection": "@angular-eslint/schematics"
}
}

View file

@ -6,15 +6,16 @@
"declaration": false,
"moduleResolution": "node",
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"allowSyntheticDefaultImports": true,
"target": "es2017",
"module": "commonjs",
"baseUrl": ".",
"typeRoots": [
"../node_modules/@types"
],
"lib": [
"es2017",
"es2020",
"dom"
]
},

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig.base.json",
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"baseUrl": "./",

37059
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -16,44 +16,43 @@
"release": "npm run desktop:build && electron-builder",
"wallet:dev": "ng serve --open",
"wallet:dev-ssl": "ng serve --ssl --open",
"wallet:build": "ng build --prod",
"wallet:build": "ng build --configuration production",
"wallet:build-desktop": "ng build --configuration=desktop --base-href ",
"desktop:compile": "cd desktop-app && tsc && cd ..",
"desktop:build": "npm run wallet:build-desktop && npm run desktop:compile",
"desktop:build-local": "npm run desktop:build && npm run desktop:local",
"desktop:dev": "npm run desktop:compile && electron desktop-app/dist/desktop-app.js",
"desktop:local": "electron-builder",
"desktop:full": "electron-builder -wml --x64",
"desktop:publish": "electron-builder -wml --x64 -p always"
"desktop:local": "electron-builder -p never"
},
"private": true,
"dependencies": {
"@angular-devkit/core": "10.0.5",
"@angular/animations": "^10.0.7",
"@angular/common": "^10.0.7",
"@angular/compiler": "^10.0.7",
"@angular/core": "^10.0.7",
"@angular/forms": "^10.0.7",
"@angular/localize": "^10.0.7",
"@angular/platform-browser": "^10.0.7",
"@angular/platform-browser-dynamic": "^10.0.7",
"@angular/router": "^10.0.7",
"@angular/service-worker": "^10.2.5",
"@ledgerhq/hw-transport": "^5.51.1",
"@ledgerhq/hw-transport-node-ble": "^6.20.0",
"@ledgerhq/hw-transport-node-hid": "^6.20.0",
"@angular-devkit/core": "13.1.2",
"@angular/animations": "^13.1.1",
"@angular/common": "^13.1.1",
"@angular/compiler": "^13.1.1",
"@angular/core": "^13.1.1",
"@angular/forms": "^13.1.1",
"@angular/localize": "^13.1.1",
"@angular/platform-browser": "^13.1.1",
"@angular/platform-browser-dynamic": "^13.1.1",
"@angular/router": "^13.1.1",
"@angular/service-worker": "^13.1.1",
"@ledgerhq/hw-transport": "^6.27.1",
"@ledgerhq/hw-transport-node-ble": "^6.27.1",
"@ledgerhq/hw-transport-node-hid": "^6.27.1",
"@ledgerhq/hw-transport-u2f": "^5.34.0",
"@ledgerhq/hw-transport-web-ble": "^5.51.1",
"@ledgerhq/hw-transport-webhid": "^5.51.1",
"@ledgerhq/hw-transport-webusb": "^5.53.1",
"@ledgerhq/logs": "^5.50.0",
"@ng-bootstrap/ng-bootstrap": "^7.0.0",
"@ngneat/transloco": "^2.22.0",
"@ledgerhq/hw-transport-web-ble": "^6.27.1",
"@ledgerhq/hw-transport-webhid": "^6.27.1",
"@ledgerhq/hw-transport-webusb": "^6.27.1",
"@ledgerhq/logs": "^6.10.0",
"@ng-bootstrap/ng-bootstrap": "^11.0.0",
"@ngneat/transloco": "^3.1.1",
"@types/crypto-js": "^3.1.38",
"@types/w3c-web-hid": "^1.0.2",
"@types/w3c-web-usb": "^1.0.5",
"@zxing/ngx-scanner": "^3.0.0",
"angular-password-strength-meter": "^3.0.0",
"@zxing/browser": "^0.0.10",
"@zxing/library": "^0.18.6",
"@zxing/ngx-scanner": "^3.4.0",
"babel-polyfill": "^6.26.0",
"babel-runtime": "^6.26.0",
"bignumber.js": "^5.0.0",
@ -77,37 +76,44 @@
"safe-buffer": "^5.2.1",
"tslib": "^2.0.0",
"tweetnacl": "^1.0.0",
"zone.js": "~0.10.3"
"url": "^0.11.0",
"usb": "^2.0.3",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1000.5",
"@angular/cli": "^10.0.5",
"@angular/compiler-cli": "^10.0.7",
"@angular/language-service": "^10.0.7",
"@angular-devkit/build-angular": "^13.1.2",
"@angular-eslint/builder": "13.2.1",
"@angular-eslint/eslint-plugin": "13.2.1",
"@angular-eslint/eslint-plugin-template": "13.2.1",
"@angular-eslint/schematics": "13.2.1",
"@angular-eslint/template-parser": "13.2.1",
"@angular/cli": "^13.1.2",
"@angular/compiler-cli": "^13.1.1",
"@angular/language-service": "^13.1.1",
"@types/bip39": "^2.4.0",
"@types/jasmine": "~2.5.53",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.2",
"@types/ledgerhq__hw-transport": "^4.21.3",
"@types/node": "^12.20.39",
"@types/qrcode": "^0.8.1",
"codelyzer": "^6.0.0",
"@typescript-eslint/eslint-plugin": "5.17.0",
"@typescript-eslint/parser": "5.17.0",
"electron": "^9.4.0",
"electron-builder": "^22.7.0",
"jasmine-core": "~3.5.0",
"electron-builder": "^22.14.5",
"eslint": "^8.12.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~5.0.0",
"karma": "~6.3.9",
"karma-chrome-launcher": "~3.1.0",
"karma-cli": "~2.0.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~3.3.0",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"protractor": "~7.0.0",
"ts-node": "~3.2.0",
"tslint": "~6.1.3",
"typescript": "~3.9.7",
"uikit": "^3.0.0-beta.40",
"worker-loader": "^2.0.0",
"zxcvbn3": "^0.1.1"
"typescript": "~4.5.4",
"uikit": "^3.9.4",
"worker-loader": "^3.0.8"
},
"build": {
"appId": "cc.nault",

View file

@ -52,7 +52,7 @@ const routes: Routes = [
@NgModule({
imports: [
// On the desktop apps, use hashes so it works properly using only index.html
RouterModule.forRoot(routes, { useHash: environment.desktop }),
RouterModule.forRoot(routes, { useHash: environment.desktop, relativeLinkResolution: 'legacy' }),
],
declarations: [],
exports: [RouterModule]

View file

@ -1,24 +1,24 @@
import { TestBed, async } from '@angular/core/testing';
import { TestBed, waitForAsync } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
it('should create the app', waitForAsync(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
it(`should have as title 'app'`, waitForAsync(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
it('should render title in a h1 tag', waitForAsync(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;

View file

@ -57,7 +57,6 @@ import { InstallWidgetComponent } from './components/install-widget/install-widg
import { QrModalComponent } from './components/qr-modal/qr-modal.component';
import { QrModalService } from './services/qr-modal.service';
import { NgbModule, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { PasswordStrengthMeterModule } from 'angular-password-strength-meter';
import {MusigService} from './services/musig.service';
// QR code module
@ -71,6 +70,7 @@ import { MultisigComponent } from './components/multisig/multisig.component';
import { KeygeneratorComponent } from './components/keygenerator/keygenerator.component';
import { NanoTransactionMobileComponent } from './components/helpers/nano-transaction-mobile/nano-transaction-mobile.component';
import { TranslocoRootModule } from './transloco/transloco-root.module';
import { NoPaddingZerosPipe } from './pipes/no-padding-zeros.pipe';
@NgModule({
declarations: [
@ -111,6 +111,7 @@ import { TranslocoRootModule } from './transloco/transloco-root.module';
MultisigComponent,
KeygeneratorComponent,
NanoTransactionMobileComponent,
NoPaddingZerosPipe
],
imports: [
BrowserModule,
@ -121,7 +122,6 @@ import { TranslocoRootModule } from './transloco/transloco-root.module';
ClipboardModule,
ZXingScannerModule,
NgbModule,
PasswordStrengthMeterModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production && !environment.desktop }),
TranslocoRootModule,
],
@ -148,6 +148,7 @@ import { TranslocoRootModule } from './transloco/transloco-root.module';
QrModalService,
DeeplinkService,
MusigService,
NoPaddingZerosPipe
],
bootstrap: [AppComponent]
})

View file

@ -519,7 +519,7 @@
</div>
<!-- Modal for remote receive incoming -->
<div id="receive-modal" uk-modal>
<div class="modal-position-bottom" id="receive-modal" uk-modal>
<div class="uk-modal-dialog uk-modal-body modal-qr">
<button class="uk-modal-close-default" type="button" uk-close></button>
<div class="uk-modal-header">
@ -547,7 +547,7 @@
</div>
<!-- Modal for creating send and change block for remote signing-->
<div id="block-modal" uk-modal>
<div class="modal-position-bottom" id="block-modal" uk-modal>
<div class="uk-modal-dialog uk-modal-body modal-block">
<button class="uk-modal-close-default" type="button" uk-close></button>
<div class="uk-modal-header">
@ -678,7 +678,7 @@
</div>
</div>
<div id="qr-code-modal" uk-modal>
<div class="modal-position-bottom" id="qr-code-modal" uk-modal>
<div class="uk-modal-dialog uk-margin-auto-vertical">
<button class="uk-modal-close-default" type="button" uk-close></button>
<div class="uk-modal-body">

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { AccountDetailsComponent } from './account-details.component';
@ -6,7 +6,7 @@ describe('AccountDetailsComponent', () => {
let component: AccountDetailsComponent;
let fixture: ComponentFixture<AccountDetailsComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ AccountDetailsComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { AccountsComponent } from './accounts.component';
@ -6,7 +6,7 @@ describe('AccountsComponent', () => {
let component: AccountsComponent;
let fixture: ComponentFixture<AccountsComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ AccountsComponent ]
})

View file

@ -184,8 +184,8 @@
</div>
</div>
<div class="uk-card-footer uk-text-right@s nlt-button-group">
<button class="uk-button uk-button-danger" (click)="cancelNewAddress()">{{ 'general.cancel' | transloco }}</button>
<button class="uk-button uk-button-primary" (click)="saveNewAddress()">{{ 'general.save' | transloco }}</button>
<button class="uk-button uk-button-danger uk-width-1-1@s uk-width-auto@m" (click)="cancelNewAddress()">{{ 'general.cancel' | transloco }}</button>
<button class="uk-button uk-button-primary uk-width-1-1@s uk-width-auto@m" (click)="saveNewAddress()">{{ 'general.save' | transloco }}</button>
</div>
</div>
</div>
@ -231,9 +231,9 @@
<span *ngIf="!addressBookShowQRExport">{{ 'address-book.you-can-still-import-your-address-book-by-using-the-url' | transloco }}</span>
<br><br>
<input type="text" class="uk-input" style="max-width: 750px;" value="{{ addressBookQRExportUrl }}"><br>
<div class="nlt-button-group uk-margin-small-top">
<button ngxClipboard [cbContent]="addressBookQRExportUrl" (cbOnSuccess)="notificationService.sendSuccess('Address book export copied to clipboard!')" class="uk-button uk-button-secondary" style="margin-left: 0;">{{ 'general.copy-to-clipboard' | transloco }}</button>
<button (click)="exportAddressBookToFile()" class="uk-button uk-button-primary">{{ 'address-book.export-as-file' | transloco }}</button>
<div class="nlt-button-group">
<button ngxClipboard [cbContent]="addressBookQRExportUrl" (cbOnSuccess)="notificationService.sendSuccess('Address book export copied to clipboard!')" class="uk-button uk-button-secondary uk-width-1-1@s uk-width-auto@m uk-margin-small-top" style="margin-left: 0;">{{ 'general.copy-to-clipboard' | transloco }}</button>
<button (click)="exportAddressBookToFile()" class="uk-button uk-button-primary uk-width-1-1@s uk-width-auto@m uk-margin-small-top">{{ 'address-book.export-as-file' | transloco }}</button>
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { AddressBookComponent } from './address-book.component';
@ -6,7 +6,7 @@ describe('AddressBookComponent', () => {
let component: AddressBookComponent;
let fixture: ComponentFixture<AddressBookComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ AddressBookComponent ]
})

View file

@ -423,24 +423,20 @@ export class AddressBookComponent implements OnInit, AfterViewInit, OnDestroy {
// Check for iOS, which is weird with saving files
const iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, fileName);
const elem = window.document.createElement('a');
const objUrl = window.URL.createObjectURL(blob);
if (iOS) {
elem.href = `data:attachment/file,${JSON.stringify(exportData)}`;
} else {
const elem = window.document.createElement('a');
const objUrl = window.URL.createObjectURL(blob);
if (iOS) {
elem.href = `data:attachment/file,${JSON.stringify(exportData)}`;
} else {
elem.href = objUrl;
}
elem.download = fileName;
document.body.appendChild(elem);
elem.click();
setTimeout(function() {
document.body.removeChild(elem);
window.URL.revokeObjectURL(objUrl);
}, 200);
elem.href = objUrl;
}
elem.download = fileName;
document.body.appendChild(elem);
elem.click();
setTimeout(function() {
document.body.removeChild(elem);
window.URL.revokeObjectURL(objUrl);
}, 200);
}
}

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ChangeRepWidgetComponent } from './change-rep-widget.component';
@ -6,7 +6,7 @@ describe('ChangeRepWidgetComponent', () => {
let component: ChangeRepWidgetComponent;
let fixture: ComponentFixture<ChangeRepWidgetComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ChangeRepWidgetComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ConfigureAppComponent } from './configure-app.component';
@ -6,7 +6,7 @@ describe('ConfigureAppComponent', () => {
let component: ConfigureAppComponent;
let fixture: ComponentFixture<ConfigureAppComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ConfigureAppComponent ]
})

View file

@ -348,7 +348,13 @@ export class ConfigureAppComponent implements OnInit {
if (resaveWallet && newStorage === this.storageOptions[1].value) {
const UIkit = window['UIkit'];
try {
await UIkit.modal.confirm('<p class="uk-alert uk-alert-danger"><br><span class="uk-flex"><span uk-icon="icon: warning; ratio: 3;" class="uk-align-center"></span></span><span style="font-size: 18px;">' + this.translocoService.translate('configure-app.you-are-about-to-disable-storage-of-all-wallet-data-which') + '</span><br><br><b style="font-size: 18px;">' + this.translocoService.translate('reset-wallet.before-continuing-make-sure-you-have-saved-the-nano-seed') + '</b><br><br><span style="font-size: 18px;"><b>' + this.translocoService.translate('reset-wallet.you-will-not-be-able-to-recover-the-funds-without-a-backup') + '</b></span></p><br>');
await UIkit.modal.confirm(
`<p class="uk-alert uk-alert-danger"><br><span class="uk-flex"><span uk-icon="icon: warning; ratio: 3;" class="uk-align-center"></span></span>
<span style="font-size: 18px;">
${ this.translocoService.translate('configure-app.you-are-about-to-disable-storage-of-all-wallet-data-which') }
</span><br>
${ this.walletService.isConfigured() ? '<br><b style="font-size: 18px;">' + this.translocoService.translate('reset-wallet.before-continuing-make-sure-you-have-saved-the-nano-seed') + '</b><br><br><span style="font-size: 18px;"><b>' + this.translocoService.translate('reset-wallet.you-will-not-be-able-to-recover-the-funds-without-a-backup') + '</b></span></p><br>' : '' }`
);
} catch (err) {
// pressing cancel, reset storage setting and interrupt
this.selectedStorage = this.storageOptions[0].value;

View file

@ -508,7 +508,7 @@
<div uk-grid>
<div class="uk-width-1-2@m">
<input type="password" class="uk-input" [(ngModel)]="walletPasswordModel" placeholder="New Wallet Password">
<password-strength-meter *ngIf="walletPasswordModel.length > 0" [password]="walletPasswordModel" [enableFeedback]="true" [minPasswordLength]="6"></password-strength-meter>
<!-- <password-strength-meter *ngIf="walletPasswordModel.length > 0" [password]="walletPasswordModel" [enableFeedback]="true" [minPasswordLength]="6"></password-strength-meter> -->
<span class="password-helper" *ngIf="walletPasswordModel.length > 0 && walletPasswordModel.length < 6">{{ 'configure-wallet.set-wallet-password.errors.password-must-be-at-least-x-characters-long' | transloco: { minCharacters: 6 } }}</span>
<span class="password-helper" *ngIf="walletPasswordConfirmModel.length >= 6 && walletPasswordModel !== walletPasswordConfirmModel">{{ 'configure-wallet.set-wallet-password.errors.passwords-do-not-match' | transloco }}</span>
</div>

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ConfigureWalletComponent } from './configure-wallet.component';
@ -6,7 +6,7 @@ describe('ConfigureWalletComponent', () => {
let component: ConfigureWalletComponent;
let fixture: ComponentFixture<ConfigureWalletComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ConfigureWalletComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ConverterComponent } from './converter.component';
@ -6,7 +6,7 @@ describe('ConverterComponent', () => {
let component: ConverterComponent;
let fixture: ComponentFixture<ConverterComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ConverterComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NanoAccountIdComponent } from './nano-account-id.component';
@ -6,7 +6,7 @@ describe('NanoAccountIdComponent', () => {
let component: NanoAccountIdComponent;
let fixture: ComponentFixture<NanoAccountIdComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ NanoAccountIdComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NanoIdenticonComponent } from './nano-identicon.component';
@ -6,7 +6,7 @@ describe('NanoIdenticonComponent', () => {
let component: NanoIdenticonComponent;
let fixture: ComponentFixture<NanoIdenticonComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ NanoIdenticonComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NanoTransactionMobileComponent } from './nano-transaction-mobile.component';
@ -6,7 +6,7 @@ describe('NanoTransactionMobileComponent', () => {
let component: NanoTransactionMobileComponent;
let fixture: ComponentFixture<NanoTransactionMobileComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ NanoTransactionMobileComponent ]
})

View file

@ -65,8 +65,8 @@
<div class="uk-card-footer">
<div uk-grid>
<div class="nlt-button-group uk-width-1-1 uk-text-right">
<button routerLink="/address-book" class="uk-button uk-button-danger">Cancel</button>
<button (click)="confirmImport()" class="uk-button uk-button-primary">Import Entries</button>
<button routerLink="/address-book" class="uk-button uk-button-danger uk-width-1-1@s uk-width-auto@m">Cancel</button>
<button (click)="confirmImport()" class="uk-button uk-button-primary uk-width-1-1@s uk-width-auto@m">Import Entries</button>
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ImportAddressBookComponent } from './import-address-book.component';
@ -6,7 +6,7 @@ describe('ImportAddressBookComponent', () => {
let component: ImportAddressBookComponent;
let fixture: ComponentFixture<ImportAddressBookComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ImportAddressBookComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ImportWalletComponent } from './import-wallet.component';
@ -6,7 +6,7 @@ describe('ImportWalletComponent', () => {
let component: ImportWalletComponent;
let fixture: ComponentFixture<ImportWalletComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ImportWalletComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { InstallWidgetComponent } from './install-widget.component';
@ -6,7 +6,7 @@ describe('InstallWidgetComponent', () => {
let component: InstallWidgetComponent;
let fixture: ComponentFixture<InstallWidgetComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ InstallWidgetComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { KeygeneratorComponent } from './keygenerator.component';
@ -6,7 +6,7 @@ describe('KeygeneratorComponent', () => {
let component: KeygeneratorComponent;
let fixture: ComponentFixture<KeygeneratorComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ KeygeneratorComponent ]
})

View file

@ -6,7 +6,7 @@ import {NotificationService} from '../../services/notification.service';
@Component({
selector: 'app-keygenerator',
templateUrl: './keygenerator.component.html',
styleUrls: ['./keygenerator.component.less']
styleUrls: ['./keygenerator.component.css']
})
export class KeygeneratorComponent implements OnInit {
seed = '';

View file

@ -116,8 +116,8 @@
</div>
</div>
<div class="uk-card-footer uk-text-right@s nlt-button-group">
<button class="uk-button uk-button-danger" (click)="cancelNewRep()">Cancel</button>
<button class="uk-button uk-button-primary" (click)="saveNewRepresentative()">Save</button>
<button class="uk-button uk-button-danger uk-width-1-1@s uk-width-auto@m" (click)="cancelNewRep()">Cancel</button>
<button class="uk-button uk-button-primary uk-width-1-1@s uk-width-auto@m" (click)="saveNewRepresentative()">Save</button>
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ManageRepresentativesComponent } from './manage-representatives.component';
@ -6,7 +6,7 @@ describe('ManageRepresentativesComponent', () => {
let component: ManageRepresentativesComponent;
let fixture: ComponentFixture<ManageRepresentativesComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ManageRepresentativesComponent ]
})

View file

@ -11,7 +11,7 @@
<div uk-grid>
<div class="uk-width-1-2@s">
<input class="uk-input" [(ngModel)]="newPassword" placeholder="New Password" type="password">
<password-strength-meter *ngIf="newPassword.length > 0" [password]="newPassword" [enableFeedback]="true" [minPasswordLength]="6"></password-strength-meter>
<!-- <password-strength-meter *ngIf="newPassword.length > 0" [password]="newPassword" [enableFeedback]="true" [minPasswordLength]="6"></password-strength-meter> -->
<span class="password-helper" *ngIf="newPassword.length > 0 && newPassword.length < 6">Password must be at least 6 characters long</span>
<span class="password-helper" *ngIf="confirmPassword.length >= 6 && newPassword !== confirmPassword">Passwords do not match!</span>
</div>

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ManageWalletComponent } from './manage-wallet.component';
@ -6,7 +6,7 @@ describe('ManageWalletComponent', () => {
let component: ManageWalletComponent;
let fixture: ComponentFixture<ManageWalletComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ManageWalletComponent ]
})

View file

@ -155,31 +155,27 @@ export class ManageWalletComponent implements OnInit {
// Check for iOS, which is weird with saving files
const iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, fileName);
} else {
const elem = window.document.createElement('a');
const objUrl = window.URL.createObjectURL(blob);
if (iOS) {
switch (type) {
case 'json':
elem.href = `data:attachment/file,${JSON.stringify(exportData)}`;
break;
case 'csv':
elem.href = `data:attachment/file,${csvFile}`;
break;
}
} else {
elem.href = objUrl;
const elem = window.document.createElement('a');
const objUrl = window.URL.createObjectURL(blob);
if (iOS) {
switch (type) {
case 'json':
elem.href = `data:attachment/file,${JSON.stringify(exportData)}`;
break;
case 'csv':
elem.href = `data:attachment/file,${csvFile}`;
break;
}
elem.download = fileName;
document.body.appendChild(elem);
elem.click();
setTimeout(function() {
document.body.removeChild(elem);
window.URL.revokeObjectURL(objUrl);
}, 200);
} else {
elem.href = objUrl;
}
elem.download = fileName;
document.body.appendChild(elem);
elem.click();
setTimeout(function() {
document.body.removeChild(elem);
window.URL.revokeObjectURL(objUrl);
}, 200);
}
async exportToFile() {

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { MultisigComponent } from './multisig.component';
@ -6,7 +6,7 @@ describe('MultisigComponent', () => {
let component: MultisigComponent;
let fixture: ComponentFixture<MultisigComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ MultisigComponent ]
})

View file

@ -9,7 +9,7 @@ import { MusigService } from '../../services/musig.service';
@Component({
selector: 'app-multisig',
templateUrl: './multisig.component.html',
styleUrls: ['./multisig.component.less']
styleUrls: ['./multisig.component.css']
})
export class MultisigComponent implements OnInit {
accountAdd = '';

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NotificationsComponent } from './notifications.component';
@ -6,7 +6,7 @@ describe('NotificationsComponent', () => {
let component: NotificationsComponent;
let fixture: ComponentFixture<NotificationsComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ NotificationsComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { QrGeneratorComponent } from './qr-generator.component';
@ -6,7 +6,7 @@ describe('QrGeneratorComponent', () => {
let component: QrGeneratorComponent;
let fixture: ComponentFixture<QrGeneratorComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ QrGeneratorComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { QrModalComponent } from './qr-modal.component';
@ -6,7 +6,7 @@ describe('QrModalComponent', () => {
let component: QrModalComponent;
let fixture: ComponentFixture<QrModalComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ QrModalComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { QrScanComponent } from './qr-scan.component';
@ -6,7 +6,7 @@ describe('AddressBookComponent', () => {
let component: QrScanComponent;
let fixture: ComponentFixture<QrScanComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ QrScanComponent ]
})

View file

@ -1,3 +1,18 @@
.merchant-mode-text-full {
display: none;
}
.merchant-mode-text-short {
display: inline-block;
}
@media (min-width: 460px) {
.merchant-mode-text-full {
display: inline-block;
}
.merchant-mode-text-short {
display: none;
}
}
.label-block {
margin-left: 10px;
margin-bottom: 10px;
@ -63,9 +78,6 @@
max-width: 280px;
margin: 25px auto 0 auto;
}
.copy-address-button {
margin-top: 25px;
}
@media (max-width: 959px) {
.qr-code {
max-width: 250px;
@ -162,3 +174,116 @@
opacity: 1;
}
}
.merchant-mode-overlay {
background-color: #FFF;
z-index: 1050; /* above notifications */
padding: 15px !important;
}
.merchant-mode-contents {
box-sizing: border-box;
height: 100%;
padding: 20px;
}
@media (max-width: 699px) {
.merchant-mode-contents {
padding: 10px;
}
}
.merchant-mode-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 25px;
}
@media (max-width: 699px) {
.merchant-mode-header {
flex-direction: column;
padding-left: 0;
}
}
@media (min-width: 1200px) {
.merchant-mode-header {
position: fixed;
width: calc(100% - 86px);
}
}
.merchant-mode-exit .label {
font-size: 1.2em;
}
.merchant-mode-logo {
width: 200px;
height: 85px;
background: url('../../../assets/img/nault-logo.svg');
background-size: contain;
background-repeat: no-repeat;
flex-shrink: 0;
}
.merchant-mode-exit {
cursor: pointer;
padding: 6px 23px 8px 20px;
border: 2px solid transparent;
border-radius: 50px;
transition: border-color 100ms ease-in-out;
}
.merchant-mode-exit:hover {
border-color: #676686AA;
}
.merchant-centered-container {
padding-bottom: 170px;
max-width: 500px;
}
@media (min-width: 1200px) {
.merchant-centered-container {
padding-bottom: 0;
}
}
.merchant-mode-icon-qr-code {
width: 19px;
height: 19px;
margin-right: 10px;
background-color: currentcolor;
-webkit-mask-image: url('assets/img/qr-code.svg');
mask-image: url('assets/img/qr-code.svg');
}
.merchant-mode-qr-code {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 290px;
height: 290px;
border-radius: 20px;
border: 2px solid #19191B;
background-color: #FFF;
}
.merchant-mode-amount-integer,
.merchant-mode-amount-fractional,
.merchant-mode-currency-name {
font-family: 'Montserrat', Arial, Helvetica, sans-serif;
font-size: 34px;
}
.merchant-mode-amount-integer {
font-weight: 700;
}
.merchant-mode-amount-fractional {
font-weight: 500;
}
.merchant-mode-currency-name {
font-weight: 400;
}
.merchant-mode-currency-margin {
margin-left: 10px;
}

View file

@ -1,7 +1,24 @@
<div class="uk-animation-slide-left-small" uk-grid>
<div class="uk-width-1-1">
<h2 class="uk-heading-divider">Receive Nano</h2>
<ng-template #switchToMerchantModeButton>
<button
class="uk-width-1-1 uk-width-auto@s uk-button uk-button-primary uk-text-center nlt-icon-button nlt-button-green"
type="button"
(click)="merchantModeEnable()"
>
<span class="nlt-icon" uk-icon="icon: cart;"></span>
<span class="merchant-mode-text-full">Switch to Merchant Mode</span>
<span class="merchant-mode-text-short">Merchant Mode</span>
</button>
</ng-template>
<div class="uk-margin-bottom uk-flex uk-flex-between">
<h2 class="uk-flex-1 uk-heading-divider uk-margin-remove">Receive Nano</h2>
<div class="uk-flex-none uk-visible@s uk-flex uk-flex-top uk-margin-medium-left">
<ng-container *ngTemplateOutlet="switchToMerchantModeButton"></ng-container>
</div>
</div>
<div class="uk-card uk-card-default uk-margin">
<div class="uk-card-body">
@ -53,14 +70,15 @@
<div style="padding-top: 100%"></div>
</div>
</ng-template>
<div *ngIf="(pendingAccountModel !== '0')">
<div class="uk-flex uk-flex-center uk-flex-middle uk-text-center qr-address">
<div>
<div class="uk-flex uk-flex-center uk-flex-middle uk-text-center qr-address" *ngIf="(pendingAccountModel !== '0')">
<app-nano-account-id [accountID]="pendingAccountModel" middle="break" class="nano-address-monospace uk-width-auto" style="max-width: 90%;"></app-nano-account-id>
<a class="span-icon hide-on-small-viewports" ngxClipboard [cbContent]="pendingAccountModel" (cbOnSuccess)="copied()" uk-icon="icon: copy" title="Copy Account Address" uk-tooltip></a>
</div>
<div class="only-on-small-viewports uk-text-center">
<div class="uk-margin-medium-top only-on-small-viewports nlt-button-group uk-flex uk-flex-column uk-flex-middle">
<button
class="copy-address-button uk-width-1-1 uk-width-4-5@s uk-button uk-button-primary uk-text-center"
*ngIf="(pendingAccountModel !== '0')"
class="uk-width-1-1 uk-width-4-5@s uk-button uk-button-primary uk-text-center nlt-icon-button"
[class.nlt-button-success]="recentlyCopiedAccountAddress"
[class.uk-disabled]="recentlyCopiedAccountAddress"
type="button"
@ -68,8 +86,12 @@
[cbContent]="pendingAccountModel"
(cbOnSuccess)="copiedAccountAddress()"
>
<span class="nlt-icon" uk-icon="icon: copy;"></span>
{{ recentlyCopiedAccountAddress ? 'Copied!' : 'Copy address' }}
</button>
<div class="uk-hidden@s uk-width-1-1 uk-flex">
<ng-container *ngTemplateOutlet="switchToMerchantModeButton"></ng-container>
</div>
</div>
</div>
</div>
@ -281,3 +303,264 @@
</div>
</div>
<div class="merchant-mode-overlay" id="merchant-mode-modal" uk-modal>
<div class="merchant-mode-contents uk-flex uk-flex-column uk-flex-middle">
<div
class="uk-width-1-1 merchant-mode-header"
[class.uk-margin-medium-bottom]="inMerchantModeQR === false"
[class.uk-margin-bottom]="inMerchantModeQR === true"
>
<div class="merchant-mode-logo"></div>
<div
class="merchant-mode-exit uk-flex uk-flex-middle"
[class.uk-visible@s]="(inMerchantModeQR === true)"
(click)="inMerchantModeQR ? merchantModeHideQR() : merchantModeDisable()"
>
<span uk-icon="icon: close; ratio: 1.4;" class="uk-margin-small-right" style="margin-top: 2px;"></span>
<span class="label">{{ inMerchantModeQR ? 'Cancel Payment' : 'Exit Merchant Mode' }}</span>
</div>
</div>
<div class="merchant-centered-container uk-flex-1 uk-width-1-1 uk-flex uk-flex-column uk-flex-center uk-flex-middle uk-text-center">
<ng-container *ngIf="(inMerchantModePaymentComplete === false) && (inMerchantModeQR === false) && (pendingAccountModel === '0')">
<div class="uk-width-1-1 uk-card uk-card-default uk-margin-bottom">
<div class="uk-card-body">
<p class="uk-text-large">Select the <span class="uk-text-primary">destination account</span></p>
<select id="form-horizontal-select" class="uk-select" [(ngModel)]="pendingAccountModel" (change)="onSelectedAccountChange(pendingAccountModel)">
<option [value]="0"></option>
<option *ngFor="let account of accounts" [value]="account.id">{{account.addressBookName ? account.addressBookName + ' - ' : '#' + account.index + ' - ' }} {{ account.id | squeeze }}</option>
</select>
</div>
</div>
</ng-container>
<ng-container *ngIf="(inMerchantModePaymentComplete === false) && (inMerchantModeQR === false) && (pendingAccountModel !== '0')">
<div class="identicon-name-row uk-text-truncate">
<app-nano-identicon scale="6" [accountID]="pendingAccountModel" [settingIdenticonsStyle]="settings.settings.identiconsStyle" class="nano-identicon" *ngIf="(settings.settings.identiconsStyle !== 'none')"></app-nano-identicon>
<div class="account-label uk-text-truncate">{{ selectedAccountAddressBookName }}</div>
</div>
<app-nano-account-id [accountID]="pendingAccountModel" middle="off" class="nano-address-monospace uk-width-auto"></app-nano-account-id>
<button
class="uk-width-auto uk-button uk-button-secondary uk-text-center nlt-icon-button uk-margin-small-top"
type="button"
(click)="unsetSelectedAccount()"
>
<span class="nlt-icon" uk-icon="icon: pencil;"></span>
Change account
</button>
<div
class="uk-width-1-1 uk-card uk-card-default uk-margin-bottom"
style="margin-top: 60px;"
>
<div class="uk-card-body">
<p class="uk-text-large">Enter the <span class="uk-text-primary">requested amount</span></p>
<div class="form-amount">
<div class="uk-width-1-1 uk-inline">
<label class="uk-form-icon uk-link-reset uk-link-muted xno-symbol" for="form-horizontal-amount"></label>
<input [(ngModel)]="amountNano" [ngClass]="{ 'uk-form-danger': !validNano }" [attr.disabled]="pendingAccountModel == '0' || null" autocomplete="off" class="uk-input" id="form-horizontal-amount" (input)="nanoAmountChange()" style="padding-left: 52px !important;" type="number" step="any" placeholder="Amount of XNO" maxlength="40">
</div>
<div style="margin-top: 10px;" *ngIf="settings.settings.displayCurrency">
<p class="text-half-muted" style="margin: 0 0 14px 0;">or</p>
<div class="uk-width-1-1 uk-inline">
<a class="uk-form-icon uk-link-reset uk-link-muted fiat-currency-ticker" uk-tooltip title="Last Price: {{ price.price.lastPrice | fiat: settings.settings.displayCurrency }} / XNO">{{ settings.settings.displayCurrency | currencySymbol }}</a>
<input [(ngModel)]="amountFiat" [ngClass]="{ 'uk-form-danger': !validFiat }" [attr.disabled]="pendingAccountModel == '0' || null" autocomplete="off" (input)="fiatAmountChange()" style="padding-left: 52px !important;" class="uk-input" id="form-horizontal-text-fiat" type="number" step="any" placeholder="Amount of {{ settings.settings.displayCurrency }}">
</div>
</div>
</div>
<button
class="uk-width-1-1 uk-button uk-button-primary uk-text-center nlt-icon-button uk-margin-medium-top"
type="button"
(click)="merchantModeShowQR()"
>
<span class="merchant-mode-icon-qr-code"></span>
Create QR code
</button>
</div>
</div>
</ng-container>
<ng-container *ngIf="(inMerchantModeQR === true)">
<p class="uk-text-large uk-margin-remove-bottom">Send</p>
<p class="uk-text-large uk-text-primary uk-margin-remove-top" *ngIf="(amountNano === '')">
<span class="merchant-mode-currency-name">XNO</span>
</p>
<p class="uk-text-large uk-text-primary uk-margin-remove-top" *ngIf="(amountNano !== '')">
<span
class="merchant-mode-amount-integer"
>{{ merchantModeRawRequestedQR | rai: 'mnano,true' | amountsplit: 0 }}</span>
<span
class="merchant-mode-amount-fractional"
>{{ merchantModeRawRequestedQR | rai: 'mnano,true' | amountsplit: 1 }}</span>
<span class="merchant-mode-currency-name merchant-mode-currency-margin">XNO</span>
</p>
<p class="text-half-muted" style="margin: -16px 0 10px 0;">to</p>
<app-nano-account-id
[accountID]="pendingAccountModel" middle="break"
class="nano-address-monospace uk-width-auto"
style="display: inline-block; max-width: 325px;"
></app-nano-account-id>
<div
class="uk-width-1-1 uk-flex uk-flex-center uk-margin-top"
style="margin-bottom: 40px;"
>
<img class="merchant-mode-qr-code" [src]="qrCodeImage" alt="QR code" *ngIf="qrCodeImage">
<div class="merchant-mode-qr-code" *ngIf="!qrCodeImage"><div uk-spinner="ratio: 2;"></div></div>
</div>
<div
class="uk-width-1-1 uk-card uk-card-default uk-margin-bottom"
*ngFor="let prompt of merchantModePrompts; let promptIdx = index"
>
<div class="uk-card-body">
<p
*ngIf="(amountNano === '')"
class="uk-text-large text-half-muted uk-margin-remove-bottom"
>
Received
</p>
<p
*ngIf="(amountNano !== '') && prompt.moreThanRequested"
class="uk-text-large text-half-muted uk-margin-remove-bottom"
>
Received <span class="uk-text-success">more</span> than requested
</p>
<p
*ngIf="(amountNano !== '') && prompt.lessThanRequested"
class="uk-text-large text-half-muted uk-margin-remove-bottom"
>
Received <span class="uk-text-warning">less</span> than requested
</p>
<p
class="uk-text-large uk-margin-remove-top"
[class.uk-text-success]="prompt.moreThanRequested"
[class.uk-text-warning]="prompt.lessThanRequested"
>
<span
class="merchant-mode-amount-integer"
>{{ prompt.amountRaw | rai: 'mnano,true' | amountsplit: 0 }}</span>
<span
class="merchant-mode-amount-fractional"
>{{ prompt.amountRaw | rai: 'mnano,true' | amountsplit: 1 }}</span>
<span class="merchant-mode-currency-name merchant-mode-currency-margin">XNO</span>
</p>
<div
*ngIf="prompt.amountHiddenRaw.gt(0)"
class="uk-text-small text-half-muted block-hash-monospace"
style="margin: -22px 0 28px 0;"
>
+{{ prompt.amountHiddenRaw.toString(10) }} raw
</div>
<button
*ngIf="prompt.moreThanRequested"
class="uk-width-1-1 uk-button uk-button-primary uk-text-center nlt-icon-button uk-margin-bottom nlt-button-green"
type="button"
(click)="merchantModeMarkCompleteFromPrompt(prompt)"
>
<span class="nlt-icon" uk-icon="icon: check;" style="margin-top: -2px;"></span>
Mark Payment Complete
</button>
<button
*ngIf="prompt.lessThanRequested"
class="uk-width-1-1 uk-button uk-button-primary uk-text-center nlt-icon-button uk-margin-bottom"
type="button"
(click)="merchantModeSubtractAmountFromPrompt(prompt, promptIdx)"
>
<span class="nlt-icon" uk-icon="icon: pencil;" style="margin-top: -2px;"></span>
Subtract From Amount
</button>
<button
class="uk-width-1-1 uk-button uk-button-secondary uk-text-danger uk-text-center nlt-icon-button"
type="button"
(click)="merchantModeDiscardPrompt(promptIdx)"
>
<span class="nlt-icon" uk-icon="icon: close;" style="margin-top: -2px;"></span>
Discard As Unrelated
</button>
</div>
</div>
<ng-container *ngIf="merchantModePrompts.length === 0">
<p class="uk-text-large uk-margin-top text-half-muted">Awaiting payment...</p>
<button
class="uk-width-auto uk-button uk-text-center nlt-icon-button"
[class.uk-button-primary]="!loadingIncomingTxList"
[class.uk-button-secondary]="loadingIncomingTxList"
[class.uk-disabled]="loadingIncomingTxList"
type="button"
(click)="!loadingIncomingTxList && getPending()"
>
<span class="nlt-icon" uk-icon="icon: refresh;" style="margin-top: -2px;" *ngIf="!loadingIncomingTxList"></span>
<span class="spinner" uk-spinner="ratio: 0.5;" *ngIf="loadingIncomingTxList"></span>
{{ loadingIncomingTxList ? 'Checking Payment...' : 'Check Payment' }}
</button>
</ng-container>
<div
class="merchant-mode-exit uk-flex uk-flex-middle uk-hidden@s"
style="margin-top: 70px;"
(click)="merchantModeHideQR()"
>
<span uk-icon="icon: close; ratio: 1.4;" class="uk-margin-small-right" style="margin-top: 2px;"></span>
<span class="label">Cancel Payment</span>
</div>
</ng-container>
<ng-container *ngIf="(inMerchantModePaymentComplete === true)">
<p class="uk-text-large uk-margin-remove-bottom uk-text-success">Received</p>
<p class="uk-text-large uk-text-success uk-margin-remove-top">
<span
class="merchant-mode-amount-integer"
>{{ merchantModeRawReceivedTotal | rai: 'mnano,true' | amountsplit: 0 }}</span>
<span
class="merchant-mode-amount-fractional"
>{{ merchantModeRawReceivedTotal | rai: 'mnano,true' | amountsplit: 1 }}</span>
<span class="merchant-mode-currency-name merchant-mode-currency-margin">XNO</span>
</p>
<div
*ngIf="merchantModeRawReceivedTotalHiddenRaw.gt(0)"
class="uk-text-small text-half-muted block-hash-monospace"
style="margin: -22px 0 28px 0;"
>
+{{ merchantModeRawReceivedTotalHiddenRaw.toString(10) }} raw
</div>
<img style="width: 50%; margin-top: -40px;" src="data:image/svg+xml,%3Csvg width='200mm' height='200mm' viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m157.05 40.584c-2.5562-2e-6 -5.1127 0.97964-7.0714 2.9383l-65.687 65.687-34.266-34.266c-3.9174-3.9174-10.225-3.9174-14.142 1e-6l-12.915 12.915c-3.9174 3.9174-3.9174 10.225-1e-6 14.142l39.526 39.526c0.4262 0.72955 0.95143 1.4181 1.5782 2.0448l12.915 12.915c3.9174 3.9174 10.225 3.9174 14.142 0l85.906-85.907c3.9174-3.9174 3.9174-10.224 0-14.142l-12.915-12.915c-1.9587-1.9587-4.5147-2.9383-7.0709-2.9383z' fill='none' stop-color='%23000000' stroke='%2332d296' stroke-linejoin='round' stroke-width='2' style='paint-order:stroke fill markers'/%3E%3C/svg%3E" />
<p class="uk-flex uk-flex-center uk-flex-middle text-half-muted uk-margin-remove-bottom">
<button
class="uk-button uk-button-secondary uk-text-center nlt-icon-button"
type="button"
ngxClipboard
[cbContent]="(
'Amount Requested: '
+ ( merchantModeRawRequestedTotal | rai: 'mnano,true' | amountsplit: 0 )
+ ( merchantModeRawRequestedTotal | rai: 'mnano,true' | amountsplit: 1 )
+ ' XNO'
+ '\n\n'
+ 'Amount Paid: '
+ ( merchantModeRawReceivedTotal | rai: 'mnano,true' | amountsplit: 0 )
+ ( merchantModeRawReceivedTotal | rai: 'mnano,true' | amountsplit: 1 )
+ ' XNO'
+ '\n\n'
+ 'Transaction ID\'s:'
+ '\n- '
+ merchantModeTransactionHashes.join('\n- ')
)"
>
<span class="nlt-icon" uk-icon="icon: copy;"></span>
Copy Payment Information
</button>
</p>
<ul class="uk-width-1-1">
<li
*ngFor="let hash of merchantModeTransactionHashes"
class="uk-text-left text-half-muted block-hash-monospace"
style="word-wrap: anywhere;"
>
{{ hash }}
</li>
</ul>
<div
class="merchant-mode-exit uk-flex uk-flex-middle"
style="margin-top: 70px;"
(click)="merchantModeResetState()"
>
<span uk-icon="icon: plus-circle; ratio: 1.4;" class="uk-margin-small-right" style="margin-top: 2px;"></span>
<span class="label">New Payment</span>
</div>
</ng-container>
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ReceiveComponent } from './receive.component';
@ -6,7 +6,7 @@ describe('ReceiveComponent', () => {
let component: ReceiveComponent;
let fixture: ComponentFixture<ReceiveComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ReceiveComponent ]
})

View file

@ -29,6 +29,7 @@ export class ReceiveComponent implements OnInit, OnDestroy {
timeoutIdClearingRecentlyCopiedState: any = null;
mobileTransactionMenuModal: any = null;
merchantModeModal: any = null;
mobileTransactionData: any = null;
selectedAccountAddressBookName = '';
@ -48,6 +49,17 @@ export class ReceiveComponent implements OnInit, OnDestroy {
validFiat = true;
qrSuccessClass = '';
inMerchantMode = false;
inMerchantModeQR = false;
inMerchantModePaymentComplete = false;
merchantModeRawRequestedQR: BigNumber = null;
merchantModeRawRequestedTotal: BigNumber = null;
merchantModeRawReceivedTotal: BigNumber = null;
merchantModeRawReceivedTotalHiddenRaw: BigNumber = null;
merchantModeSeenBlockHashes = {};
merchantModePrompts = [];
merchantModeTransactionHashes = [];
routerSub = null;
constructor(
@ -67,12 +79,17 @@ export class ReceiveComponent implements OnInit, OnDestroy {
async ngOnInit() {
const UIkit = window['UIkit'];
const mobileTransactionMenuModal = UIkit.modal('#mobile-transaction-menu-modal');
this.mobileTransactionMenuModal = mobileTransactionMenuModal;
const merchantModeModal = UIkit.modal('#merchant-mode-modal');
this.merchantModeModal = merchantModeModal;
this.routerSub = this.route.events.subscribe(event => {
if (event instanceof ChildActivationEnd) {
this.mobileTransactionMenuModal.hide();
this.merchantModeModal.hide();
}
});
@ -110,12 +127,16 @@ export class ReceiveComponent implements OnInit, OnDestroy {
this.showQrConfirmation();
setTimeout(() => this.resetAmount(), 500);
}
if ( (this.inMerchantModeQR === true) && (transaction.block.link_as_account === this.qrAccount) ) {
this.onMerchantModeReceiveTransaction(transaction);
}
}
});
}
ngOnDestroy() {
this.mobileTransactionMenuModal.hide();
this.merchantModeModal.hide();
if (this.routerSub) {
this.routerSub.unsubscribe();
}
@ -164,6 +185,14 @@ export class ReceiveComponent implements OnInit, OnDestroy {
// Blocks for selected account
this.pendingBlocksForSelectedAccount =
this.pendingBlocks.filter(block => (block.destination === selectedAccountID));
if (this.inMerchantModeQR === true) {
this.pendingBlocksForSelectedAccount.forEach(
(pendingBlock) => {
this.onMerchantModeReceiveTransaction(pendingBlock);
}
)
}
}
showMobileMenuForTransaction(transaction) {
@ -364,4 +393,140 @@ export class ReceiveComponent implements OnInit, OnDestroy {
return new BigNumber(value);
}
unsetSelectedAccount() {
this.pendingAccountModel = '0';
this.onSelectedAccountChange(this.pendingAccountModel);
}
getRawAmountWithoutTinyRaws(rawAmountWithTinyRaws) {
const tinyRaws =
rawAmountWithTinyRaws.mod(this.nano);
return rawAmountWithTinyRaws.minus(tinyRaws);
}
merchantModeResetState() {
this.unsetSelectedAccount();
this.resetAmount();
this.inMerchantModeQR = false;
this.inMerchantModePaymentComplete = false;
}
merchantModeEnable() {
this.merchantModeResetState();
this.inMerchantMode = true;
this.merchantModeModal.show();
}
merchantModeDisable() {
this.inMerchantMode = false;
this.inMerchantModeQR = false;
this.inMerchantModePaymentComplete = false;
this.merchantModeModal.hide();
}
merchantModeShowQR() {
const isRequestingAnyAmount = (this.validNano === false || Number(this.amountNano) === 0);
if(isRequestingAnyAmount === true) {
this.resetAmount();
}
this.merchantModeRawRequestedTotal =
(isRequestingAnyAmount === true)
? new BigNumber(0)
: this.util.nano.mnanoToRaw(this.amountNano);
this.merchantModeRawRequestedQR =
(isRequestingAnyAmount === true)
? new BigNumber(0)
: this.util.nano.mnanoToRaw(this.amountNano);
this.merchantModeSeenBlockHashes =
this.pendingBlocksForSelectedAccount.reduce(
(seenHashes, receivableBlock) => {
seenHashes[receivableBlock.hash] = true
return seenHashes
},
{}
);
this.merchantModeTransactionHashes = [];
this.inMerchantModeQR = true;
}
merchantModeHideQR() {
this.inMerchantModeQR = false;
}
onMerchantModeReceiveTransaction(transaction) {
if( this.merchantModeSeenBlockHashes[transaction.hash] != null ) {
return;
}
this.merchantModeSeenBlockHashes[transaction.hash] = true;
const receivedAmountWithTinyRaws = new BigNumber(transaction.amount);
const receivedAmount =
this.getRawAmountWithoutTinyRaws(receivedAmountWithTinyRaws);
const requestedAmount =
this.getRawAmountWithoutTinyRaws(this.merchantModeRawRequestedQR);
if( receivedAmount.eq(requestedAmount) ) {
this.merchantModeTransactionHashes.push(transaction.hash);
this.merchantModeMarkCompleteWithAmount(this.merchantModeRawRequestedTotal);
} else {
const transactionPrompt = {
moreThanRequested: receivedAmount.gt(requestedAmount),
lessThanRequested: receivedAmount.lt(requestedAmount),
amountRaw: receivedAmountWithTinyRaws,
amountHiddenRaw: receivedAmountWithTinyRaws.mod(this.nano),
transactionHash: transaction.hash,
}
this.merchantModePrompts.push(transactionPrompt);
}
}
merchantModeSubtractAmountFromPrompt(prompt, promptIdx) {
const subtractedRawWithTinyRaws = prompt.amountRaw;
const subtractedRaw =
this.getRawAmountWithoutTinyRaws(subtractedRawWithTinyRaws);
const newAmountRaw =
this.merchantModeRawRequestedQR.minus(subtractedRaw);
this.merchantModeRawRequestedQR = newAmountRaw;
this.changeQRAmount(newAmountRaw.toFixed());
this.merchantModeTransactionHashes.push(prompt.transactionHash);
this.merchantModePrompts.splice(promptIdx, 1);
}
merchantModeMarkCompleteFromPrompt(prompt) {
this.merchantModeTransactionHashes.push(prompt.transactionHash);
this.merchantModeMarkCompleteWithAmount(prompt.amountRaw);
}
merchantModeDiscardPrompt(promptIdx) {
this.merchantModePrompts.splice(promptIdx, 1);
}
merchantModeMarkCompleteWithAmount(amountRaw) {
this.merchantModeRawReceivedTotal = amountRaw;
this.merchantModeRawReceivedTotalHiddenRaw = amountRaw.mod(this.nano);
this.inMerchantModePaymentComplete = true;
this.inMerchantModeQR = false;
}
}

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RemoteSigningComponent } from './remote-signing.component';
@ -6,7 +6,7 @@ describe('RemoteSigningComponent', () => {
let component: RemoteSigningComponent;
let fixture: ComponentFixture<RemoteSigningComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ RemoteSigningComponent ]
})

View file

@ -248,7 +248,7 @@
</div>
</div>
<div class="uk-card-footer">
<button class="uk-button uk-button-primary uk-width-1-1" type="button" (click)="changeRepresentatives()" *ngIf="!changingRepresentatives">Update Representatives</button>
<button class="uk-button uk-button-primary uk-width-1-1@s uk-width-auto@m uk-float-right" type="button" (click)="changeRepresentatives()" *ngIf="!changingRepresentatives">Update Representatives</button>
<button class="uk-button uk-button-secondary uk-width-1-1 uk-disabled nlt-icon-button" type="button" *ngIf="changingRepresentatives"><span class="spinner" uk-spinner="ratio: 0.5;"></span> Updating Representatives</button>
</div>
</div>

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RepresentativesComponent } from './representatives.component';
@ -6,7 +6,7 @@ describe('RepresentativesComponent', () => {
let component: RepresentativesComponent;
let fixture: ComponentFixture<RepresentativesComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ RepresentativesComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { SendComponent } from './send.component';
@ -6,7 +6,7 @@ describe('SendComponent', () => {
let component: SendComponent;
let fixture: ComponentFixture<SendComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ SendComponent ]
})

View file

@ -334,15 +334,13 @@
<a *ngIf="processedHash" [routerLink]="'/account/' + signatureAccount" [queryParams]="{ sign: 1 }" class="uk-button uk-button-primary uk-width-auto" title="Account detail view" uk-tooltip>Account Detail View</a>
</div>
<div *ngIf="!processedHash" uk-grid>
<div class="uk-width-1-2@s">
<a class="uk-button uk-button-danger uk-width-1-1" (click)="cancel()">Cancel</a>
</div>
<div class="uk-width-1-2@s">
<button *ngIf="!confirmingTransaction && shouldSign && signTypeSelected !== signTypes[3]" class="uk-button uk-button-primary uk-width-1-1" (click)="confirmTransaction()">Confirm & Sign</button>
<button *ngIf="!confirmingTransaction && shouldSign && signTypeSelected === signTypes[3]" class="uk-button uk-button-primary uk-width-1-1" (click)="startMultisig()" [disabled]="!this.validPrivkey || !this.validParticipants || finalSignature || (this.activeStep > 1 && !this.isInputAddDisabled)">{{this.activeStep !== 4 ? (this.activeStep === 1 ? 'Start Multi-signing' : 'Step '+ (this.activeStep - 1) + '/3 | Next') : 'Step '+ (this.activeStep - 1) + '/3 | Final Step'}}</button>
<div *ngIf="!processedHash">
<div class="nlt-button-group uk-width-1-1 uk-text-right">
<button class="uk-button uk-button-danger uk-width-1-1@s uk-width-auto@m" (click)="cancel()">Cancel</button>
<button *ngIf="!confirmingTransaction && shouldSign && signTypeSelected !== signTypes[3]" class="uk-button uk-button-primary uk-width-1-1@s uk-width-auto@m" (click)="confirmTransaction()">Confirm & Sign</button>
<button *ngIf="!confirmingTransaction && shouldSign && signTypeSelected === signTypes[3]" class="uk-button uk-button-primary uk-width-1-1@s uk-width-auto@m" (click)="startMultisig()" [disabled]="!this.validPrivkey || !this.validParticipants || finalSignature || (this.activeStep > 1 && !this.isInputAddDisabled)">{{this.activeStep !== 4 ? (this.activeStep === 1 ? 'Start Multi-signing' : 'Step '+ (this.activeStep - 1) + '/3 | Next') : 'Step '+ (this.activeStep - 1) + '/3 | Final Step'}}</button>
<button *ngIf="confirmingTransaction && shouldSign" class="uk-button uk-button-primary uk-disabled uk-width-1-1"><span class="uk-margin-right" uk-spinner></span> Loading</button>
<button *ngIf="!confirmingTransaction && !shouldSign" class="uk-button uk-button-primary uk-width-1-1" (click)="confirmBlock()">Confirm & Process</button>
<button *ngIf="!confirmingTransaction && !shouldSign" class="uk-button uk-button-primary uk-width-1-1@s uk-width-auto@m" (click)="confirmBlock()">Confirm & Process</button>
<button *ngIf="confirmingTransaction && !shouldSign" class="uk-button uk-button-primary uk-disabled uk-width-1-1"><span class="uk-margin-right" uk-spinner></span> Loading</button>
</div>
</div>
@ -362,7 +360,7 @@
</div>
<!-- Modal for result QR -->
<div id="signed-modal" uk-modal>
<div class="modal-position-bottom" id="signed-modal" uk-modal>
<div class="uk-modal-dialog uk-modal-body modal-qr">
<button class="uk-modal-close-default" type="button" uk-close></button>
<div class="uk-modal-header">
@ -390,7 +388,7 @@
</div>
<!-- Modal for output data QR -->
<div id="qr-code-modal" uk-modal>
<div class="modal-position-bottom" id="qr-code-modal" uk-modal>
<div class="uk-modal-dialog uk-margin-auto-vertical">
<button class="uk-modal-close-default" type="button" uk-close></button>
<div class="uk-modal-body">

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { SignComponent } from './sign.component';
@ -6,7 +6,7 @@ describe('SignComponent', () => {
let component: SignComponent;
let fixture: ComponentFixture<SignComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ SignComponent ]
})

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { SweeperComponent } from './sweeper.component';
@ -6,7 +6,7 @@ describe('SweeperComponent', () => {
let component: SweeperComponent;
let fixture: ComponentFixture<SweeperComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ SweeperComponent ]
})

View file

@ -191,6 +191,29 @@
</div>
</div>
</div>
<div class="uk-margin" *ngIf="successorHash">
<label class="uk-form-label">Successor:</label>
<div class="uk-form-controls uk-text-truncate">
<div uk-grid class="uk-flex-nowrap uk-text-truncate">
<a
class="uk-width-auto uk-text-truncate block-hash-monospace block-hash-clickable"
[routerLink]="'/transaction/' + successorHash"
style="max-width: calc(100% - 35px);"
title="View Block Details"
uk-tooltip
>{{ successorHash }}</a>
<div class="uk-width-auto block-hash-actions">
<ul class="uk-iconnav">
<li><a ngxClipboard [cbContent]="successorHash" (cbOnSuccess)="copied()" uk-icon="icon: copy" title="Copy Successor Block Hash" uk-tooltip></a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="uk-margin" *ngIf="blockHeight != -1">
<label class="uk-form-label">Height:</label>
<div class="uk-form-controls uk-text-truncate">{{ blockHeight | number:'':'en-US' }}</div>
</div>
<div class="uk-margin" *ngIf="(transaction?.contents?.link || transaction?.contents?.source) && (blockType == 'open' || blockType == 'receive')">
<label class="uk-form-label">Link (Source):</label>
<div class="uk-form-controls uk-text-truncate">
@ -220,10 +243,6 @@
</a>
</div>
</div>
<div class="uk-margin" *ngIf="blockHeight != -1">
<label class="uk-form-label">Height:</label>
<div class="uk-form-controls uk-text-truncate">{{ blockHeight | number:'':'en-US' }}</div>
</div>
<div class="uk-margin" *ngIf="transaction?.contents?.work">
<label class="uk-form-label">Work:</label>
<div class="uk-form-controls uk-text-truncate">

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { TransactionDetailsComponent } from './transaction-details.component';
@ -6,7 +6,7 @@ describe('TransactionDetailsComponent', () => {
let component: TransactionDetailsComponent;
let fixture: ComponentFixture<TransactionDetailsComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ TransactionDetailsComponent ]
})

View file

@ -34,6 +34,7 @@ export class TransactionDetailsComponent implements OnInit {
showBlockData = false;
amountRaw = new BigNumber(0);
successorHash = '';
constructor(
private walletService: WalletService,
@ -69,6 +70,7 @@ export class TransactionDetailsComponent implements OnInit {
let legacyFromAccount = '';
this.blockType = '';
this.amountRaw = new BigNumber(0);
this.successorHash = '';
const hash = this.route.snapshot.params.transaction;
this.hashID = hash;
@ -90,9 +92,11 @@ export class TransactionDetailsComponent implements OnInit {
this.isUnconfirmedBlock = (hashData.confirmed === 'false') ? true : false;
this.blockHeight = hashData.height;
const HASH_ONLY_ZEROES = '0000000000000000000000000000000000000000000000000000000000000000';
const blockType = hashData.contents.type;
if (blockType === 'state') {
const isOpen = hashData.contents.previous === '0000000000000000000000000000000000000000000000000000000000000000';
const isOpen = (hashData.contents.previous === HASH_ONLY_ZEROES);
if (isOpen) {
this.blockType = 'open';
@ -126,6 +130,13 @@ export class TransactionDetailsComponent implements OnInit {
this.amountRaw = new BigNumber(hashData.amount).mod(this.nano);
}
if (
(hashData.successor != null)
&& (hashData.successor !== HASH_ONLY_ZEROES)
) {
this.successorHash = hashData.successor;
}
this.transaction = hashData;
let fromAccount = '';

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { WalletWidgetComponent } from './wallet-widget.component';
@ -6,7 +6,7 @@ describe('WalletWidgetComponent', () => {
let component: WalletWidgetComponent;
let fixture: ComponentFixture<WalletWidgetComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ WalletWidgetComponent ]
})

View file

@ -136,7 +136,7 @@ export class WalletWidgetComponent implements OnInit {
this.notificationService.sendSuccess(`Wallet unlocked`);
this.modal.hide();
if (this.unlockPassword.length < 6) {
// tslint:disable-next-line: max-line-length
// eslint-disable-next-line max-len
this.notificationService.sendWarning(`You are using an insecure password and encouraged to change it from settings > manage wallet`);
}

View file

@ -0,0 +1,19 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'noPaddingZeros'
})
export class NoPaddingZerosPipe implements PipeTransform {
transform(input: string): string {
const sig = input.split('.')[0];
const frac = input.split('.')[1].replace(/0+$/g, '');
// 1.000000 XNO >> 1 XNO
if (!frac) {
return sig;
}
// 0.002200 >> 0.0022 XNO
return `${sig}.${frac}`;
}
}

View file

@ -22,14 +22,21 @@ export class ApiService {
this.node.setLoading();
}
}
let header;
let options: any = {
responseType: 'json',
};
if (this.appSettings.settings.serverAuth != null && this.appSettings.settings.serverAuth !== '') {
header = {
headers: new HttpHeaders()
.set('Authorization', this.appSettings.settings.serverAuth)
};
options =
Object.assign(
{},
options,
{
headers: new HttpHeaders()
.set('Authorization', this.appSettings.settings.serverAuth)
}
);
}
return await this.http.post(apiUrl, data, header).toPromise()
return await this.http.post(apiUrl, data, options).toPromise()
.then(res => {
this.node.setOnline();
return res;

View file

@ -64,17 +64,35 @@ export class NinjaService {
// false - does not exist, null - any other error
async getAccount(account: string): Promise<any> {
return await this.http.get(this.ninjaUrl + 'accounts/' + account).toPromise()
.then(res => {
return res;
})
.catch(err => {
if (err.status === 404) {
return false;
}
const REQUEST_TIMEOUT_MS = 10000;
return null;
const successPromise =
this.http.get(this.ninjaUrl + 'accounts/' + account).toPromise()
.then(res => {
return res;
})
.catch(err => {
if (err.status === 404) {
return false;
}
return null;
});
const timeoutPromise =
new Promise(resolve => {
setTimeout(
() => {
resolve(null);
},
REQUEST_TIMEOUT_MS
);
});
return await Promise.race([
successPromise,
timeoutPromise
]);
}
}

View file

@ -453,11 +453,11 @@ export class RepresentativeService {
}
// Default representatives list
// tslint:disable-next-line:member-ordering
// eslint-disable-next-line @typescript-eslint/member-ordering
defaultRepresentatives = [];
// Bad representatives hardcoded to be avoided. Not visible in the user rep list
// tslint:disable-next-line:member-ordering
// eslint-disable-next-line @typescript-eslint/member-ordering
nfReps = [
{
id: 'nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4',

View file

@ -100,7 +100,7 @@ function hexToUint4(hexValue) {
return uint4;
}
function hexToUint8(hexValue) {
// tslint:disable-next-line:no-bitwise
// eslint-disable-next-line no-bitwise
const length = (hexValue.length / 2) | 0;
const uint8 = new Uint8Array(length);
for (let i = 0; i < length; i++) uint8[i] = parseInt(hexValue.substr(i * 2, 2), 16);
@ -124,7 +124,7 @@ function uint4ToUint8(uintValue) {
return uint8;
}
// tslint:disable:no-bitwise
/* eslint-disable no-bitwise */
function uint4ToUint5(uintValue) {
const length = uintValue.length / 5 * 4;
const uint5 = new Uint8Array(length);
@ -140,7 +140,7 @@ function uint4ToUint5(uintValue) {
}
return uint5;
}
// tslint:enable:no-bitwise
/* eslint-enable no-bitwise */
function uint4ToHex(uint4) {
let hex = '';
@ -158,7 +158,7 @@ function uint5ToString(uint5) {
return string;
}
// tslint:disable:no-bitwise
/* eslint-disable no-bitwise */
function uint5ToUint4(uint5) {
const length = uint5.length / 4 * 5;
const uint4 = new Uint8Array(length);
@ -172,7 +172,7 @@ function uint5ToUint4(uint5) {
}
return uint4;
}
// tslint:enable:no-bitwise
/* eslint-enable no-bitwise */
/** Uint8 Functions **/
@ -191,7 +191,7 @@ function uint8ToHex(uintValue) {
return(hex);
}
// tslint:disable:no-bitwise
/* eslint-disable no-bitwise */
function uint8ToUint4(uintValue) {
const uint4 = new Uint8Array(uintValue.length * 2);
for (let i = 0; i < uintValue.length; i++) {
@ -201,12 +201,12 @@ function uint8ToUint4(uintValue) {
return uint4;
}
// tslint:enable:no-bitwise
/* eslint-enable no-bitwise */
/** Dec Functions **/
function decToHex(decValue, bytes = null) {
// tslint:disable-next-line:prefer-const
// eslint-disable-next-line prefer-const
let dec = decValue.toString().split(''), sum = [], hex = '', hexArray = [], i, s;
while (dec.length) {
s = 1 * dec.shift();

View file

@ -12,6 +12,7 @@ import {NotificationService} from './notification.service';
import {AppSettingsService} from './app-settings.service';
import {PriceService} from './price.service';
import {LedgerService} from './ledger.service';
import { NoPaddingZerosPipe } from 'app/pipes/no-padding-zeros.pipe';
export type WalletType = 'seed' | 'ledger' | 'privateKey' | 'expandedKey';
@ -136,6 +137,7 @@ export class WalletService {
private websocket: WebsocketService,
private nanoBlock: NanoBlockService,
private ledgerService: LedgerService,
private noZerosPipe: NoPaddingZerosPipe,
private notifications: NotificationService) {
this.websocket.newTransactions$.subscribe(async (transaction) => {
if (!transaction) return; // Not really a new transaction
@ -853,7 +855,7 @@ export class WalletService {
this.wallet.balanceFiat = this.util.nano.rawToMnano(walletBalance).times(fiatPrice).toNumber();
this.wallet.pendingFiat = this.util.nano.rawToMnano(walletPendingAboveThresholdConfirmed).times(fiatPrice).toNumber();
// tslint:disable-next-line
// eslint-disable-next-line
this.wallet.hasPending = walletPendingAboveThresholdConfirmed.gt(0);
this.wallet.updatingBalance = false;
@ -1018,7 +1020,7 @@ export class WalletService {
const receiveAmount = this.util.nano.rawToMnano(nextBlock.amount);
this.notifications.removeNotification('success-receive');
this.notifications.sendSuccess(`Successfully received ${receiveAmount.isZero() ? '' : receiveAmount.toFixed(6)} XNO!`, { identifier: 'success-receive' });
this.notifications.sendSuccess(`Successfully received ${receiveAmount.isZero() ? '' : this.noZerosPipe.transform(receiveAmount.toFixed(6)) } XNO!`, { identifier: 'success-receive' });
// remove after processing
// list also updated with reloadBalances but not if called too fast

View file

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { WelcomeComponent } from './welcome.component';
@ -6,7 +6,7 @@ describe('WelcomeComponent', () => {
let component: WelcomeComponent;
let fixture: ComponentFixture<WelcomeComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ WelcomeComponent ]
})

View file

@ -1,10 +1,10 @@
/*! UIkit 3.5.4 | https://www.getuikit.com | (c) 2014 - 2020 YOOtheme | MIT License */
/*! UIkit 3.9.4 | https://www.getuikit.com | (c) 2014 - 2021 YOOtheme | MIT License */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define('uikiticons', factory) :
(global = global || self, global.UIkitIcons = factory());
}(this, (function () { 'use strict';
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.UIkitIcons = factory());
})(this, (function () { 'use strict';
function plugin(UIkit) {
@ -19,6 +19,7 @@
"arrow-left": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><polyline fill=\"none\" stroke=\"#000\" points=\"10 14 5 9.5 10 5\"/><line fill=\"none\" stroke=\"#000\" x1=\"16\" y1=\"9.5\" x2=\"5\" y2=\"9.52\"/></svg>",
"arrow-right": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><polyline fill=\"none\" stroke=\"#000\" points=\"10 5 15 9.5 10 14\"/><line fill=\"none\" stroke=\"#000\" x1=\"4\" y1=\"9.5\" x2=\"15\" y2=\"9.5\"/></svg>",
"arrow-up": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><polygon points=\"10.5,4 15.37,9.4 14.63,10.08 10.5,5.49 6.37,10.08 5.63,9.4\"/><line fill=\"none\" stroke=\"#000\" x1=\"10.5\" y1=\"16\" x2=\"10.5\" y2=\"5\"/></svg>",
"bag": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"none\" stroke=\"#000\" d=\"M7.5,7.5V4A2.48,2.48,0,0,1,10,1.5,2.54,2.54,0,0,1,12.5,4V7.5\"/><polygon fill=\"none\" stroke=\"#000\" points=\"16.5 7.5 3.5 7.5 2.5 18.5 17.5 18.5 16.5 7.5\"/></svg>",
"ban": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><circle fill=\"none\" stroke=\"#000\" stroke-width=\"1.1\" cx=\"10\" cy=\"10\" r=\"9\"/><line fill=\"none\" stroke=\"#000\" stroke-width=\"1.1\" x1=\"4\" y1=\"3.5\" x2=\"16\" y2=\"16.5\"/></svg>",
"behance": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.5,10.6c-0.4-0.5-0.9-0.9-1.6-1.1c1.7-1,2.2-3.2,0.7-4.7C7.8,4,6.3,4,5.2,4C3.5,4,1.7,4,0,4v12c1.7,0,3.4,0,5.2,0 c1,0,2.1,0,3.1-0.5C10.2,14.6,10.5,12.3,9.5,10.6L9.5,10.6z M5.6,6.1c1.8,0,1.8,2.7-0.1,2.7c-1,0-2,0-2.9,0V6.1H5.6z M2.6,13.8v-3.1 c1.1,0,2.1,0,3.2,0c2.1,0,2.1,3.2,0.1,3.2L2.6,13.8z\"/><path d=\"M19.9,10.9C19.7,9.2,18.7,7.6,17,7c-4.2-1.3-7.3,3.4-5.3,7.1c0.9,1.7,2.8,2.3,4.7,2.1c1.7-0.2,2.9-1.3,3.4-2.9h-2.2 c-0.4,1.3-2.4,1.5-3.5,0.6c-0.4-0.4-0.6-1.1-0.6-1.7H20C20,11.7,19.9,10.9,19.9,10.9z M13.5,10.6c0-1.6,2.3-2.7,3.5-1.4 c0.4,0.4,0.5,0.9,0.6,1.4H13.5L13.5,10.6z\"/><rect x=\"13\" y=\"4\" width=\"5\" height=\"1.4\"/></svg>",
"bell": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"none\" stroke=\"#000\" stroke-width=\"1.1\" d=\"M17,15.5 L3,15.5 C2.99,14.61 3.79,13.34 4.1,12.51 C4.58,11.3 4.72,10.35 5.19,7.01 C5.54,4.53 5.89,3.2 7.28,2.16 C8.13,1.56 9.37,1.5 9.81,1.5 L9.96,1.5 C9.96,1.5 11.62,1.41 12.67,2.17 C14.08,3.2 14.42,4.54 14.77,7.02 C15.26,10.35 15.4,11.31 15.87,12.52 C16.2,13.34 17.01,14.61 17,15.5 L17,15.5 Z\"/><path fill=\"none\" stroke=\"#000\" d=\"M12.39,16 C12.39,17.37 11.35,18.43 9.91,18.43 C8.48,18.43 7.42,17.37 7.42,16\"/></svg>",
@ -48,6 +49,7 @@
"credit-card": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><rect fill=\"none\" stroke=\"#000\" x=\"1.5\" y=\"4.5\" width=\"17\" height=\"12\"/><rect x=\"1\" y=\"7\" width=\"18\" height=\"3\"/></svg>",
"database": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><ellipse fill=\"none\" stroke=\"#000\" cx=\"10\" cy=\"4.64\" rx=\"7.5\" ry=\"3.14\"/><path fill=\"none\" stroke=\"#000\" d=\"M17.5,8.11 C17.5,9.85 14.14,11.25 10,11.25 C5.86,11.25 2.5,9.84 2.5,8.11\"/><path fill=\"none\" stroke=\"#000\" d=\"M17.5,11.25 C17.5,12.99 14.14,14.39 10,14.39 C5.86,14.39 2.5,12.98 2.5,11.25\"/><path fill=\"none\" stroke=\"#000\" d=\"M17.49,4.64 L17.5,14.36 C17.5,16.1 14.14,17.5 10,17.5 C5.86,17.5 2.5,16.09 2.5,14.36 L2.5,4.64\"/></svg>",
"desktop": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"8\" y=\"15\" width=\"1\" height=\"2\"/><rect x=\"11\" y=\"15\" width=\"1\" height=\"2\"/><rect x=\"5\" y=\"16\" width=\"10\" height=\"1\"/><rect fill=\"none\" stroke=\"#000\" x=\"1.5\" y=\"3.5\" width=\"17\" height=\"11\"/></svg>",
"discord": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\"><path d=\"M16.074,4.361a14.243,14.243,0,0,0-3.61-1.134,10.61,10.61,0,0,0-.463.96,13.219,13.219,0,0,0-4,0,10.138,10.138,0,0,0-.468-.96A14.206,14.206,0,0,0,3.919,4.364,15.146,15.146,0,0,0,1.324,14.5a14.435,14.435,0,0,0,4.428,2.269A10.982,10.982,0,0,0,6.7,15.21a9.294,9.294,0,0,1-1.494-.727c.125-.093.248-.19.366-.289a10.212,10.212,0,0,0,8.854,0c.119.1.242.2.366.289a9.274,9.274,0,0,1-1.5.728,10.8,10.8,0,0,0,.948,1.562,14.419,14.419,0,0,0,4.431-2.27A15.128,15.128,0,0,0,16.074,4.361Zm-8.981,8.1a1.7,1.7,0,0,1-1.573-1.79A1.689,1.689,0,0,1,7.093,8.881a1.679,1.679,0,0,1,1.573,1.791A1.687,1.687,0,0,1,7.093,12.462Zm5.814,0a1.7,1.7,0,0,1-1.573-1.79,1.689,1.689,0,0,1,1.573-1.791,1.679,1.679,0,0,1,1.573,1.791A1.688,1.688,0,0,1,12.907,12.462Z\"/></svg>",
"download": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><polyline fill=\"none\" stroke=\"#000\" points=\"14,10 9.5,14.5 5,10\"/><rect x=\"3\" y=\"17\" width=\"13\" height=\"1\"/><line fill=\"none\" stroke=\"#000\" x1=\"9.5\" y1=\"13.91\" x2=\"9.5\" y2=\"3\"/></svg>",
"dribbble": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"none\" stroke=\"#000\" stroke-width=\"1.4\" d=\"M1.3,8.9c0,0,5,0.1,8.6-1c1.4-0.4,2.6-0.9,4-1.9 c1.4-1.1,2.5-2.5,2.5-2.5\"/><path fill=\"none\" stroke=\"#000\" stroke-width=\"1.4\" d=\"M3.9,16.6c0,0,1.7-2.8,3.5-4.2 c1.8-1.3,4-2,5.7-2.2C16,10,19,10.6,19,10.6\"/><path fill=\"none\" stroke=\"#000\" stroke-width=\"1.4\" d=\"M6.9,1.6c0,0,3.3,4.6,4.2,6.8 c0.4,0.9,1.3,3.1,1.9,5.2c0.6,2,0.9,4.4,0.9,4.4\"/><circle fill=\"none\" stroke=\"#000\" stroke-width=\"1.4\" cx=\"10\" cy=\"10\" r=\"9\"/></svg>",
"etsy": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\"><path d=\"M8,4.26C8,4.07,8,4,8.31,4h4.46c.79,0,1.22.67,1.53,1.91l.25,1h.76c.14-2.82.26-4,.26-4S13.65,3,12.52,3H6.81L3.75,2.92v.84l1,.2c.73.11.9.27,1,1,0,0,.06,2,.06,5.17s-.06,5.14-.06,5.14c0,.59-.23.81-1,.94l-1,.2v.84l3.06-.1h5.11c1.15,0,3.82.1,3.82.1,0-.7.45-3.88.51-4.22h-.73l-.76,1.69a2.25,2.25,0,0,1-2.45,1.47H9.4c-1,0-1.44-.4-1.44-1.24V10.44s2.16,0,2.86.06c.55,0,.85.19,1.06,1l.23,1H13L12.9,9.94,13,7.41h-.85l-.28,1.13c-.16.74-.28.84-1,1-1,.1-2.89.09-2.89.09Z\"/></svg>",
@ -67,7 +69,6 @@
"github-alt": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10,0.5 C4.75,0.5 0.5,4.76 0.5,10.01 C0.5,15.26 4.75,19.51 10,19.51 C15.24,19.51 19.5,15.26 19.5,10.01 C19.5,4.76 15.25,0.5 10,0.5 L10,0.5 Z M12.81,17.69 C12.81,17.69 12.81,17.7 12.79,17.69 C12.47,17.75 12.35,17.59 12.35,17.36 L12.35,16.17 C12.35,15.45 12.09,14.92 11.58,14.56 C12.2,14.51 12.77,14.39 13.26,14.21 C13.87,13.98 14.36,13.69 14.74,13.29 C15.42,12.59 15.76,11.55 15.76,10.17 C15.76,9.25 15.45,8.46 14.83,7.8 C15.1,7.08 15.07,6.29 14.75,5.44 L14.51,5.42 C14.34,5.4 14.06,5.46 13.67,5.61 C13.25,5.78 12.79,6.03 12.31,6.35 C11.55,6.16 10.81,6.05 10.09,6.05 C9.36,6.05 8.61,6.15 7.88,6.35 C7.28,5.96 6.75,5.68 6.26,5.54 C6.07,5.47 5.9,5.44 5.78,5.44 L5.42,5.44 C5.06,6.29 5.04,7.08 5.32,7.8 C4.7,8.46 4.4,9.25 4.4,10.17 C4.4,11.94 4.96,13.16 6.08,13.84 C6.53,14.13 7.05,14.32 7.69,14.43 C8.03,14.5 8.32,14.54 8.55,14.55 C8.07,14.89 7.82,15.42 7.82,16.16 L7.82,17.51 C7.8,17.69 7.7,17.8 7.51,17.8 C4.21,16.74 1.82,13.65 1.82,10.01 C1.82,5.5 5.49,1.83 10,1.83 C14.5,1.83 18.17,5.5 18.17,10.01 C18.18,13.53 15.94,16.54 12.81,17.69 L12.81,17.69 Z\"/></svg>",
"github": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10,1 C5.03,1 1,5.03 1,10 C1,13.98 3.58,17.35 7.16,18.54 C7.61,18.62 7.77,18.34 7.77,18.11 C7.77,17.9 7.76,17.33 7.76,16.58 C5.26,17.12 4.73,15.37 4.73,15.37 C4.32,14.33 3.73,14.05 3.73,14.05 C2.91,13.5 3.79,13.5 3.79,13.5 C4.69,13.56 5.17,14.43 5.17,14.43 C5.97,15.8 7.28,15.41 7.79,15.18 C7.87,14.6 8.1,14.2 8.36,13.98 C6.36,13.75 4.26,12.98 4.26,9.53 C4.26,8.55 4.61,7.74 5.19,7.11 C5.1,6.88 4.79,5.97 5.28,4.73 C5.28,4.73 6.04,4.49 7.75,5.65 C8.47,5.45 9.24,5.35 10,5.35 C10.76,5.35 11.53,5.45 12.25,5.65 C13.97,4.48 14.72,4.73 14.72,4.73 C15.21,5.97 14.9,6.88 14.81,7.11 C15.39,7.74 15.73,8.54 15.73,9.53 C15.73,12.99 13.63,13.75 11.62,13.97 C11.94,14.25 12.23,14.8 12.23,15.64 C12.23,16.84 12.22,17.81 12.22,18.11 C12.22,18.35 12.38,18.63 12.84,18.54 C16.42,17.35 19,13.98 19,10 C19,5.03 14.97,1 10,1 L10,1 Z\"/></svg>",
"gitter": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"3.5\" y=\"1\" width=\"1.531\" height=\"11.471\"/><rect x=\"7.324\" y=\"4.059\" width=\"1.529\" height=\"15.294\"/><rect x=\"11.148\" y=\"4.059\" width=\"1.527\" height=\"15.294\"/><rect x=\"14.971\" y=\"4.059\" width=\"1.529\" height=\"8.412\"/></svg>",
"google-plus": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.9,9c0,2.7-0.6,5-3.2,6.3c-3.7,1.8-8.1,0.2-9.4-3.6C-1.1,7.6,1.9,3.3,6.1,3c1.7-0.1,3.2,0.3,4.6,1.3 c0.1,0.1,0.3,0.2,0.4,0.4c-0.5,0.5-1.2,1-1.7,1.6c-1-0.8-2.1-1.1-3.5-0.9C5,5.6,4.2,6,3.6,6.7c-1.3,1.3-1.5,3.4-0.5,5 c1,1.7,2.6,2.3,4.6,1.9c1.4-0.3,2.4-1.2,2.6-2.6H6.9V9H12.9z\"/><polygon points=\"20,9 20,11 18,11 18,13 16,13 16,11 14,11 14,9 16,9 16,7 18,7 18,9\"/></svg>",
"google": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M17.86,9.09 C18.46,12.12 17.14,16.05 13.81,17.56 C9.45,19.53 4.13,17.68 2.47,12.87 C0.68,7.68 4.22,2.42 9.5,2.03 C11.57,1.88 13.42,2.37 15.05,3.65 C15.22,3.78 15.37,3.93 15.61,4.14 C14.9,4.81 14.23,5.45 13.5,6.14 C12.27,5.08 10.84,4.72 9.28,4.98 C8.12,5.17 7.16,5.76 6.37,6.63 C4.88,8.27 4.62,10.86 5.76,12.82 C6.95,14.87 9.17,15.8 11.57,15.25 C13.27,14.87 14.76,13.33 14.89,11.75 L10.51,11.75 L10.51,9.09 L17.86,9.09 L17.86,9.09 Z\"/></svg>",
"grid": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"2\" y=\"2\" width=\"3\" height=\"3\"/><rect x=\"8\" y=\"2\" width=\"3\" height=\"3\"/><rect x=\"14\" y=\"2\" width=\"3\" height=\"3\"/><rect x=\"2\" y=\"8\" width=\"3\" height=\"3\"/><rect x=\"8\" y=\"8\" width=\"3\" height=\"3\"/><rect x=\"14\" y=\"8\" width=\"3\" height=\"3\"/><rect x=\"2\" y=\"14\" width=\"3\" height=\"3\"/><rect x=\"8\" y=\"14\" width=\"3\" height=\"3\"/><rect x=\"14\" y=\"14\" width=\"3\" height=\"3\"/></svg>",
"happy": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"13\" cy=\"7\" r=\"1\"/><circle cx=\"7\" cy=\"7\" r=\"1\"/><circle fill=\"none\" stroke=\"#000\" cx=\"10\" cy=\"10\" r=\"8.5\"/><path fill=\"none\" stroke=\"#000\" d=\"M14.6,11.4 C13.9,13.3 12.1,14.5 10,14.5 C7.9,14.5 6.1,13.3 5.4,11.4\"/></svg>",
@ -131,6 +132,7 @@
"tablet": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"none\" stroke=\"#000\" d=\"M5,18.5 C4.2,18.5 3.5,17.8 3.5,17 L3.5,3 C3.5,2.2 4.2,1.5 5,1.5 L16,1.5 C16.8,1.5 17.5,2.2 17.5,3 L17.5,17 C17.5,17.8 16.8,18.5 16,18.5 L5,18.5 L5,18.5 L5,18.5 Z\"/><circle cx=\"10.5\" cy=\"16.3\" r=\".8\"/></svg>",
"tag": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"none\" stroke=\"#000\" stroke-width=\"1.1\" d=\"M17.5,3.71 L17.5,7.72 C17.5,7.96 17.4,8.2 17.21,8.39 L8.39,17.2 C7.99,17.6 7.33,17.6 6.93,17.2 L2.8,13.07 C2.4,12.67 2.4,12.01 2.8,11.61 L11.61,2.8 C11.81,2.6 12.08,2.5 12.34,2.5 L16.19,2.5 C16.52,2.5 16.86,2.63 17.11,2.88 C17.35,3.11 17.48,3.4 17.5,3.71 L17.5,3.71 Z\"/><circle cx=\"14\" cy=\"6\" r=\"1\"/></svg>",
"thumbnails": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><rect fill=\"none\" stroke=\"#000\" x=\"3.5\" y=\"3.5\" width=\"5\" height=\"5\"/><rect fill=\"none\" stroke=\"#000\" x=\"11.5\" y=\"3.5\" width=\"5\" height=\"5\"/><rect fill=\"none\" stroke=\"#000\" x=\"11.5\" y=\"11.5\" width=\"5\" height=\"5\"/><rect fill=\"none\" stroke=\"#000\" x=\"3.5\" y=\"11.5\" width=\"5\" height=\"5\"/></svg>",
"tiktok": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M17.24,6V8.82a6.79,6.79,0,0,1-4-1.28v5.81A5.26,5.26,0,1,1,8,8.1a4.36,4.36,0,0,1,.72.05v2.9A2.57,2.57,0,0,0,7.64,11a2.4,2.4,0,1,0,2.77,2.38V2h2.86a4,4,0,0,0,1.84,3.38A4,4,0,0,0,17.24,6Z\"/></svg>",
"trash": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><polyline fill=\"none\" stroke=\"#000\" points=\"6.5 3 6.5 1.5 13.5 1.5 13.5 3\"/><polyline fill=\"none\" stroke=\"#000\" points=\"4.5 4 4.5 18.5 15.5 18.5 15.5 4\"/><rect x=\"8\" y=\"7\" width=\"1\" height=\"9\"/><rect x=\"11\" y=\"7\" width=\"1\" height=\"9\"/><rect x=\"2\" y=\"3\" width=\"16\" height=\"1\"/></svg>",
"triangle-down": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><polygon points=\"5 7 15 7 10 12\"/></svg>",
"triangle-left": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><polygon points=\"12 5 7 10 12 15\"/></svg>",
@ -139,6 +141,7 @@
"tripadvisor": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M19.021,7.866C19.256,6.862,20,5.854,20,5.854h-3.346C14.781,4.641,12.504,4,9.98,4C7.363,4,4.999,4.651,3.135,5.876H0\tc0,0,0.738,0.987,0.976,1.988c-0.611,0.837-0.973,1.852-0.973,2.964c0,2.763,2.249,5.009,5.011,5.009\tc1.576,0,2.976-0.737,3.901-1.879l1.063,1.599l1.075-1.615c0.475,0.611,1.1,1.111,1.838,1.451c1.213,0.547,2.574,0.612,3.825,0.15\tc2.589-0.963,3.913-3.852,2.964-6.439c-0.175-0.463-0.4-0.876-0.675-1.238H19.021z M16.38,14.594\tc-1.002,0.371-2.088,0.328-3.06-0.119c-0.688-0.317-1.252-0.817-1.657-1.438c-0.164-0.25-0.313-0.52-0.417-0.811\tc-0.124-0.328-0.186-0.668-0.217-1.014c-0.063-0.689,0.037-1.396,0.339-2.043c0.448-0.971,1.251-1.71,2.25-2.079\tc2.075-0.765,4.375,0.3,5.14,2.366c0.762,2.066-0.301,4.37-2.363,5.134L16.38,14.594L16.38,14.594z M8.322,13.066\tc-0.72,1.059-1.935,1.76-3.309,1.76c-2.207,0-4.001-1.797-4.001-3.996c0-2.203,1.795-4.002,4.001-4.002\tc2.204,0,3.999,1.8,3.999,4.002c0,0.137-0.024,0.261-0.04,0.396c-0.067,0.678-0.284,1.313-0.648,1.853v-0.013H8.322z M2.472,10.775\tc0,1.367,1.112,2.479,2.476,2.479c1.363,0,2.472-1.11,2.472-2.479c0-1.359-1.11-2.468-2.472-2.468\tC3.584,8.306,2.473,9.416,2.472,10.775L2.472,10.775z M12.514,10.775c0,1.367,1.104,2.479,2.471,2.479\tc1.363,0,2.474-1.108,2.474-2.479c0-1.359-1.11-2.468-2.474-2.468c-1.364,0-2.477,1.109-2.477,2.468H12.514z M3.324,10.775\tc0-0.893,0.726-1.618,1.614-1.618c0.889,0,1.625,0.727,1.625,1.618c0,0.898-0.725,1.627-1.625,1.627\tc-0.901,0-1.625-0.729-1.625-1.627H3.324z M13.354,10.775c0-0.893,0.726-1.618,1.627-1.618c0.886,0,1.61,0.727,1.61,1.618\tc0,0.898-0.726,1.627-1.626,1.627s-1.625-0.729-1.625-1.627H13.354z M9.977,4.875c1.798,0,3.425,0.324,4.849,0.968\tc-0.535,0.015-1.061,0.108-1.586,0.3c-1.264,0.463-2.264,1.388-2.815,2.604c-0.262,0.551-0.398,1.133-0.448,1.72\tC9.79,7.905,7.677,5.873,5.076,5.82C6.501,5.208,8.153,4.875,9.94,4.875H9.977z\"/></svg>",
"tumblr": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.885,8.598c0,0,0,3.393,0,4.996c0,0.282,0,0.66,0.094,0.942c0.377,1.509,1.131,2.545,2.545,3.11 c1.319,0.472,2.356,0.472,3.676,0c0.565-0.188,1.132-0.659,1.132-0.659l-0.849-2.263c0,0-1.036,0.378-1.603,0.283 c-0.565-0.094-1.226-0.66-1.226-1.508c0-1.603,0-4.902,0-4.902h2.828V5.771h-2.828V2H8.205c0,0-0.094,0.66-0.188,0.942 C7.828,3.791,7.262,4.733,6.603,5.394C5.848,6.147,5,6.43,5,6.43v2.168H6.885z\"/></svg>",
"tv": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"7\" y=\"16\" width=\"6\" height=\"1\"/><rect fill=\"none\" stroke=\"#000\" x=\".5\" y=\"3.5\" width=\"19\" height=\"11\"/></svg>",
"twitch": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.23,1,2,4.23V15.85H5.88v3.23L9.1,15.85h2.59L17.5,10V1Zm11,8.4L13.62,12H11L8.78,14.24V12H5.88V2.29H16.21Z\"/><rect x=\"12.98\" y=\"4.55\" width=\"1.29\" height=\"3.88\"/><rect x=\"9.43\" y=\"4.55\" width=\"1.29\" height=\"3.88\"/></svg>",
"twitter": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M19,4.74 C18.339,5.029 17.626,5.229 16.881,5.32 C17.644,4.86 18.227,4.139 18.503,3.28 C17.79,3.7 17.001,4.009 16.159,4.17 C15.485,3.45 14.526,3 13.464,3 C11.423,3 9.771,4.66 9.771,6.7 C9.771,6.99 9.804,7.269 9.868,7.539 C6.795,7.38 4.076,5.919 2.254,3.679 C1.936,4.219 1.754,4.86 1.754,5.539 C1.754,6.82 2.405,7.95 3.397,8.61 C2.79,8.589 2.22,8.429 1.723,8.149 L1.723,8.189 C1.723,9.978 2.997,11.478 4.686,11.82 C4.376,11.899 4.049,11.939 3.713,11.939 C3.475,11.939 3.245,11.919 3.018,11.88 C3.49,13.349 4.852,14.419 6.469,14.449 C5.205,15.429 3.612,16.019 1.882,16.019 C1.583,16.019 1.29,16.009 1,15.969 C2.635,17.019 4.576,17.629 6.662,17.629 C13.454,17.629 17.17,12 17.17,7.129 C17.17,6.969 17.166,6.809 17.157,6.649 C17.879,6.129 18.504,5.478 19,4.74\"/></svg>",
"uikit": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><polygon points=\"14.4,3.1 11.3,5.1 15,7.3 15,12.9 10,15.7 5,12.9 5,8.5 2,6.8 2,14.8 9.9,19.5 18,14.8 18,5.3\"/><polygon points=\"9.8,4.2 6.7,2.4 9.8,0.4 12.9,2.3\"/></svg>",
"unlock": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><rect fill=\"none\" stroke=\"#000\" x=\"3.5\" y=\"8.5\" width=\"13\" height=\"10\"/><path fill=\"none\" stroke=\"#000\" d=\"M6.5,8.5 L6.5,4.9 C6.5,3 8.1,1.5 10,1.5 C11.9,1.5 13.5,3 13.5,4.9\"/></svg>",
@ -164,4 +167,4 @@
return plugin;
})));
}));

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

1
src/assets/lib/base/uikit-rtl.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -186,6 +186,10 @@
border-bottom-color: @dark-mode-background-1;
}
.uk-table-striped > tr:nth-of-type(2n):last-child, .uk-table-striped tbody tr:nth-of-type(2n):last-child {
border-bottom: 1px solid @dark-mode-background-2;
}
// General (List)
.uk-list {
background: @dark-mode-background-2;
@ -449,6 +453,16 @@
background: @dark-mode-background-2 !important;
}
.merchant-mode-overlay {
background: @dark-mode-background-1 !important;
.merchant-mode-logo {
background: url('../../assets/img/nault-logo-night-mode.svg');
background-size: contain;
background-repeat: no-repeat;
}
}
// Representatives page
.delegating-account-row, .representative-row {
background: @dark-mode-background-3 !important;

View file

@ -575,6 +575,10 @@
border-left-color: @global-primary-background;
color: @global-primary-background;
}
> .uk-grid-stack {
flex: 1;
}
}
.label-new {
@ -582,8 +586,10 @@
margin: -10px 0px -10px -9px;
> .uk-badge {
display: flex;
height: 22px;
font-size: 16px;
padding-bottom: 2px;
padding: 1px 0 0 0;
}
}

View file

@ -28,7 +28,7 @@ h1, h2, h3, h4, h5, .uk-text-lead, .uk-button, .uk-alert, .uk-description-list d
@media (max-width: 939px) {
.nlt-button-group button {
margin-bottom: @nlt-intro-margin / 2 !important;
margin-bottom: 20px !important;
}
h2:not(.uk-card-title):not(.uk-modal-title) {
@ -1336,6 +1336,30 @@ input[type=number] {
}
}
// Receive page
.merchant-centered-container {
.identicon-name-row {
display: flex;
flex-direction: row;
align-items: center;
height: 28px;
padding-bottom: 8px;
.nano-identicon {
display: inline-block;
width: 27px;
height: 27px;
margin-right: 12px;
margin-left: 1px;
flex-shrink: 0;
.canvas-container canvas {
border-radius: 3px;
}
}
}
}
// Representatives page
.delegating-account-row {
border-top: none !important;
@ -1527,6 +1551,14 @@ input[type=number] {
background-color: #16A670 !important;
}
.nlt-button-green {
background-color: #16A670 !important;
&:hover {
background-color: #069660 !important;
}
}
.nlt-page-intro {
margin-bottom: @nlt-intro-margin;
}

View file

@ -13,18 +13,12 @@ import '@angular/localize/init';
// (window as any).global = window;
global.Buffer = global.Buffer || require('buffer').Buffer;
/**
* Required to support Web Animations `@angular/platform-browser/animations`.
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
**/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
import 'zone.js'; // Included with Angular CLI.

View file

@ -22,7 +22,9 @@ __karma__.loaded = function () {};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
platformBrowserDynamicTesting(), {
teardown: { destroyAfterEach: false }
}
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig.base.json",
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"baseUrl": "./",

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig.base.json",
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"baseUrl": "./",

View file

@ -1,27 +0,0 @@
{
"compileOnSave": false,
"compilerOptions": {
"downlevelIteration": true,
"importHelpers": true,
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types",
"./src/typings"
],
"lib": [
"es2017",
"dom"
],
"module": "es2020",
"baseUrl": "./",
"paths": {
"stream": ["../node_modules/readable-stream/readable.js"]
}
}
}

View file

@ -1,17 +1,27 @@
/*
This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScripts language server to improve development experience.
It is not intended to be used to perform a compilation.
To learn more about this file see: https://angular.io/config/solution-tsconfig.
*/
{
"files": [],
"references": [
{
"path": "./src/tsconfig.app.json"
},
{
"path": "./src/tsconfig.spec.json"
"compileOnSave": false,
"compilerOptions": {
"downlevelIteration": true,
"importHelpers": true,
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"typeRoots": [
"node_modules/@types",
"./src/typings"
],
"lib": [
"es2020",
"dom"
],
"module": "es2020",
"baseUrl": "./",
"paths": {
"stream": ["../node_modules/readable-stream/readable.js"]
}
]
}
}

View file

@ -7,7 +7,6 @@
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2015",
"typeRoots": [

View file

@ -1,141 +0,0 @@
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"arrow-return-shorthand": true,
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": [true, "ignore-same-line"],
"deprecation": {
"severity": "warn"
},
"eofline": true,
"forin": true,
"import-blacklist": [
true,
"rxjs/Rx"
],
"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,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-misused-new": true,
"no-non-null-assertion": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unnecessary-initializer": true,
"no-unused-expression": 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": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"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"
],
"no-output-on-prefix": true,
"no-inputs-metadata-property": true,
"no-outputs-metadata-property": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-output-rename": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true
}
}