mirror of
https://github.com/FJurmanovic/wallet-web.git
synced 2026-02-06 06:08:10 +00:00
Merge branch 'feature/WW-26-architecture'
This commit is contained in:
4
.babelrc
4
.babelrc
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"presets": [
|
"presets": [
|
||||||
"@babel/preset-env",
|
["@babel/preset-env", {"modules": false}],
|
||||||
"@babel/preset-typescript"
|
["@babel/preset-typescript", {"modules": false}]
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -1,20 +1,37 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"es2021": true
|
|
||||||
},
|
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
"plugin:@typescript-eslint/recommended"
|
"prettier"
|
||||||
],
|
],
|
||||||
"parser": "@typescript-eslint/parser",
|
"env": {
|
||||||
"parserOptions": {
|
"browser": true,
|
||||||
"ecmaVersion": 12,
|
"node": true,
|
||||||
"sourceType": "module"
|
"es6": true
|
||||||
|
},
|
||||||
|
"parser": "babel-eslint",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 6,
|
||||||
|
"sourceType": "module",
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"modules": true,
|
||||||
|
"experimentalObjectRestSpread": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"__CONFIG__": true
|
||||||
},
|
},
|
||||||
"plugins": [
|
|
||||||
"@typescript-eslint"
|
|
||||||
],
|
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"no-multiple-empty-lines": [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
"max": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-unused-vars": [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
"ignoreRestSiblings": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
10
.prettierrc
Normal file
10
.prettierrc
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 120,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": true,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"jsxBracketSameLine": false
|
||||||
|
}
|
||||||
18126
package-lock.json
generated
18126
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
32
package.json
32
package.json
@@ -7,36 +7,42 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "webpack serve --mode development --hot",
|
"start": "webpack serve --mode development --hot",
|
||||||
"build": "webpack --mode production",
|
"build": "webpack --mode production",
|
||||||
"format": "eslint"
|
"format": "prettier --write src/**/*.{js,ts,html}"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@github/catalyst": "^1.1.3",
|
||||||
|
"core/utils": "^1.4.1",
|
||||||
|
"validator": "^13.6.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
"@babel/core": "^7.14.3",
|
"@babel/core": "^7.14.3",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||||
"@babel/plugin-proposal-decorators": "^7.14.2",
|
"@babel/plugin-proposal-decorators": "^7.14.2",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^7.14.2",
|
"@babel/plugin-proposal-object-rest-spread": "^7.14.2",
|
||||||
"@babel/preset-env": "^7.14.2",
|
"@babel/preset-env": "^7.14.2",
|
||||||
"@babel/preset-typescript": "^7.13.0",
|
"@babel/preset-typescript": "^7.13.0",
|
||||||
"@github/catalyst": "^1.1.3",
|
"@typescript-eslint/eslint-plugin": "^4.26.0",
|
||||||
"@github/jtml": "^0.4.0",
|
"@typescript-eslint/parser": "^4.26.0",
|
||||||
"babel-loader": "^8.2.2",
|
"babel-loader": "^8.2.2",
|
||||||
"babel-plugin-module-resolver": "^4.1.0",
|
"babel-plugin-module-resolver": "^4.1.0",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
|
"compression-webpack-plugin": "^8.0.0",
|
||||||
"connect-history-api-fallback": "^1.6.0",
|
"connect-history-api-fallback": "^1.6.0",
|
||||||
"css-loader": "^5.2.6",
|
"css-loader": "^5.2.6",
|
||||||
|
"eslint": "^7.28.0",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-loader": "^4.0.2",
|
||||||
|
"eslint-plugin-import": "^2.23.4",
|
||||||
"html-webpack-plugin": "^5.3.1",
|
"html-webpack-plugin": "^5.3.1",
|
||||||
"node-sass": "^6.0.0",
|
"node-sass": "^6.0.0",
|
||||||
|
"prettier": "^2.3.1",
|
||||||
"sass-loader": "^11.1.1",
|
"sass-loader": "^11.1.1",
|
||||||
"sass-to-string": "^1.5.1",
|
"sass-to-string": "^1.5.1",
|
||||||
"validator": "^13.6.0",
|
|
||||||
"webpack": "^5.38.1",
|
|
||||||
"webpack-dev-server": "^3.11.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@typescript-eslint/eslint-plugin": "^4.26.0",
|
|
||||||
"@typescript-eslint/parser": "^4.26.0",
|
|
||||||
"compression-webpack-plugin": "^8.0.0",
|
|
||||||
"eslint": "^7.27.0",
|
|
||||||
"terser-webpack-plugin": "^5.1.3",
|
"terser-webpack-plugin": "^5.1.3",
|
||||||
"webpack-cli": "^4.7.0"
|
"uglify-js": "^3.13.9",
|
||||||
|
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||||
|
"webpack": "^5.38.1",
|
||||||
|
"webpack-cli": "^4.7.0",
|
||||||
|
"webpack-dev-server": "^3.11.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BaseElement } from "common/";
|
import { BaseElement } from 'common/';
|
||||||
|
|
||||||
class BaseComponentElement extends BaseElement {}
|
class BaseComponentElement extends BaseElement {}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export { default as BaseComponentElement } from "./BaseComponentElement/BaseComponentElement";
|
export { default as BaseComponentElement } from './BaseComponentElement/BaseComponentElement';
|
||||||
|
|||||||
@@ -1,142 +1,133 @@
|
|||||||
import { html, render, TemplateResult } from "@github/jtml";
|
import { html, render, TemplateResult } from 'core/utils';
|
||||||
import {
|
import { AppLoaderElement, AppMainElement, AppModalElement, AppRootElement } from 'components/';
|
||||||
AppLoaderElement,
|
import { AppService, RouterService } from 'core/services';
|
||||||
AppMainElement,
|
import { AuthStore } from 'core/store';
|
||||||
AppModalElement,
|
import { closest } from 'core/utils';
|
||||||
AppRootElement,
|
|
||||||
} from "components/";
|
|
||||||
import { AppService, RouterService } from "core/services";
|
|
||||||
import { AuthStore } from "core/store";
|
|
||||||
import { closest } from "core/utils";
|
|
||||||
|
|
||||||
class BaseElement extends HTMLElement {
|
class BaseElement extends HTMLElement {
|
||||||
@closest appMain: AppMainElement;
|
@closest appMain: AppMainElement;
|
||||||
private _appMain: AppMainElement;
|
private _appMain: AppMainElement;
|
||||||
public loader: Loader;
|
public loader: Loader;
|
||||||
private elementDisconnectCallbacks: Array<Function> = [];
|
private elementDisconnectCallbacks: Array<Function> = [];
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.connectedCallback = this.connectedCallback.bind(this);
|
this.connectedCallback = this.connectedCallback.bind(this);
|
||||||
this.disconnectedCallback = this.disconnectedCallback.bind(this);
|
this.disconnectedCallback = this.disconnectedCallback.bind(this);
|
||||||
this.loader = new Loader(this);
|
this.loader = new Loader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get routerService(): RouterService {
|
public get routerService(): RouterService {
|
||||||
return this.appMain?.routerService;
|
return this.appMain?.routerService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get authStore(): AuthStore {
|
public get authStore(): AuthStore {
|
||||||
return this.appMain?.authStore;
|
return this.appMain?.authStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get appService(): AppService {
|
public get appService(): AppService {
|
||||||
return this.appMain?.appService;
|
return this.appMain?.appService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get appModal(): AppModalElement {
|
public get appModal(): AppModalElement {
|
||||||
return this.appMain?.appModal;
|
return this.appMain?.appModal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get mainRoot(): AppRootElement {
|
public get mainRoot(): AppRootElement {
|
||||||
return this.appMain?.mainRoot;
|
return this.appMain?.mainRoot;
|
||||||
}
|
}
|
||||||
public get appLoader(): AppLoaderElement {
|
public get appLoader(): AppLoaderElement {
|
||||||
return this.appMain?.appLoader;
|
return this.appMain?.appLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get isAuth(): boolean {
|
public get isAuth(): boolean {
|
||||||
return this.appMain?.isAuth();
|
return this.appMain?.isAuth();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bindEvents = (attrName): void => {
|
public bindEvents = (attrName): void => {
|
||||||
const _elems = this.querySelectorAll(`[${attrName}]`);
|
const _elems = this.querySelectorAll(`[${attrName}]`);
|
||||||
_elems?.forEach((el) => {
|
_elems?.forEach((el) => {
|
||||||
for (const action of (el.getAttribute(attrName) || "")
|
for (const action of (el.getAttribute(attrName) || '').trim().split(/\s+/)) {
|
||||||
.trim()
|
const eventSep = action.lastIndexOf(':');
|
||||||
.split(/\s+/)) {
|
const methodSep = action.lastIndexOf('#');
|
||||||
const eventSep = action.lastIndexOf(":");
|
const tag = action.slice(eventSep + 1, methodSep);
|
||||||
const methodSep = action.lastIndexOf("#");
|
|
||||||
const tag = action.slice(eventSep + 1, methodSep);
|
|
||||||
|
|
||||||
const type = action.slice(0, eventSep);
|
const type = action.slice(0, eventSep);
|
||||||
const method = action.slice(methodSep + 1);
|
const method = action.slice(methodSep + 1);
|
||||||
|
|
||||||
if (tag.toUpperCase() === this.tagName) {
|
if (tag.toUpperCase() === this.tagName) {
|
||||||
el.addEventListener(type, this?.[method]);
|
el.addEventListener(type, this?.[method]);
|
||||||
const _callback = () =>
|
const _callback = () => el.removeEventListener(type, this?.[method]);
|
||||||
el.removeEventListener(type, this?.[method]);
|
this.elementDisconnectCallbacks.push(_callback);
|
||||||
this.elementDisconnectCallbacks.push(_callback);
|
} else {
|
||||||
} else {
|
this.childNodes.forEach((child: HTMLElement) => {
|
||||||
this.childNodes.forEach((child: HTMLElement) => {
|
if (child.tagName == tag.toUpperCase()) {
|
||||||
if (child.tagName == tag.toUpperCase()) {
|
el.addEventListener(type, child?.[method]);
|
||||||
el.addEventListener(type, child?.[method]);
|
const _callback = () => el.removeEventListener(type, child?.[method]);
|
||||||
const _callback = () =>
|
this.elementDisconnectCallbacks.push(_callback);
|
||||||
el.removeEventListener(type, child?.[method]);
|
}
|
||||||
this.elementDisconnectCallbacks.push(_callback);
|
});
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
}
|
};
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html``;
|
return html``;
|
||||||
};
|
};
|
||||||
|
|
||||||
updateCallback = (): void => {};
|
updateCallback = (): void => {};
|
||||||
|
|
||||||
update = (): void => {
|
update = (): void => {
|
||||||
render(this.render(), this);
|
render(this.render(), this);
|
||||||
this.bindEvents("data-action");
|
this.bindEvents('data-action');
|
||||||
this.bindEvents("app-action");
|
this.bindEvents('app-action');
|
||||||
this.updateCallback();
|
this.updateCallback();
|
||||||
};
|
};
|
||||||
|
|
||||||
connectedCallback(): void {
|
connectedCallback(): void {
|
||||||
this.elementConnected();
|
this.elementConnected();
|
||||||
this._appMain = this.appMain;
|
this._appMain = this.appMain;
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback(): void {
|
disconnectedCallback(): void {
|
||||||
const { _appMain } = this;
|
const { _appMain } = this;
|
||||||
this.elementDisconnected(_appMain);
|
this.elementDisconnected(_appMain);
|
||||||
if (Array.isArray(this.elementDisconnectCallbacks)) {
|
if (Array.isArray(this.elementDisconnectCallbacks)) {
|
||||||
this.elementDisconnectCallbacks.forEach((callback: Function) => {
|
this.elementDisconnectCallbacks.forEach((callback: Function) => {
|
||||||
if (typeof callback == "function") {
|
if (typeof callback == 'function') {
|
||||||
callback(_appMain);
|
callback(_appMain);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
elementDisconnected = (appMain: AppMainElement): void => {};
|
elementDisconnected = (appMain: AppMainElement): void => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BaseElement;
|
export default BaseElement;
|
||||||
|
|
||||||
class Loader {
|
class Loader {
|
||||||
private _loading: number = 0;
|
private _loading: number = 0;
|
||||||
|
|
||||||
constructor(private _main: BaseElement) {}
|
constructor(private _main: BaseElement) {}
|
||||||
|
|
||||||
public start = () => {
|
public start = () => {
|
||||||
this._loading++;
|
this._loading++;
|
||||||
this._main?.update?.();
|
this._main?.update?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
public stop = () => {
|
public stop = () => {
|
||||||
if (this._loading > 0) {
|
if (this._loading > 0) {
|
||||||
this._loading--;
|
this._loading--;
|
||||||
this._main?.update?.();
|
this._main?.update?.();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public get loading() {
|
public get loading() {
|
||||||
return this._loading > 0;
|
return this._loading > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
86
src/common/core/Validator/Validator.ts
Normal file
86
src/common/core/Validator/Validator.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import { AppFormElement } from 'components/';
|
||||||
|
import { validatorErrors } from 'core/constants';
|
||||||
|
import { firstUpper, validator } from 'core/utils';
|
||||||
|
|
||||||
|
class Validator {
|
||||||
|
public _error: string;
|
||||||
|
public _valid: boolean;
|
||||||
|
constructor(public input: any, public form: AppFormElement, public rules: string) {}
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.input?._value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get name() {
|
||||||
|
return this.input?.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
get error() {
|
||||||
|
return this._error;
|
||||||
|
}
|
||||||
|
|
||||||
|
set error(error) {
|
||||||
|
this._error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
get valid() {
|
||||||
|
return this._valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
set valid(error) {
|
||||||
|
this._valid = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
validate = () => {
|
||||||
|
const rules = this.rules?.split('|').filter((a) => a);
|
||||||
|
const value = this.value;
|
||||||
|
const validArr = rules
|
||||||
|
.slice()
|
||||||
|
.reverse()
|
||||||
|
.map((rule) => {
|
||||||
|
let args = [];
|
||||||
|
if (rule.includes('[') && rule.includes(']')) {
|
||||||
|
const begSep = rule.lastIndexOf('[');
|
||||||
|
const endSep = rule.lastIndexOf(']');
|
||||||
|
|
||||||
|
args = rule
|
||||||
|
.slice(begSep + 1, endSep)
|
||||||
|
.split(',')
|
||||||
|
.map((arg: string) => {
|
||||||
|
if (this.form && arg?.includes?.('field')) {
|
||||||
|
const begBr = arg.lastIndexOf('(');
|
||||||
|
const endBr = arg.lastIndexOf(')');
|
||||||
|
const field = arg.slice(begBr + 1, endBr);
|
||||||
|
|
||||||
|
return this.form?.values[field];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
rule = rule.slice(0, begSep);
|
||||||
|
}
|
||||||
|
let validRule = validator?.[rule];
|
||||||
|
let ruleArray = validRule ? Array.isArray(validRule) : false;
|
||||||
|
let valid = true;
|
||||||
|
|
||||||
|
if (validRule) {
|
||||||
|
if (ruleArray) {
|
||||||
|
valid = validRule?.[0]?.(value, ...args);
|
||||||
|
} else {
|
||||||
|
valid = validRule?.(value, ...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!valid) {
|
||||||
|
const error = validatorErrors[rule]?.replaceAll('{- name}', firstUpper(this.name?.toString()));
|
||||||
|
this.error = ruleArray ? validRule?.[1]?.replaceAll('{- name}', firstUpper(this.name?.toString())) : error;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
});
|
||||||
|
const _return = validArr?.includes(false);
|
||||||
|
if (_return) {
|
||||||
|
this.error = null;
|
||||||
|
}
|
||||||
|
this.valid = !_return;
|
||||||
|
return !_return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Validator;
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
export { default as BaseElement } from "./core/BaseElement/BaseElement";
|
export { default as BaseElement } from './core/BaseElement/BaseElement';
|
||||||
export * from "./layouts";
|
export { default as Validator } from './core/Validator/Validator';
|
||||||
export * from "./components";
|
|
||||||
export * from "./pages";
|
export * from './layouts';
|
||||||
|
export * from './components';
|
||||||
|
export * from './pages';
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import { target } from "@github/catalyst";
|
import { target } from '@github/catalyst';
|
||||||
import { BaseElement } from "common/";
|
import { BaseElement } from 'common/';
|
||||||
|
|
||||||
class BaseLayoutElement extends BaseElement {
|
class BaseLayoutElement extends BaseElement {
|
||||||
@target appSlot: HTMLElement;
|
@target appSlot: HTMLElement;
|
||||||
public isLayout: boolean = true;
|
public isLayout: boolean = true;
|
||||||
public _appSlot: string;
|
public _appSlot: string;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
get slotTag(): string {
|
get slotTag(): string {
|
||||||
return this.appSlot?.firstElementChild?.tagName;
|
return this.appSlot?.firstElementChild?.tagName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compareTags = (tag: string | HTMLElement): boolean => {
|
compareTags = (tag: string | HTMLElement): boolean => {
|
||||||
if (typeof tag === "string") {
|
if (typeof tag === 'string') {
|
||||||
return this.slotTag === tag;
|
return this.slotTag === tag;
|
||||||
}
|
}
|
||||||
return tag?.tagName === this.slotTag;
|
return tag?.tagName === this.slotTag;
|
||||||
};
|
};
|
||||||
|
|
||||||
setElement = (newTag: string): void => {
|
setElement = (newTag: string): void => {
|
||||||
const _appSlot = `<div data-target="base-layout.content"><${newTag}></${newTag}></div>`;
|
const _appSlot = `<div data-target="base-layout.content"><${newTag}></${newTag}></div>`;
|
||||||
this._appSlot = _appSlot;
|
this._appSlot = _appSlot;
|
||||||
this.appSlot.innerHTML = _appSlot;
|
this.appSlot.innerHTML = _appSlot;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BaseLayoutElement;
|
export default BaseLayoutElement;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export { default as BaseLayoutElement } from "./BaseLayoutElement/BaseLayoutElement";
|
export { default as BaseLayoutElement } from './BaseLayoutElement/BaseLayoutElement';
|
||||||
|
|||||||
@@ -1,45 +1,43 @@
|
|||||||
import { attr } from "@github/catalyst";
|
import { attr } from '@github/catalyst';
|
||||||
import { html, render } from "@github/jtml";
|
import { html, render } from 'core/utils';
|
||||||
import { BaseElement } from "common/";
|
import { BaseElement } from 'common/';
|
||||||
import { isTrue } from "core/utils";
|
import { isTrue } from 'core/utils';
|
||||||
|
|
||||||
class BasePageElement extends BaseElement {
|
class BasePageElement extends BaseElement {
|
||||||
public pageTitle: string = "";
|
public pageTitle: string = '';
|
||||||
@attr hidetitle: string;
|
@attr hidetitle: string;
|
||||||
@attr customtitle: string;
|
@attr customtitle: string;
|
||||||
constructor(options: OptionType) {
|
constructor(options: OptionType) {
|
||||||
super();
|
super();
|
||||||
if (options?.title) {
|
if (options?.title) {
|
||||||
this.pageTitle = options?.title;
|
this.pageTitle = options?.title;
|
||||||
}
|
}
|
||||||
this.connectedCallback = this.connectedCallback.bind(this);
|
this.connectedCallback = this.connectedCallback.bind(this);
|
||||||
this.disconnectedCallback = this.disconnectedCallback.bind(this);
|
this.disconnectedCallback = this.disconnectedCallback.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public renderTitle = () => {
|
public renderTitle = () => {
|
||||||
if (!isTrue(this.hidetitle)) {
|
if (!isTrue(this.hidetitle)) {
|
||||||
return html`<div class="page --title">
|
return html`<div class="page --title">${this.customtitle ? this.customtitle : this.pageTitle}</div>`;
|
||||||
${this.customtitle ? this.customtitle : this.pageTitle}
|
}
|
||||||
</div>`;
|
return html``;
|
||||||
}
|
};
|
||||||
return html``;
|
|
||||||
};
|
|
||||||
|
|
||||||
update = (): void => {
|
update = (): void => {
|
||||||
const _render = () => html` ${this.renderTitle()} ${this.render()} `;
|
const _render = () => html` ${this.renderTitle()} ${this.render()} `;
|
||||||
render(_render(), this);
|
render(_render(), this);
|
||||||
this.bindEvents();
|
this.bindEvents('app-action');
|
||||||
this.updateCallback();
|
this.updateCallback();
|
||||||
};
|
};
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this.appMain.setTitle(this.pageTitle);
|
this.appMain.setTitle(this.pageTitle);
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BasePageElement;
|
export default BasePageElement;
|
||||||
|
|
||||||
export type OptionType = {
|
export type OptionType = {
|
||||||
title?: string;
|
title?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export { default as BasePageElement } from "./BasePageElement/BasePageElement";
|
export { default as BasePageElement } from './BasePageElement/BasePageElement';
|
||||||
|
|||||||
@@ -1,241 +1,212 @@
|
|||||||
import { attr, controller, target } from "@github/catalyst";
|
import { attr, controller, target } from '@github/catalyst';
|
||||||
import { findMethod, firstUpper } from "core/utils";
|
import { closest, findMethod, firstUpper } from 'core/utils';
|
||||||
import { html } from "@github/jtml";
|
import { html } from 'core/utils';
|
||||||
import randomId from "core/utils/random-id";
|
import randomId from 'core/utils/random-id';
|
||||||
import validator from "validator";
|
import { validatorErrors } from 'core/constants';
|
||||||
import { validatorErrors } from "core/constants";
|
import { BaseComponentElement, Validator } from 'common/';
|
||||||
import { BaseComponentElement } from "common/";
|
import { AppFormElement } from 'components/app-form/AppFormElement';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppDropdownElement extends BaseComponentElement {
|
class AppDropdownElement extends BaseComponentElement {
|
||||||
@attr name: string;
|
@attr name: string;
|
||||||
@attr label: string;
|
@attr label: string;
|
||||||
@attr rules: string;
|
@attr rules: string;
|
||||||
@target main: HTMLElement;
|
@target main: HTMLElement;
|
||||||
@target inp: HTMLElement;
|
@target inp: HTMLElement;
|
||||||
@attr displaykey: string = "name";
|
@target dropdowncontainer: HTMLElement;
|
||||||
@attr valuekey: string = "id";
|
@attr displaykey: string = 'name';
|
||||||
@attr fetch: string;
|
@attr valuekey: string = 'id';
|
||||||
fetchFunc: any;
|
@attr fetch: string;
|
||||||
|
@closest appForm: AppFormElement;
|
||||||
|
|
||||||
error: boolean;
|
errorMessage: string;
|
||||||
errorMessage: string;
|
|
||||||
|
|
||||||
searchPhrase: string;
|
searchPhrase: string;
|
||||||
|
|
||||||
randId: string;
|
randId: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
|
||||||
@attr isOpen: boolean = false;
|
@attr isOpen: boolean = false;
|
||||||
|
|
||||||
items: Array<any>;
|
items: Array<any>;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
page: number = 1;
|
page: number = 1;
|
||||||
rpp: number = 30;
|
rpp: number = 30;
|
||||||
|
validator: Validator;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
getItems = async (options?: any): Promise<void> => {
|
|
||||||
if (typeof this.fetchFunc !== "function") return;
|
|
||||||
try {
|
|
||||||
const response = await this.fetchFunc(options);
|
|
||||||
this.setItems(response);
|
|
||||||
} catch (err) {
|
|
||||||
this.update();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setItems = (response): void => {
|
updateCallback = () => {
|
||||||
if (response) {
|
this.dropdowncontainer?.scrollIntoView();
|
||||||
let items = [];
|
};
|
||||||
if (Array.isArray(response)) {
|
|
||||||
items = response;
|
|
||||||
} else if (Array.isArray(response.items)) {
|
|
||||||
items = response.items;
|
|
||||||
this.totalItems = response?.totalRecords;
|
|
||||||
} else {
|
|
||||||
items = [];
|
|
||||||
}
|
|
||||||
this.items = items;
|
|
||||||
this.update();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
get selectedItem() {
|
public elementConnected = (): void => {
|
||||||
const { value, valuekey, items } = this;
|
this.validator = new Validator(this, this.appForm, this.rules);
|
||||||
const item = items?.find((item) => {
|
this.randId = `${name}${randomId()}`;
|
||||||
return value == item[valuekey];
|
this.update();
|
||||||
});
|
|
||||||
|
|
||||||
console.log(item, value, valuekey);
|
const options = {
|
||||||
|
rpp: this.rpp,
|
||||||
|
page: this.page,
|
||||||
|
};
|
||||||
|
this.getItems(options);
|
||||||
|
};
|
||||||
|
|
||||||
return item;
|
attributeChangedCallback(): void {
|
||||||
}
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
get optionValues() {
|
setError = (error) => {
|
||||||
let values = [];
|
this.validator.error = error;
|
||||||
this.inp.childNodes.forEach((item: HTMLElement) => {
|
};
|
||||||
const value = item.getAttribute("value");
|
|
||||||
const name = item.innerText;
|
|
||||||
values.push({ name, value });
|
|
||||||
});
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public elementConnected = (): void => {
|
get error(): string {
|
||||||
this.randId = `${name}${randomId()}`;
|
return this.validator?.error;
|
||||||
this.fetchFunc = findMethod(this.fetch, this.appMain);
|
}
|
||||||
this.update();
|
|
||||||
|
|
||||||
const options = {
|
get isValid(): boolean {
|
||||||
rpp: this.rpp,
|
return this.validator?.valid;
|
||||||
page: this.page,
|
}
|
||||||
};
|
|
||||||
this.getItems(options);
|
|
||||||
};
|
|
||||||
|
|
||||||
attributeChangedCallback(): void {
|
get required(): boolean {
|
||||||
this.update();
|
return this.rules.includes('required');
|
||||||
}
|
}
|
||||||
|
|
||||||
get valid(): boolean {
|
get _value() {
|
||||||
return !!this.error;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get required(): boolean {
|
validate = (): boolean => {
|
||||||
return this.rules.includes("required");
|
return this.validator.validate();
|
||||||
}
|
};
|
||||||
|
|
||||||
validate(): boolean {
|
getItems = async (options?: any): Promise<void> => {
|
||||||
let _return = true;
|
if (typeof this.fetchFunc !== 'function') return;
|
||||||
const rules = this.rules?.split("|").filter((a) => a);
|
try {
|
||||||
const value = (this.inp as HTMLSelectElement)?.value;
|
const response = await this.fetchFunc(options);
|
||||||
rules
|
this.setItems(response);
|
||||||
.slice()
|
} catch (err) {
|
||||||
.reverse()
|
this.update();
|
||||||
.forEach((rule) => {
|
}
|
||||||
let valid = true;
|
};
|
||||||
if (rule == "required") {
|
|
||||||
if (value === "") valid = false;
|
|
||||||
} else {
|
|
||||||
if (validator.hasOwnProperty(rule)) {
|
|
||||||
valid = validator?.[rule]?.(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!valid) {
|
|
||||||
const error = validatorErrors[rule]?.replaceAll(
|
|
||||||
"{- name}",
|
|
||||||
firstUpper(this.name?.toString())
|
|
||||||
);
|
|
||||||
_return = false;
|
|
||||||
this.error = error;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (_return) {
|
|
||||||
this.error = null;
|
|
||||||
}
|
|
||||||
this.update();
|
|
||||||
return _return;
|
|
||||||
}
|
|
||||||
|
|
||||||
openDropdown = () => {
|
setItems = (response): void => {
|
||||||
this.isOpen = true;
|
if (response) {
|
||||||
};
|
let items = [];
|
||||||
|
if (Array.isArray(response)) {
|
||||||
|
items = response;
|
||||||
|
} else if (Array.isArray(response.items)) {
|
||||||
|
items = response.items;
|
||||||
|
this.totalItems = response?.totalRecords;
|
||||||
|
} else {
|
||||||
|
items = [];
|
||||||
|
}
|
||||||
|
this.items = items;
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
stopPropagation = (e) => {
|
get selectedItem() {
|
||||||
e.stopPropagation();
|
const { value, valuekey, items } = this;
|
||||||
};
|
const item = items?.find((item) => {
|
||||||
|
return value == item[valuekey];
|
||||||
|
});
|
||||||
|
|
||||||
toggleDropdown = () => {
|
return item;
|
||||||
const isOpen = this.isOpen;
|
}
|
||||||
this.isOpen = !isOpen;
|
|
||||||
};
|
|
||||||
|
|
||||||
itemSelected = (e) => {
|
get optionValues() {
|
||||||
const value = (e.target as HTMLSpanElement).getAttribute("data-value");
|
let values = [];
|
||||||
this.value = value;
|
this.inp.childNodes.forEach((item: HTMLElement) => {
|
||||||
this.isOpen = false;
|
const value = item.getAttribute('value');
|
||||||
};
|
const name = item.innerText;
|
||||||
|
values.push({ name, value });
|
||||||
|
});
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
get _value() {
|
get fetchFunc() {
|
||||||
return this.value;
|
return findMethod(this.fetch, this.appMain);
|
||||||
}
|
}
|
||||||
|
|
||||||
render = () => {
|
setOpen = (isOpen) => {
|
||||||
const {
|
this.isOpen = isOpen;
|
||||||
label,
|
};
|
||||||
error,
|
|
||||||
errorMessage,
|
|
||||||
isOpen,
|
|
||||||
searchPhrase,
|
|
||||||
items,
|
|
||||||
selectedItem,
|
|
||||||
displaykey,
|
|
||||||
valuekey,
|
|
||||||
} = this;
|
|
||||||
|
|
||||||
console.log(isOpen);
|
openDropdown = () => {
|
||||||
|
this.setOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
const renderItem = (item) => {
|
stopPropagation = (e) => {
|
||||||
return html` <li
|
e.stopPropagation();
|
||||||
class="dropdown-custom-listitem ${selectedItem?.[valuekey] ==
|
};
|
||||||
item[valuekey]
|
|
||||||
? "--selected"
|
|
||||||
: ""}"
|
|
||||||
app-action="click:app-dropdown#itemSelected"
|
|
||||||
data-value="${item[valuekey]}"
|
|
||||||
>
|
|
||||||
${item[displaykey]}
|
|
||||||
</li>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderItems = (_items) => {
|
toggleDropdown = () => {
|
||||||
return _items.map((item) => renderItem(item));
|
const isOpen = this.isOpen;
|
||||||
};
|
this.setOpen(!isOpen);
|
||||||
|
};
|
||||||
|
|
||||||
return html`
|
itemSelected = (e) => {
|
||||||
<div>
|
const value = (e.target as HTMLSpanElement).getAttribute('data-value');
|
||||||
<label app-action="click:app-dropdown#openDropdown">
|
this.setOpen(false);
|
||||||
${label ? html`<div>${label}</div>` : html``}
|
this.setValue(value);
|
||||||
<div
|
this.appForm?.inputChange(e);
|
||||||
class="dropdown-custom"
|
};
|
||||||
app-action="click:app-dropdown#stopPropagation"
|
|
||||||
>
|
setValue = (value) => {
|
||||||
<div
|
this.value = value;
|
||||||
class="dropdown-custom-top"
|
this.update();
|
||||||
app-action="click:app-dropdown#toggleDropdown"
|
};
|
||||||
>
|
|
||||||
<span class="dropdown-custom-fieldname"
|
render = () => {
|
||||||
>${selectedItem
|
const { label, error, errorMessage, isOpen, searchPhrase, items, selectedItem, displaykey, valuekey } = this;
|
||||||
? selectedItem[displaykey]
|
|
||||||
: "Select"}</span
|
const renderItem = (item) => {
|
||||||
>
|
return html` <li
|
||||||
</div>
|
class="dropdown-custom-listitem ${selectedItem?.[valuekey] == item[valuekey] ? '--selected' : ''}"
|
||||||
${isOpen
|
app-action="click:app-dropdown#itemSelected"
|
||||||
? html`
|
data-value="${item[valuekey]}"
|
||||||
<div class="dropdown-custom-open">
|
>
|
||||||
<input
|
${item[displaykey]}
|
||||||
class="dropdown-custom-search"
|
</li>`;
|
||||||
type="text"
|
};
|
||||||
value="${searchPhrase}"
|
|
||||||
app-action="input:app-dropdown#phraseChange"
|
const renderItems = (_items) => {
|
||||||
autofocus
|
return _items?.map((item) => renderItem(item));
|
||||||
/>
|
};
|
||||||
<ul class="dropdown-custom-list">
|
|
||||||
${renderItems(items)}
|
return html`
|
||||||
</ul>
|
<div>
|
||||||
</div>
|
<label app-action="click:app-dropdown#openDropdown">
|
||||||
`
|
${label ? html`<div>${label}</div>` : html``}
|
||||||
: html``}
|
<div class="dropdown-custom" app-action="click:app-dropdown#stopPropagation">
|
||||||
</div>
|
<div class="dropdown-custom-top${isOpen ? ' --open' : ''}" app-action="click:app-dropdown#toggleDropdown">
|
||||||
${error
|
<span class="dropdown-custom-fieldname">${selectedItem ? selectedItem[displaykey] : 'Select'}</span>
|
||||||
? html` <div class="h5 text-red">${errorMessage}</div>`
|
</div>
|
||||||
: html``}
|
${isOpen
|
||||||
</label>
|
? html`
|
||||||
</div>
|
<div class="dropdown-custom-open" data-target="app-dropdown.dropdowncontainer">
|
||||||
`;
|
<input
|
||||||
};
|
class="dropdown-custom-search"
|
||||||
|
type="text"
|
||||||
|
value="${searchPhrase}"
|
||||||
|
app-action="input:app-dropdown#phraseChange"
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
|
<ul class="dropdown-custom-list">
|
||||||
|
${renderItems(items)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: html``}
|
||||||
|
</div>
|
||||||
|
${error ? html` <div class="h5 text-red">${errorMessage}</div>` : html``}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppDropdownElement };
|
export type { AppDropdownElement };
|
||||||
|
|||||||
@@ -1,135 +1,142 @@
|
|||||||
import { attr, controller, target } from "@github/catalyst";
|
import { attr, controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult, unsafeHTML } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
import { AppDropdownElement } from "components/app-dropdown/AppDropdownElement";
|
import { AppDropdownElement } from 'components/app-dropdown/AppDropdownElement';
|
||||||
import { InputFieldElement } from "components/input-field/InputFieldElement";
|
import { InputFieldElement } from 'components/input-field/InputFieldElement';
|
||||||
import { findMethod, isTrue, querys } from "core/utils";
|
import { findMethod, isTrue, querys } from 'core/utils';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppFormElement extends BaseComponentElement {
|
class AppFormElement extends BaseComponentElement {
|
||||||
@target formElement: HTMLElement;
|
@target formElement: HTMLElement;
|
||||||
@target innerSlot: HTMLElement;
|
@target innerSlot: HTMLElement;
|
||||||
@querys inputField: NodeListOf<InputFieldElement>;
|
@querys inputField: NodeListOf<InputFieldElement>;
|
||||||
@querys appDropdown: NodeListOf<AppDropdownElement>;
|
@querys appDropdown: NodeListOf<AppDropdownElement>;
|
||||||
@attr custom: string;
|
@attr custom: string;
|
||||||
@attr hasCancel: string;
|
@attr hasCancel: string;
|
||||||
slotted: any;
|
slotted: any;
|
||||||
isValid: boolean = false;
|
isValid: boolean = false;
|
||||||
error: string;
|
error: string;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public inputChange = (e) => {
|
get submitFunc() {
|
||||||
this.validate();
|
return findMethod(this.custom, this.appMain);
|
||||||
this.update();
|
}
|
||||||
};
|
|
||||||
|
|
||||||
public onSubmit = (e) => {
|
public inputChange = (e) => {
|
||||||
e.preventDefault();
|
this.validate();
|
||||||
if (!this.valid) {
|
this.update();
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
const actionString = this.custom;
|
|
||||||
const submitFunc = findMethod(actionString, this.appMain);
|
|
||||||
submitFunc?.(this.values);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
public validate = () => {
|
public onSubmit = (e) => {
|
||||||
this.isValid = true;
|
e.preventDefault();
|
||||||
this.inputField?.forEach((input) => {
|
if (!this.valid) {
|
||||||
if (input?.error) {
|
return;
|
||||||
this.isValid = false;
|
}
|
||||||
}
|
this.submitFunc?.(this.values);
|
||||||
});
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
public setError = (error) => {
|
public validate = () => {
|
||||||
this.error = error;
|
const validArr = [];
|
||||||
this.update();
|
this.inputField?.forEach((input) => {
|
||||||
};
|
validArr.push(input?.validate());
|
||||||
|
});
|
||||||
|
this.appDropdown?.forEach((input) => {
|
||||||
|
validArr.push(input?.validate());
|
||||||
|
});
|
||||||
|
this.isValid = !validArr?.includes(false);
|
||||||
|
};
|
||||||
|
|
||||||
public goBack = (e) => {
|
public setError = (error) => {
|
||||||
e.preventDefault();
|
this.error = error;
|
||||||
|
this.update();
|
||||||
|
};
|
||||||
|
|
||||||
if (this.appMain?.appModal) {
|
public goBack = (e) => {
|
||||||
this.appMain?.closeModal?.();
|
e.preventDefault();
|
||||||
} else if (this.routerService?.canGoBack) {
|
|
||||||
this.routerService?.goBack();
|
|
||||||
} else {
|
|
||||||
this.routerService?.goTo("/");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
get values(): any {
|
if (this.appMain?.appModal) {
|
||||||
const formObject: any = {};
|
this.appMain?.closeModal?.();
|
||||||
this.inputField.forEach((input: InputFieldElement) => {
|
} else if (this.routerService?.canGoBack) {
|
||||||
formObject[input.name] = input._value;
|
this.routerService?.goBack();
|
||||||
});
|
} else {
|
||||||
this.appDropdown?.forEach((input: AppDropdownElement) => {
|
this.routerService?.goTo('/');
|
||||||
if (input.required && input.value) {
|
}
|
||||||
formObject[input.name] = input._value;
|
};
|
||||||
}
|
|
||||||
});
|
|
||||||
return formObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
get valid() {
|
get values(): any {
|
||||||
let _valid = 0;
|
const formObject: any = {};
|
||||||
this.inputField?.forEach((input) => {
|
this.inputField.forEach((input: InputFieldElement) => {
|
||||||
if (input.required && (input.inp as HTMLSelectElement).value) {
|
formObject[input.name] = input._value;
|
||||||
_valid++;
|
});
|
||||||
}
|
this.appDropdown?.forEach((input: AppDropdownElement) => {
|
||||||
});
|
if (input.required && input.value) {
|
||||||
return _valid == this.inputField?.length;
|
formObject[input.name] = input._value;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
return formObject;
|
||||||
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
getInput = (name: string): InputFieldElement | AppDropdownElement => {
|
||||||
const _template = document.createElement("template");
|
let formObject;
|
||||||
const _slot = this.innerHTML;
|
this.inputField.forEach((input: InputFieldElement) => {
|
||||||
_template.innerHTML = _slot;
|
const inputType = input;
|
||||||
this.innerHTML = null;
|
if (inputType.name === name) formObject = inputType;
|
||||||
this.update();
|
});
|
||||||
|
this.appDropdown.forEach((input: AppDropdownElement) => {
|
||||||
|
const inputType = input;
|
||||||
|
if (inputType.name === name) formObject = inputType;
|
||||||
|
});
|
||||||
|
return formObject;
|
||||||
|
};
|
||||||
|
|
||||||
this.formElement.replaceChild(_template.content, this.innerSlot);
|
get valid() {
|
||||||
};
|
let _valid = 0;
|
||||||
|
this.inputField?.forEach((input) => {
|
||||||
|
if (input.required && (input.inp as HTMLSelectElement).value) {
|
||||||
|
_valid++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return _valid == this.inputField?.length;
|
||||||
|
}
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
elementConnected = (): void => {
|
||||||
const renderSubmit = (valid: boolean) => {
|
const _template = document.createElement('template');
|
||||||
if (!valid) {
|
const _slot = this.innerHTML;
|
||||||
return html` <button type="submit" disabled>Submit</button> `;
|
_template.innerHTML = _slot;
|
||||||
}
|
this.innerHTML = null;
|
||||||
return html` <button type="submit">Submit</button> `;
|
this.update();
|
||||||
};
|
|
||||||
const renderError = (error: string) => {
|
|
||||||
if (error) {
|
|
||||||
return html`<span>${error}</span>`;
|
|
||||||
}
|
|
||||||
return html``;
|
|
||||||
};
|
|
||||||
const renderCancel = (hasCancel: boolean) => {
|
|
||||||
if (hasCancel) {
|
|
||||||
return html`<button
|
|
||||||
type="button"
|
|
||||||
app-action="click:app-form#goBack"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>`;
|
|
||||||
}
|
|
||||||
return html``;
|
|
||||||
};
|
|
||||||
|
|
||||||
return html`<form
|
this.formElement.replaceChild(_template.content, this.innerSlot);
|
||||||
app-action="submit:app-form#onSubmit"
|
};
|
||||||
data-target="app-form.formElement"
|
|
||||||
>
|
render = (): TemplateResult => {
|
||||||
<slot data-target="app-form.innerSlot"></slot>
|
const renderSubmit = (valid: boolean) => {
|
||||||
${renderError(this.error)}${renderSubmit(
|
if (!valid) {
|
||||||
this.isValid
|
return html` <button type="submit" disabled>Submit</button> `;
|
||||||
)}${renderCancel(isTrue(this.hasCancel))}
|
}
|
||||||
</form>`;
|
return html` <button type="submit">Submit</button> `;
|
||||||
};
|
};
|
||||||
|
const renderError = (error: string) => {
|
||||||
|
if (error) {
|
||||||
|
return html`<span>${error}</span>`;
|
||||||
|
}
|
||||||
|
return html``;
|
||||||
|
};
|
||||||
|
const renderCancel = (hasCancel: boolean) => {
|
||||||
|
if (hasCancel) {
|
||||||
|
return html`<button type="button" app-action="click:app-form#goBack">Cancel</button>`;
|
||||||
|
}
|
||||||
|
return html``;
|
||||||
|
};
|
||||||
|
|
||||||
|
return html`<form app-action="submit:app-form#onSubmit" data-target="app-form.formElement">
|
||||||
|
<slot data-target="app-form.innerSlot"></slot>
|
||||||
|
${renderError(this.error)}${renderSubmit(this.isValid)}${renderCancel(isTrue(this.hasCancel))}
|
||||||
|
</form>`;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppFormElement };
|
export type { AppFormElement };
|
||||||
|
|||||||
@@ -1,72 +1,67 @@
|
|||||||
import { attr, controller, target } from "@github/catalyst";
|
import { attr, controller, target } from '@github/catalyst';
|
||||||
import { isTrue } from "core/utils";
|
import { isTrue } from 'core/utils';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { AppMainElement } from "components/app-main/AppMainElement";
|
import { AppMainElement } from 'components/app-main/AppMainElement';
|
||||||
import { RouterService } from "core/services";
|
import { RouterService } from 'core/services';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppLinkElement extends BaseComponentElement {
|
class AppLinkElement extends BaseComponentElement {
|
||||||
@attr to: string;
|
@attr to: string;
|
||||||
@attr goBack: string;
|
@attr goBack: string;
|
||||||
@attr title: string;
|
@attr title: string;
|
||||||
@target main: Element;
|
@target main: Element;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
if (!this.title && this.innerText) {
|
if (!this.title && this.innerText) {
|
||||||
const _slottedText = this.innerText;
|
const _slottedText = this.innerText;
|
||||||
this.innerText = null;
|
this.innerText = null;
|
||||||
this.title = _slottedText;
|
this.title = _slottedText;
|
||||||
}
|
}
|
||||||
this.update();
|
this.update();
|
||||||
if (isTrue(this.goBack)) {
|
if (isTrue(this.goBack)) {
|
||||||
this.appMain.addEventListener("routechanged", this.update);
|
this.appMain.addEventListener('routechanged', this.update);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
elementDisconnected = (appMain: AppMainElement): void => {
|
elementDisconnected = (appMain: AppMainElement): void => {
|
||||||
if (isTrue(this.goBack)) {
|
if (isTrue(this.goBack)) {
|
||||||
appMain?.removeEventListener("routechanged", this.update);
|
appMain?.removeEventListener('routechanged', this.update);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
goTo = (e: Event): void => {
|
goTo = (e: Event): void => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!isTrue(this.goBack) && this.to) {
|
if (!isTrue(this.goBack) && this.to) {
|
||||||
this.routerService.goTo(this.to);
|
this.routerService.goTo(this.to);
|
||||||
} else {
|
} else {
|
||||||
this.routerService.goBack();
|
this.routerService.goBack();
|
||||||
}
|
}
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
get disabled(): boolean {
|
get disabled(): boolean {
|
||||||
if (isTrue(this.goBack)) {
|
if (isTrue(this.goBack)) {
|
||||||
return this.routerService.emptyState;
|
return this.routerService.emptyState;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`${this.disabled
|
return html`${this.disabled
|
||||||
? html`<a
|
? html`<a class="btn btn-link btn-disabled" data-target="app-link.main" style="color:grey">${this.title}</a>`
|
||||||
class="btn btn-link btn-disabled"
|
: html`<a
|
||||||
data-target="app-link.main"
|
class="btn btn-link"
|
||||||
style="color:grey"
|
data-target="app-link.main"
|
||||||
>${this.title}</a
|
app-action="click:app-link#goTo"
|
||||||
>`
|
href="${this.to}"
|
||||||
: html`<a
|
style="text-decoration: underline; cursor: pointer;"
|
||||||
class="btn btn-link"
|
>${this.title}</a
|
||||||
data-target="app-link.main"
|
>`}`;
|
||||||
app-action="click:app-link#goTo"
|
};
|
||||||
href="${this.to}"
|
|
||||||
style="text-decoration: underline; cursor: pointer;"
|
|
||||||
>${this.title}</a
|
|
||||||
>`}`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppLinkElement };
|
export type { AppLinkElement };
|
||||||
|
|||||||
@@ -1,58 +1,58 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { html } from "@github/jtml";
|
import { html } from 'core/utils';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppLoaderElement extends BaseComponentElement {
|
class AppLoaderElement extends BaseComponentElement {
|
||||||
private finished: boolean = true;
|
private finished: boolean = true;
|
||||||
private _loading: number = 0;
|
private _loading: number = 0;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public start = () => {
|
public start = () => {
|
||||||
this.finished = false;
|
this.finished = false;
|
||||||
this._loading++;
|
this._loading++;
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
public stop = () => {
|
public stop = () => {
|
||||||
if (this._loading > 0) {
|
if (this._loading > 0) {
|
||||||
this._loading--;
|
this._loading--;
|
||||||
}
|
}
|
||||||
if (this._loading == 0) {
|
if (this._loading == 0) {
|
||||||
this.finishInitiate();
|
this.finishInitiate();
|
||||||
}
|
}
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
public get loading() {
|
public get loading() {
|
||||||
return this._loading > 0;
|
return this._loading > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private finishInitiate = () => {
|
private finishInitiate = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.finished = true;
|
this.finished = true;
|
||||||
this.update();
|
this.update();
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
};
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
render = () => {
|
render = () => {
|
||||||
const renderLoader = (finished: boolean, loading: boolean) => {
|
const renderLoader = (finished: boolean, loading: boolean) => {
|
||||||
if (!finished && !loading) {
|
if (!finished && !loading) {
|
||||||
return html`<div class="loader --removing"></div>`;
|
return html`<div class="loader --removing"></div>`;
|
||||||
} else if (loading) {
|
} else if (loading) {
|
||||||
return html`<div class="loader --loading"></div>`;
|
return html`<div class="loader --loading"></div>`;
|
||||||
}
|
}
|
||||||
return html``;
|
return html``;
|
||||||
};
|
};
|
||||||
return html`${renderLoader(this.finished, this.loading)}`;
|
return html`${renderLoader(this.finished, this.loading)}`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppLoaderElement };
|
export type { AppLoaderElement };
|
||||||
|
|||||||
@@ -1,185 +1,185 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { AppService, HttpClient, RouterService } from "core/services";
|
import { AppService, HttpClient, RouterService } from 'core/services';
|
||||||
import { AuthStore } from "core/store";
|
import { AuthStore } from 'core/store';
|
||||||
import { AppModalElement, AppRootElement } from "components/";
|
import { AppModalElement, AppRootElement } from 'components/';
|
||||||
import { closest } from "core/utils";
|
import { closest } from 'core/utils';
|
||||||
import { AppLoaderElement } from "components/app-loader/AppLoaderElement";
|
import { AppLoaderElement } from 'components/app-loader/AppLoaderElement';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppMainElement extends HTMLElement {
|
class AppMainElement extends HTMLElement {
|
||||||
public routerService: RouterService;
|
public routerService: RouterService;
|
||||||
public authStore: AuthStore;
|
public authStore: AuthStore;
|
||||||
private httpClient: HttpClient;
|
private httpClient: HttpClient;
|
||||||
public appService: AppService;
|
public appService: AppService;
|
||||||
@target appModal: AppModalElement;
|
@target appModal: AppModalElement;
|
||||||
@target mainRoot: AppRootElement;
|
@target mainRoot: AppRootElement;
|
||||||
@target appLoader: AppLoaderElement;
|
@target appLoader: AppLoaderElement;
|
||||||
@closest appMain: AppMainElement;
|
@closest appMain: AppMainElement;
|
||||||
public domEvents: any = {
|
public domEvents: any = {
|
||||||
routechanged: new Event("routechanged"),
|
routechanged: new Event('routechanged'),
|
||||||
tokenchange: new Event("tokenchange"),
|
tokenchange: new Event('tokenchange'),
|
||||||
walletupdate: new Event("walletupdate"),
|
walletupdate: new Event('walletupdate'),
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
if (this.appMain !== this) return;
|
if (this.appMain !== this) return;
|
||||||
this.createLoader();
|
this.createLoader();
|
||||||
const mainRoot = this.createMainRoot();
|
const mainRoot = this.createMainRoot();
|
||||||
this.httpClient = new HttpClient();
|
this.httpClient = new HttpClient();
|
||||||
this.appService = new AppService(this, this.httpClient);
|
this.appService = new AppService(this, this.httpClient);
|
||||||
this.routerService = new RouterService(this, mainRoot);
|
this.routerService = new RouterService(this, mainRoot);
|
||||||
this.authStore = new AuthStore(this, this.appService);
|
this.authStore = new AuthStore(this, this.appService);
|
||||||
this.routerService.setRoutes([
|
this.routerService.setRoutes([
|
||||||
{
|
{
|
||||||
path: "/",
|
path: '/',
|
||||||
component: "home-page",
|
component: 'home-page',
|
||||||
layout: "menu-layout",
|
layout: 'menu-layout',
|
||||||
middleware: this.isAuth,
|
middleware: this.isAuth,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/home",
|
path: '/home',
|
||||||
component: "home-page",
|
component: 'home-page',
|
||||||
layout: "menu-layout",
|
layout: 'menu-layout',
|
||||||
middleware: this.isAuth,
|
middleware: this.isAuth,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/history",
|
path: '/history',
|
||||||
component: "history-page",
|
component: 'history-page',
|
||||||
layout: "menu-layout",
|
layout: 'menu-layout',
|
||||||
middleware: this.isAuth,
|
middleware: this.isAuth,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/wallet",
|
path: '/wallet',
|
||||||
component: "history-page",
|
component: 'history-page',
|
||||||
layout: "menu-layout",
|
layout: 'menu-layout',
|
||||||
middleware: this.isAuth,
|
middleware: this.isAuth,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/all",
|
path: '/all',
|
||||||
component: "wallet-list",
|
component: 'wallet-list',
|
||||||
layout: "menu-layout",
|
layout: 'menu-layout',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/:walletId",
|
path: '/:walletId',
|
||||||
component: "wallet-page",
|
component: 'wallet-page',
|
||||||
layout: "menu-layout",
|
layout: 'menu-layout',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/register",
|
path: '/register',
|
||||||
component: "register-page",
|
component: 'register-page',
|
||||||
layout: "initial-layout",
|
layout: 'initial-layout',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/login",
|
path: '/login',
|
||||||
component: "login-page",
|
component: 'login-page',
|
||||||
layout: "initial-layout",
|
layout: 'initial-layout',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/unauthorized",
|
path: '/unauthorized',
|
||||||
component: "login-page",
|
component: 'login-page',
|
||||||
layout: "initial-layout",
|
layout: 'initial-layout',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/token-expired",
|
path: '/token-expired',
|
||||||
component: "login-page",
|
component: 'login-page',
|
||||||
layout: "initial-layout",
|
layout: 'initial-layout',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/not-found",
|
path: '/not-found',
|
||||||
component: "not-found",
|
component: 'not-found',
|
||||||
layout: "initial-layout",
|
layout: 'initial-layout',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/logout",
|
path: '/logout',
|
||||||
component: "logout-page",
|
component: 'logout-page',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
this.routerService.init();
|
this.routerService.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
middleAuth = () => {
|
middleAuth = () => {
|
||||||
if (!this.isAuth) {
|
if (!this.isAuth) {
|
||||||
this.routerService.goTo("/unauthorized");
|
this.routerService.goTo('/unauthorized');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
createModal = (element: string) => {
|
createModal = (element: string) => {
|
||||||
this.closeModal();
|
this.closeModal();
|
||||||
this.appMain.addEventListener("routechanged", this.closeModal);
|
this.appMain.addEventListener('routechanged', this.closeModal);
|
||||||
|
|
||||||
const _appModal = this.createAppModal();
|
const _appModal = this.createAppModal();
|
||||||
const _modalContent = this.createModalContent(element);
|
const _modalContent = this.createModalContent(element);
|
||||||
const _modalOverlay = this.createModalOverlay();
|
const _modalOverlay = this.createModalOverlay();
|
||||||
|
|
||||||
_modalOverlay.appendChild(_modalContent);
|
_modalOverlay.appendChild(_modalContent);
|
||||||
_appModal.appendChild(_modalOverlay);
|
_appModal.appendChild(_modalOverlay);
|
||||||
this.appendChild(_appModal);
|
this.appendChild(_appModal);
|
||||||
};
|
};
|
||||||
|
|
||||||
public triggerWalletUpdate = () => {
|
public triggerWalletUpdate = () => {
|
||||||
this.dispatchEvent(this.domEvents.walletupdate);
|
this.dispatchEvent(this.domEvents.walletupdate);
|
||||||
};
|
};
|
||||||
|
|
||||||
public setTitle = (title: string): void => {
|
public setTitle = (title: string): void => {
|
||||||
if (!title) title = __CONFIG__.appName;
|
if (!title) title = __CONFIG__.appName;
|
||||||
window.document.title = title;
|
window.document.title = title;
|
||||||
};
|
};
|
||||||
|
|
||||||
private createAppModal = () => {
|
private createAppModal = () => {
|
||||||
const _appModal = document.createElement("app-modal");
|
const _appModal = document.createElement('app-modal');
|
||||||
_appModal.setAttribute("data-target", "app-main.appModal");
|
_appModal.setAttribute('data-target', 'app-main.appModal');
|
||||||
return _appModal;
|
return _appModal;
|
||||||
};
|
};
|
||||||
|
|
||||||
private createLoader = () => {
|
private createLoader = () => {
|
||||||
const _loader = document.createElement("app-loader");
|
const _loader = document.createElement('app-loader');
|
||||||
_loader.setAttribute("data-target", "app-main.appLoader");
|
_loader.setAttribute('data-target', 'app-main.appLoader');
|
||||||
this.appendChild(_loader);
|
this.appendChild(_loader);
|
||||||
};
|
};
|
||||||
|
|
||||||
private createModalContent = (element: string) => {
|
private createModalContent = (element: string) => {
|
||||||
const _modalElement = document.createElement(element);
|
const _modalElement = document.createElement(element);
|
||||||
const _divEl = document.createElement("div");
|
const _divEl = document.createElement('div');
|
||||||
_modalElement.setAttribute("data-target", "app-modal.modalElement");
|
_modalElement.setAttribute('data-target', 'app-modal.modalElement');
|
||||||
_divEl.setAttribute("data-target", "app-modal.modalContent");
|
_divEl.setAttribute('data-target', 'app-modal.modalContent');
|
||||||
_divEl.setAttribute("data-action", "click:app-main#preventClosing");
|
_divEl.setAttribute('data-action', 'click:app-main#preventClosing');
|
||||||
_divEl.appendChild(_modalElement);
|
_divEl.appendChild(_modalElement);
|
||||||
return _divEl;
|
return _divEl;
|
||||||
};
|
};
|
||||||
|
|
||||||
private createModalOverlay = () => {
|
private createModalOverlay = () => {
|
||||||
const _divOverlay = document.createElement("div");
|
const _divOverlay = document.createElement('div');
|
||||||
_divOverlay.setAttribute("data-target", "app-modal.modalOverlay");
|
_divOverlay.setAttribute('data-target', 'app-modal.modalOverlay');
|
||||||
_divOverlay.setAttribute("data-action", "click:app-main#closeModal");
|
_divOverlay.setAttribute('data-action', 'click:app-main#closeModal');
|
||||||
return _divOverlay;
|
return _divOverlay;
|
||||||
};
|
};
|
||||||
|
|
||||||
private createMainRoot = () => {
|
private createMainRoot = () => {
|
||||||
if (this.mainRoot) this.removeChild(this.mainRoot);
|
if (this.mainRoot) this.removeChild(this.mainRoot);
|
||||||
const _mainRoot = document.createElement("app-root");
|
const _mainRoot = document.createElement('app-root');
|
||||||
_mainRoot.setAttribute("data-target", "app-main.mainRoot");
|
_mainRoot.setAttribute('data-target', 'app-main.mainRoot');
|
||||||
this.appendChild(_mainRoot);
|
this.appendChild(_mainRoot);
|
||||||
return _mainRoot;
|
return _mainRoot;
|
||||||
};
|
};
|
||||||
|
|
||||||
preventClosing = (e: Event) => {
|
preventClosing = (e: Event) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
closeModal = () => {
|
closeModal = () => {
|
||||||
if (this.appModal) this.removeChild(this.appModal);
|
if (this.appModal) this.removeChild(this.appModal);
|
||||||
this.appMain.removeEventListener("routechanged", this.closeModal);
|
this.appMain.removeEventListener('routechanged', this.closeModal);
|
||||||
};
|
};
|
||||||
|
|
||||||
isAuth = (): boolean => {
|
isAuth = (): boolean => {
|
||||||
return this.authStore && !!this.authStore.token;
|
return this.authStore && !!this.authStore.token;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppMainElement };
|
export type { AppMainElement };
|
||||||
|
|||||||
@@ -1,164 +1,132 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
import { AppMainElement } from "components/app-main/AppMainElement";
|
import { AppMainElement } from 'components/app-main/AppMainElement';
|
||||||
import { MenuItemElement } from "components/menu-item/MenuItemElement";
|
import { MenuItemElement } from 'components/menu-item/MenuItemElement';
|
||||||
import { WalletService } from "services/";
|
import { WalletService } from 'services/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppMenuElement extends BaseComponentElement {
|
class AppMenuElement extends BaseComponentElement {
|
||||||
private walletService: WalletService;
|
private walletService: WalletService;
|
||||||
private walletData: Array<any>;
|
private walletData: Array<any>;
|
||||||
private totalWallets: number;
|
private totalWallets: number;
|
||||||
@target walletlist: MenuItemElement;
|
@target walletlist: MenuItemElement;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.walletService = new WalletService(this.appMain?.appService);
|
this.walletService = new WalletService(this.appMain?.appService);
|
||||||
if (this.appMain.isAuth) {
|
if (this.appMain.isAuth) {
|
||||||
this.getWallets();
|
this.getWallets();
|
||||||
}
|
}
|
||||||
this.update();
|
this.update();
|
||||||
this.appMain.addEventListener("tokenchange", this.updateToken);
|
this.appMain.addEventListener('tokenchange', this.updateToken);
|
||||||
this.appMain.addEventListener("walletupdate", this.updateToken);
|
this.appMain.addEventListener('walletupdate', this.updateToken);
|
||||||
};
|
};
|
||||||
|
|
||||||
elementDisconnected = (appMain: AppMainElement): void => {
|
elementDisconnected = (appMain: AppMainElement): void => {
|
||||||
appMain?.removeEventListener("tokenchange", this.updateToken);
|
appMain?.removeEventListener('tokenchange', this.updateToken);
|
||||||
appMain?.removeEventListener("walletupdate", this.updateToken);
|
appMain?.removeEventListener('walletupdate', this.updateToken);
|
||||||
};
|
};
|
||||||
|
|
||||||
getWallets = async (): Promise<void> => {
|
getWallets = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const response = await this.walletService.getAll({ rpp: 3 });
|
const response = await this.walletService.getAll({ rpp: 3 });
|
||||||
this.setWallets(response.items, response.totalRecords);
|
this.setWallets(response.items, response.totalRecords);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setWallets = (wallets: Array<any>, totalWallets: number): void => {
|
setWallets = (wallets: Array<any>, totalWallets: number): void => {
|
||||||
this.walletData = wallets;
|
this.walletData = wallets;
|
||||||
this.totalWallets = totalWallets;
|
this.totalWallets = totalWallets;
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
updateToken = (): void => {
|
updateToken = (): void => {
|
||||||
if (this.isAuth) {
|
if (this.isAuth) {
|
||||||
this.getWallets();
|
this.getWallets();
|
||||||
} else {
|
} else {
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
get isAuth(): boolean {
|
get isAuth(): boolean {
|
||||||
if (this.appMain?.isAuth) {
|
if (this.appMain?.isAuth) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderWallets = (): Array<TemplateResult> => {
|
renderWallets = (): Array<TemplateResult> => {
|
||||||
if (this.isAuth && this.totalWallets > 0) {
|
if (this.isAuth && this.totalWallets > 0) {
|
||||||
return this.walletData.map(
|
return this.walletData.map(
|
||||||
(wallet) => html`<menu-item data-path="/wallet/${wallet.id}"
|
(wallet) => html`<menu-item data-path="/wallet/${wallet.id}">${wallet.name}</menu-item>`
|
||||||
>${wallet.name}</menu-item
|
);
|
||||||
>`
|
}
|
||||||
);
|
return null;
|
||||||
}
|
};
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
modalWallet = (): void => {
|
modalWallet = (): void => {
|
||||||
const _modal = this.appMain.appModal;
|
const _modal = this.appMain.appModal;
|
||||||
if (_modal) {
|
if (_modal) {
|
||||||
this.appMain.closeModal();
|
this.appMain.closeModal();
|
||||||
} else {
|
} else {
|
||||||
this.appMain.createModal("wallet-create");
|
this.appMain.createModal('wallet-create');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
modalTransaction = (): void => {
|
modalTransaction = (s): void => {
|
||||||
const _modal = this.appMain.appModal;
|
const _modal = this.appMain.appModal;
|
||||||
if (_modal) {
|
if (_modal) {
|
||||||
this.appMain.closeModal();
|
this.appMain.closeModal();
|
||||||
} else {
|
} else {
|
||||||
this.appMain.createModal("transaction-create");
|
this.appMain.createModal('transaction-create');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
const { isAuth, totalWallets, walletData } = this;
|
const { isAuth, totalWallets, walletData } = this;
|
||||||
|
|
||||||
const regularMenu = (
|
const regularMenu = (path: string, title: string, action?: string): TemplateResult => {
|
||||||
path: string,
|
if (action) {
|
||||||
title: string,
|
return html` <menu-item data-path="${path}" data-customaction="${action}">${title}</menu-item> `;
|
||||||
action?: string
|
}
|
||||||
): TemplateResult => {
|
return html`<menu-item data-path="${path}">${title}</menu-item>`;
|
||||||
if (action) {
|
};
|
||||||
return html`
|
const authMenu = (path: string, title: string, action?: string): TemplateResult => {
|
||||||
<menu-item data-path="${path}" data-customaction="${action}"
|
if (isAuth) {
|
||||||
>${title}</menu-item
|
return regularMenu(path, title, action);
|
||||||
>
|
}
|
||||||
`;
|
return html``;
|
||||||
}
|
};
|
||||||
return html`<menu-item data-path="${path}">${title}</menu-item>`;
|
const notAuthMenu = (path: string, title: string, action?: string): TemplateResult => {
|
||||||
};
|
if (!isAuth) {
|
||||||
const authMenu = (
|
return regularMenu(path, title, action);
|
||||||
path: string,
|
}
|
||||||
title: string,
|
return html``;
|
||||||
action?: string
|
};
|
||||||
): TemplateResult => {
|
const renderWallets = (wallets: Array<any>) => {
|
||||||
if (isAuth) {
|
if (isAuth && totalWallets > 0) {
|
||||||
return regularMenu(path, title, action);
|
return html`<div class="menu-item divider"></div>
|
||||||
}
|
${wallets.map((wallet) => regularMenu(`/wallet/${wallet.id}`, wallet.name))}`;
|
||||||
return html``;
|
}
|
||||||
};
|
return html``;
|
||||||
const notAuthMenu = (
|
};
|
||||||
path: string,
|
const menuHeader = (title) => html`<div class="menu-item menu-header">${title}</div>`;
|
||||||
title: string,
|
|
||||||
action?: string
|
|
||||||
): TemplateResult => {
|
|
||||||
if (!isAuth) {
|
|
||||||
return regularMenu(path, title, action);
|
|
||||||
}
|
|
||||||
return html``;
|
|
||||||
};
|
|
||||||
const renderWallets = (wallets: Array<any>) => {
|
|
||||||
if (isAuth && totalWallets > 0) {
|
|
||||||
return html`<div class="menu-item divider"></div>
|
|
||||||
${wallets.map((wallet) =>
|
|
||||||
regularMenu(`/wallet/${wallet.id}`, wallet.name)
|
|
||||||
)}`;
|
|
||||||
}
|
|
||||||
return html``;
|
|
||||||
};
|
|
||||||
const menuHeader = (title) =>
|
|
||||||
html`<div class="menu-item menu-header">${title}</div>`;
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div data-target="app-menu.sidebar">
|
<div data-target="app-menu.sidebar">
|
||||||
${menuHeader(__CONFIG__.appName)} ${regularMenu("/", "Home")}
|
${menuHeader(__CONFIG__.appName)} ${regularMenu('/', 'Home')}
|
||||||
${authMenu(
|
${authMenu('/history', 'Transaction History', 'click:app-menu#modalTransaction')}
|
||||||
"/history",
|
${authMenu('/wallet/all', 'My Wallets', 'click:app-menu#modalWallet')} ${renderWallets(walletData)}
|
||||||
"Transaction History",
|
<span class="menu-item divider"></span>
|
||||||
"click:app-menu#modalTransaction"
|
${authMenu('/logout', 'Logout')} ${notAuthMenu('/login', 'Login')} ${notAuthMenu('/register', 'Register')}
|
||||||
)}
|
</div>
|
||||||
${authMenu(
|
`;
|
||||||
"/wallet/all",
|
};
|
||||||
"My Wallets",
|
|
||||||
"click:app-menu#modalWallet"
|
|
||||||
)}
|
|
||||||
${renderWallets(walletData)}
|
|
||||||
<span class="menu-item divider"></span>
|
|
||||||
${authMenu("/logout", "Logout")}
|
|
||||||
${notAuthMenu("/login", "Login")}
|
|
||||||
${notAuthMenu("/register", "Register")}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppMenuElement };
|
export type { AppMenuElement };
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppModalElement extends BaseComponentElement {
|
class AppModalElement extends BaseComponentElement {
|
||||||
@target modalElement: HTMLElement;
|
@target modalElement: HTMLElement;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {};
|
elementConnected = (): void => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppModalElement };
|
export type { AppModalElement };
|
||||||
|
|||||||
@@ -1,148 +1,143 @@
|
|||||||
import { attr, controller, target } from "@github/catalyst";
|
import { attr, controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
import { CircleLoaderElement } from "components/circle-loader/CircleLoaderElement";
|
import { CircleLoaderElement } from 'components/circle-loader/CircleLoaderElement';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppPaginationElement extends BaseComponentElement {
|
class AppPaginationElement extends BaseComponentElement {
|
||||||
public items: Array<any>;
|
public items: Array<any>;
|
||||||
@attr page: number;
|
@attr page: number;
|
||||||
@attr rpp: number;
|
@attr rpp: number;
|
||||||
@attr totalItems: number;
|
@attr totalItems: number;
|
||||||
@attr autoInit: string;
|
@attr autoInit: string;
|
||||||
|
|
||||||
private customRenderItems: () => TemplateResult;
|
private customRenderItems: () => TemplateResult;
|
||||||
private customRenderItem: (item: any) => TemplateResult;
|
private customRenderItem: (item: any) => TemplateResult;
|
||||||
fetchFunc: Function = () => {};
|
fetchFunc: Function = () => {};
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {};
|
elementConnected = (): void => {};
|
||||||
|
|
||||||
attributeChangedCallback(): void {
|
attributeChangedCallback(): void {
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
setItems = (items): void => {
|
setItems = (items): void => {
|
||||||
this.items = items;
|
this.items = items;
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
setFetchFunc = async (fetchFunc: Function, autoInit?): Promise<void> => {
|
setFetchFunc = async (fetchFunc: Function, autoInit?): Promise<void> => {
|
||||||
this.fetchFunc = fetchFunc;
|
this.fetchFunc = fetchFunc;
|
||||||
if (autoInit) {
|
if (autoInit) {
|
||||||
const options = {
|
const options = {
|
||||||
rpp: this.rpp || 5,
|
rpp: this.rpp || 5,
|
||||||
page: this.page || 1,
|
page: this.page || 1,
|
||||||
};
|
};
|
||||||
this.executeFetch(options);
|
this.executeFetch(options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setCustomRenderItems = (customRenderItems: () => TemplateResult) => {
|
setCustomRenderItems = (customRenderItems: () => TemplateResult) => {
|
||||||
this.customRenderItems = customRenderItems;
|
this.customRenderItems = customRenderItems;
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
setCustomRenderItem = (customRenderItem: (item: any) => TemplateResult) => {
|
setCustomRenderItem = (customRenderItem: (item: any) => TemplateResult) => {
|
||||||
this.customRenderItem = customRenderItem;
|
this.customRenderItem = customRenderItem;
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
executeFetch = async (options?): Promise<void> => {
|
executeFetch = async (options?): Promise<void> => {
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {
|
options = {
|
||||||
rpp: this.rpp || 5,
|
rpp: this.rpp || 5,
|
||||||
page: this.page || 1,
|
page: this.page || 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.loader?.start?.();
|
this.loader?.start?.();
|
||||||
const response = await this.fetchFunc(options);
|
const response = await this.fetchFunc(options);
|
||||||
this.loader?.stop?.();
|
this.loader?.stop?.();
|
||||||
this.setItems(response?.items);
|
this.setItems(response?.items);
|
||||||
this.totalItems = response?.totalRecords;
|
this.totalItems = response?.totalRecords;
|
||||||
this.page = response?.page;
|
this.page = response?.page;
|
||||||
this.rpp = response?.rpp;
|
this.rpp = response?.rpp;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.loader?.stop?.();
|
this.loader?.stop?.();
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pageBack = (): void => {
|
pageBack = (): void => {
|
||||||
const { page } = this;
|
const { page } = this;
|
||||||
if (page > 1) {
|
if (page > 1) {
|
||||||
this.page--;
|
this.page--;
|
||||||
this.executeFetch();
|
this.executeFetch();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pageNext = (): void => {
|
pageNext = (): void => {
|
||||||
const { rpp, totalItems, page } = this;
|
const { rpp, totalItems, page } = this;
|
||||||
const pageRange = Math.ceil(totalItems / rpp);
|
const pageRange = Math.ceil(totalItems / rpp);
|
||||||
if (page < pageRange) {
|
if (page < pageRange) {
|
||||||
this.page++;
|
this.page++;
|
||||||
this.executeFetch();
|
this.executeFetch();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
const { rpp, totalItems, page, items } = this;
|
const { rpp, totalItems, page, items } = this;
|
||||||
|
|
||||||
const renderItem = this.customRenderItem
|
const renderItem = this.customRenderItem
|
||||||
? this.customRenderItem
|
? this.customRenderItem
|
||||||
: (item) => html`<tr>
|
: (item) => html`<tr>
|
||||||
<td>${item.description}</td>
|
<td>${item.description}</td>
|
||||||
<td>${item.amount}</td>
|
<td>${item.amount}</td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
|
|
||||||
const renderItems = this.customRenderItems
|
const renderItems = this.customRenderItems
|
||||||
? this.customRenderItems
|
? this.customRenderItems
|
||||||
: () => {
|
: () => {
|
||||||
if (this.loader && this.loader.loading) {
|
if (this.loader && this.loader.loading) {
|
||||||
return html`<circle-loader></circle-loader>`;
|
return html`<circle-loader></circle-loader>`;
|
||||||
} else {
|
} else {
|
||||||
if (items?.length > 0) {
|
if (items?.length > 0) {
|
||||||
return html`<div class="table">
|
return html`<table>
|
||||||
${items?.map((item) => renderItem(item))}
|
${items?.map((item) => renderItem(item))}
|
||||||
</div>`;
|
</table>`;
|
||||||
}
|
}
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderPagination = () => {
|
const renderPagination = () => {
|
||||||
if (totalItems > items?.length) {
|
if (totalItems > items?.length) {
|
||||||
const pageRange = Math.ceil(totalItems / rpp);
|
const pageRange = Math.ceil(totalItems / rpp);
|
||||||
return html`
|
return html`
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
class="btn btn-primary btn-squared ${page <= 1
|
class="btn btn-primary btn-squared ${page <= 1 ? 'disabled' : ''}"
|
||||||
? "disabled"
|
app-action="click:app-pagination#pageBack"
|
||||||
: ""}"
|
>
|
||||||
app-action="click:app-pagination#pageBack"
|
Prev
|
||||||
>
|
</button>
|
||||||
Prev
|
<button
|
||||||
</button>
|
class="btn btn-primary btn-squared ${page >= pageRange ? 'disabled' : ''}"
|
||||||
<button
|
app-action="click:app-pagination#pageNext"
|
||||||
class="btn btn-primary btn-squared ${page >=
|
>
|
||||||
pageRange
|
Next
|
||||||
? "disabled"
|
</button>
|
||||||
: ""}"
|
</div>
|
||||||
app-action="click:app-pagination#pageNext"
|
`;
|
||||||
>
|
}
|
||||||
Next
|
};
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return html`<div>${renderItems()} ${renderPagination()}</div>`;
|
return html`<div>${renderItems()} ${renderPagination()}</div>`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppPaginationElement };
|
export type { AppPaginationElement };
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppRootElement extends BaseComponentElement {
|
class AppRootElement extends BaseComponentElement {
|
||||||
@target rootElement: HTMLElement;
|
@target rootElement: HTMLElement;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {};
|
elementConnected = (): void => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppRootElement };
|
export type { AppRootElement };
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
import { controller } from "@github/catalyst";
|
import { controller } from '@github/catalyst';
|
||||||
import style from "styles/main.scss";
|
import style from 'styles/main.scss';
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
const _shadow = new WeakMap();
|
const _shadow = new WeakMap();
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppShadowElement extends HTMLElement {
|
class AppShadowElement extends HTMLElement {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
_shadow.set(this, this.attachShadow({ mode: "closed" }));
|
_shadow.set(this, this.attachShadow({ mode: 'closed' }));
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
const _root = _shadow.get(this);
|
const _root = _shadow.get(this);
|
||||||
const _appMain = document.createElement("app-main");
|
const _appMain = document.createElement('app-main');
|
||||||
const _style = document.createElement("style");
|
const _style = document.createElement('style');
|
||||||
_style.innerHTML = style;
|
_style.innerHTML = style;
|
||||||
|
|
||||||
_root.appendChild(_style);
|
_root.appendChild(_style);
|
||||||
_root.appendChild(_appMain);
|
_root.appendChild(_appMain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class AppSlotElement extends BaseComponentElement {
|
class AppSlotElement extends BaseComponentElement {
|
||||||
@target slotElement: HTMLElement;
|
@target slotElement: HTMLElement;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {};
|
elementConnected = (): void => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { AppSlotElement };
|
export type { AppSlotElement };
|
||||||
|
|||||||
@@ -1,23 +1,21 @@
|
|||||||
import { attr, controller } from "@github/catalyst";
|
import { attr, controller } from '@github/catalyst';
|
||||||
import { html } from "@github/jtml";
|
import { html } from 'core/utils';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class CircleLoaderElement extends BaseComponentElement {
|
class CircleLoaderElement extends BaseComponentElement {
|
||||||
@attr size: string;
|
@attr size: string;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
render = () => {
|
render = () => {
|
||||||
return html`<div
|
return html`<div class="circle-loader ${this.size ? `-${this.size}` : ''}"></div>`;
|
||||||
class="circle-loader ${this.size ? `-${this.size}` : ""}"
|
};
|
||||||
></div>`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { CircleLoaderElement };
|
export type { CircleLoaderElement };
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
export * from "./app-link/AppLinkElement";
|
export * from './app-link/AppLinkElement';
|
||||||
export * from "./menu-item/MenuItemElement";
|
export * from './menu-item/MenuItemElement';
|
||||||
export * from "./app-pagination/AppPaginationElement";
|
export * from './app-pagination/AppPaginationElement';
|
||||||
export * from "./app-modal/AppModalElement";
|
export * from './app-modal/AppModalElement';
|
||||||
export * from "./app-root/AppRootElement";
|
export * from './app-root/AppRootElement';
|
||||||
export * from "./app-slot/AppSlotElement";
|
export * from './app-slot/AppSlotElement';
|
||||||
export * from "./app-menu/AppMenuElement";
|
export * from './app-menu/AppMenuElement';
|
||||||
export * from "./input-field/InputFieldElement";
|
export * from './input-field/InputFieldElement';
|
||||||
export * from "./app-dropdown/AppDropdownElement";
|
export * from './app-dropdown/AppDropdownElement';
|
||||||
export * from "./app-loader/AppLoaderElement";
|
export * from './app-loader/AppLoaderElement';
|
||||||
export * from "./circle-loader/CircleLoaderElement";
|
export * from './circle-loader/CircleLoaderElement';
|
||||||
export * from "./app-form/AppFormElement";
|
export * from './app-form/AppFormElement';
|
||||||
export * from "./wallet-header/WalletHeaderElement";
|
export * from './wallet-header/WalletHeaderElement';
|
||||||
|
|
||||||
// LAST
|
// LAST
|
||||||
export * from "./app-main/AppMainElement";
|
export * from './app-main/AppMainElement';
|
||||||
export * from "./app-shadow/AppShadowElement";
|
export * from './app-shadow/AppShadowElement';
|
||||||
|
|||||||
@@ -1,125 +1,106 @@
|
|||||||
import { attr, controller, target } from "@github/catalyst";
|
import { attr, controller, target } from '@github/catalyst';
|
||||||
import { closest, firstUpper } from "core/utils";
|
import { closest, firstUpper } from 'core/utils';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { RouterService } from "core/services";
|
import randomId from 'core/utils/random-id';
|
||||||
import randomId from "core/utils/random-id";
|
import { validatorErrors } from 'core/constants';
|
||||||
import validator from "validator";
|
import { BaseComponentElement, Validator } from 'common/';
|
||||||
import { validatorErrors } from "core/constants";
|
import { AppFormElement } from 'components/app-form/AppFormElement';
|
||||||
import { BaseComponentElement } from "common/";
|
import { validator } from 'core/utils';
|
||||||
import { AppFormElement } from "components/app-form/AppFormElement";
|
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class InputFieldElement extends BaseComponentElement {
|
class InputFieldElement extends BaseComponentElement {
|
||||||
@attr name: string;
|
@attr name: string;
|
||||||
@attr type: string;
|
@attr type: string;
|
||||||
@attr label: string;
|
@attr label: string;
|
||||||
@attr rules: string;
|
@attr rules: string;
|
||||||
@target main: HTMLElement;
|
@target main: HTMLElement;
|
||||||
@target inp: HTMLElement;
|
@target inp: HTMLElement;
|
||||||
@closest appForm: AppFormElement;
|
@closest appForm: AppFormElement;
|
||||||
error: string;
|
valid: boolean;
|
||||||
displayError: boolean;
|
displayError: boolean;
|
||||||
randId: string;
|
randId: string;
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public elementConnected = (): void => {
|
validator: Validator;
|
||||||
this.randId = `${name}${randomId()}`;
|
|
||||||
this.update();
|
|
||||||
this.validate();
|
|
||||||
};
|
|
||||||
|
|
||||||
get valid(): boolean {
|
constructor() {
|
||||||
return !!this.error;
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
get required(): boolean {
|
public elementConnected = (): void => {
|
||||||
return this.rules.includes("required");
|
this.validator = new Validator(this, this.appForm, this.rules);
|
||||||
}
|
this.randId = `${name}${randomId()}`;
|
||||||
|
this.update();
|
||||||
|
this.validate();
|
||||||
|
};
|
||||||
|
|
||||||
get _value() {
|
setError = (error) => {
|
||||||
return (this.inp as HTMLInputElement)?.value;
|
this.validator.error = error;
|
||||||
}
|
};
|
||||||
|
|
||||||
validate = (): boolean => {
|
get error(): string {
|
||||||
let _return = true;
|
return this.validator.error;
|
||||||
const rules = this.rules?.split("|").filter((a) => a);
|
}
|
||||||
const value = (this.inp as HTMLInputElement)?.value;
|
|
||||||
rules
|
|
||||||
.slice()
|
|
||||||
.reverse()
|
|
||||||
.forEach((rule) => {
|
|
||||||
let valid = true;
|
|
||||||
if (rule == "required") {
|
|
||||||
if (value === "") valid = false;
|
|
||||||
} else {
|
|
||||||
if (validator.hasOwnProperty(rule)) {
|
|
||||||
valid = validator?.[rule]?.(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!valid) {
|
|
||||||
const error = validatorErrors[rule]?.replaceAll(
|
|
||||||
"{- name}",
|
|
||||||
firstUpper(this.name?.toString())
|
|
||||||
);
|
|
||||||
_return = false;
|
|
||||||
this.error = error;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (_return) {
|
|
||||||
this.error = null;
|
|
||||||
}
|
|
||||||
return _return;
|
|
||||||
};
|
|
||||||
|
|
||||||
validateDisplay = () => {
|
get isValid(): boolean {
|
||||||
if (!this.validate()) {
|
return this.validator.valid;
|
||||||
this.displayError = true;
|
}
|
||||||
} else {
|
|
||||||
this.displayError = false;
|
|
||||||
}
|
|
||||||
this.update();
|
|
||||||
};
|
|
||||||
|
|
||||||
inputChange = (e) => {
|
get required(): boolean {
|
||||||
this.validate();
|
return this.rules.includes('required');
|
||||||
this.appForm?.inputChange(e);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
get _value() {
|
||||||
const renderMessage = (label: string) => {
|
return (this.inp as HTMLInputElement)?.value;
|
||||||
if (this.label) {
|
}
|
||||||
return html`<label for="${this.randId}"
|
|
||||||
>${this.label}${this.required ? " (*)" : ""}</label
|
|
||||||
>`;
|
|
||||||
}
|
|
||||||
return html``;
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderError = (displayError: boolean, error: string) => {
|
validate = (): boolean => {
|
||||||
if (displayError) {
|
return this.validator.validate();
|
||||||
return html`<span>${error}</span>`;
|
};
|
||||||
}
|
|
||||||
return html``;
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderInput = (type) => {
|
validateDisplay = () => {
|
||||||
return html` <input
|
if (!this.validate()) {
|
||||||
type="${this.type}"
|
this.displayError = true;
|
||||||
data-target="input-field.inp"
|
} else {
|
||||||
app-action="
|
this.displayError = false;
|
||||||
|
}
|
||||||
|
this.update();
|
||||||
|
};
|
||||||
|
|
||||||
|
inputChange = (e) => {
|
||||||
|
this.validate();
|
||||||
|
this.appForm?.inputChange(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
render = (): TemplateResult => {
|
||||||
|
const renderMessage = (label: string) => {
|
||||||
|
if (this.label) {
|
||||||
|
return html`<label for="${this.randId}">${this.label}${this.required ? ' (*)' : ''}</label>`;
|
||||||
|
}
|
||||||
|
return html``;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderError = (displayError: boolean, error: string) => {
|
||||||
|
if (displayError) {
|
||||||
|
return html`<span>${error}</span>`;
|
||||||
|
}
|
||||||
|
return html``;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderInput = (type) => {
|
||||||
|
return html` <input
|
||||||
|
type="${this.type}"
|
||||||
|
data-target="input-field.inp"
|
||||||
|
app-action="
|
||||||
input:input-field#inputChange
|
input:input-field#inputChange
|
||||||
blur:input-field#validateDisplay
|
blur:input-field#validateDisplay
|
||||||
"
|
"
|
||||||
/>`;
|
/>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
return html`<div class="input-main" data-target="input-field.main">
|
return html`<div class="input-main" data-target="input-field.main">
|
||||||
${renderMessage(this.label)} ${renderInput(this.type)}
|
${renderMessage(this.label)} ${renderInput(this.type)} ${renderError(this.displayError, this.error)}
|
||||||
${renderError(this.displayError, this.error)}
|
</div>`;
|
||||||
</div>`;
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { InputFieldElement };
|
export type { InputFieldElement };
|
||||||
|
|||||||
@@ -1,55 +1,47 @@
|
|||||||
import { attr, controller, target } from "@github/catalyst";
|
import { attr, controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { AppMainElement } from "components/app-main/AppMainElement";
|
import { AppMainElement } from 'components/app-main/AppMainElement';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class MenuItemElement extends BaseComponentElement {
|
class MenuItemElement extends BaseComponentElement {
|
||||||
@attr path: string;
|
@attr path: string;
|
||||||
@attr title: string;
|
@attr title: string;
|
||||||
@attr customaction: string;
|
@attr customaction: string;
|
||||||
@target itemEl: HTMLElement;
|
@target itemEl: HTMLElement;
|
||||||
@target customButton: HTMLDivElement;
|
@target customButton: HTMLDivElement;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public elementConnected = (): void => {
|
public elementConnected = (): void => {
|
||||||
if (!this.title && this.innerText) {
|
if (!this.title && this.innerText) {
|
||||||
const _slottedText = this.innerText;
|
const _slottedText = this.innerText;
|
||||||
this.innerText = null;
|
this.innerText = null;
|
||||||
this.title = _slottedText;
|
this.title = _slottedText;
|
||||||
}
|
}
|
||||||
this.update();
|
this.update();
|
||||||
this.appMain.addEventListener("routechanged", this.update);
|
this.appMain.addEventListener('routechanged', this.update);
|
||||||
};
|
};
|
||||||
|
|
||||||
public elementDisconnected = (appMain: AppMainElement): void => {
|
public elementDisconnected = (appMain: AppMainElement): void => {
|
||||||
appMain?.removeEventListener("routechanged", this.update);
|
appMain?.removeEventListener('routechanged', this.update);
|
||||||
};
|
};
|
||||||
|
|
||||||
get current(): boolean {
|
get current(): boolean {
|
||||||
return this.routerService.comparePath(this.path);
|
return this.routerService.comparePath(this.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div class="${this.current ? 'selected ' : ''}menu-item" data-target="menu-item.itemEl">
|
||||||
class="${this.current ? "selected " : ""}menu-item"
|
<app-link data-to="${this.path}">${this.title}</app-link>
|
||||||
data-target="menu-item.itemEl"
|
${this.customaction
|
||||||
>
|
? html`<div data-target="menu-item.customButton" app-action="${this.customaction}">+</div>`
|
||||||
<app-link data-to="${this.path}">${this.title}</app-link>
|
: html``}
|
||||||
${this.customaction
|
</div>
|
||||||
? html`<div
|
`;
|
||||||
data-target="menu-item.customButton"
|
};
|
||||||
app-action="${this.customaction}"
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</div>`
|
|
||||||
: html``}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { MenuItemElement };
|
export type { MenuItemElement };
|
||||||
|
|||||||
@@ -1,70 +1,67 @@
|
|||||||
import { attr, controller, target } from "@github/catalyst";
|
import { attr, controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { BaseComponentElement } from "common/";
|
import { BaseComponentElement } from 'common/';
|
||||||
import { CircleLoaderElement } from "components/circle-loader/CircleLoaderElement";
|
import { CircleLoaderElement } from 'components/circle-loader/CircleLoaderElement';
|
||||||
import { findMethod } from "core/utils";
|
import { findMethod } from 'core/utils';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class WalletHeaderElement extends BaseComponentElement {
|
class WalletHeaderElement extends BaseComponentElement {
|
||||||
@attr currentBalance: number;
|
@attr currentBalance: number;
|
||||||
@attr lastMonth: number;
|
@attr lastMonth: number;
|
||||||
@attr nextMonth: number;
|
@attr nextMonth: number;
|
||||||
@attr currency: string;
|
@attr currency: string;
|
||||||
@attr custom: string;
|
@attr custom: string;
|
||||||
|
|
||||||
fetchFunc: Function = () => {};
|
fetchFunc: Function = () => {};
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.executeFetch();
|
this.executeFetch();
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
attributeChangedCallback(): void {
|
attributeChangedCallback(): void {
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
executeFetch = async (options?): Promise<void> => {
|
get submitFunc() {
|
||||||
const actionString = this.custom;
|
return findMethod(this.custom, this.appMain);
|
||||||
const submitFunc = findMethod(actionString, this.appMain);
|
}
|
||||||
|
|
||||||
try {
|
executeFetch = async (options?): Promise<void> => {
|
||||||
this.loader?.start?.();
|
try {
|
||||||
await submitFunc(options);
|
this.loader?.start?.();
|
||||||
this.loader?.stop?.();
|
await this.submitFunc(options);
|
||||||
} catch (err) {
|
this.loader?.stop?.();
|
||||||
this.loader?.stop?.();
|
} catch (err) {
|
||||||
console.error(err);
|
this.loader?.stop?.();
|
||||||
}
|
console.error(err);
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
const { currentBalance, currency, lastMonth, nextMonth } = this;
|
const { currentBalance, currency, lastMonth, nextMonth } = this;
|
||||||
|
|
||||||
const renderItem = (header, balance, currency) => html`<div>
|
const renderItem = (header, balance, currency) => html`<div>
|
||||||
<div>${header}</div>
|
<div>${header}</div>
|
||||||
<div><span>${balance}</span><span>${currency}</span></div>
|
<div><span>${balance}</span><span>${currency}</span></div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
const renderHeader = () => {
|
const renderHeader = () => {
|
||||||
if (this.loader && this.loader.loading) {
|
if (this.loader && this.loader.loading) {
|
||||||
return html`<circle-loader></circle-loader>`;
|
return html`<circle-loader></circle-loader>`;
|
||||||
}
|
}
|
||||||
return html`${renderItem(
|
return html`${renderItem('Last Month', lastMonth, currency)}${renderItem(
|
||||||
"Last Month",
|
'Current Balance',
|
||||||
lastMonth,
|
currentBalance,
|
||||||
currency
|
currency
|
||||||
)}${renderItem(
|
)}${renderItem('Next Month', nextMonth, currency)}`;
|
||||||
"Current Balance",
|
};
|
||||||
currentBalance,
|
|
||||||
currency
|
|
||||||
)}${renderItem("Next Month", nextMonth, currency)}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
return html`<div>${renderHeader()}</div>`;
|
return html`<div>${renderHeader()}</div>`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { WalletHeaderElement };
|
export type { WalletHeaderElement };
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from "./validatorErrors";
|
export * from './validatorErrors';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export const validatorErrors = {
|
export const validatorErrors = {
|
||||||
required: "{- name} is required.",
|
required: '{- name} is required.',
|
||||||
isEmail: "{- name} needs to be email format.",
|
isEmail: '{- name} needs to be email format.',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,147 +1,100 @@
|
|||||||
import { AppMainElement } from "components/";
|
import { AppMainElement } from 'components/';
|
||||||
import { HttpClient } from "..";
|
import { HttpClient } from '..';
|
||||||
|
|
||||||
class AppService {
|
class AppService {
|
||||||
constructor(
|
constructor(public appMain: AppMainElement, public httpClient: HttpClient) {}
|
||||||
public appMain: AppMainElement,
|
|
||||||
public httpClient: HttpClient
|
|
||||||
) {}
|
|
||||||
|
|
||||||
post = async (
|
post = async (url: string, data: Object, headersParam: HeadersInit): Promise<any> => {
|
||||||
url: string,
|
headersParam = {
|
||||||
data: Object,
|
...headersParam,
|
||||||
headersParam: HeadersInit
|
Authorization: `BEARER ${this.appMain?.authStore?.token}`,
|
||||||
): Promise<any> => {
|
};
|
||||||
headersParam = {
|
try {
|
||||||
...headersParam,
|
this?.appMain?.appLoader?.start?.();
|
||||||
Authorization: `BEARER ${this.appMain?.authStore?.token}`,
|
const response = await this.httpClient.post(url, data, headersParam);
|
||||||
};
|
this?.appMain?.appLoader?.stop?.();
|
||||||
try {
|
if (response?.statusCode == 400 || response?.statusCode == 500 || response?.statusCode == 401) {
|
||||||
this?.appMain?.appLoader?.start?.();
|
if (response?.statusCode == 401) {
|
||||||
const response = await this.httpClient.post(
|
this.appMain.authStore.token = null;
|
||||||
url,
|
this.appMain.routerService.goTo('/token-expired');
|
||||||
data,
|
}
|
||||||
headersParam
|
throw response;
|
||||||
);
|
}
|
||||||
this?.appMain?.appLoader?.stop?.();
|
return response;
|
||||||
if (
|
} catch (err) {
|
||||||
response?.statusCode == 400 ||
|
this?.appMain?.appLoader?.stop?.();
|
||||||
response?.statusCode == 500 ||
|
throw err;
|
||||||
response?.statusCode == 401
|
}
|
||||||
) {
|
};
|
||||||
if (response?.statusCode == 401) {
|
|
||||||
this.appMain.authStore.token = null;
|
|
||||||
this.appMain.routerService.goTo("/token-expired");
|
|
||||||
}
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
} catch (err) {
|
|
||||||
this?.appMain?.appLoader?.stop?.();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
put = async (
|
put = async (url: string, data: Object, headersParam: HeadersInit): Promise<any> => {
|
||||||
url: string,
|
headersParam = {
|
||||||
data: Object,
|
...headersParam,
|
||||||
headersParam: HeadersInit
|
Authorization: `BEARER ${this.appMain?.authStore?.token}`,
|
||||||
): Promise<any> => {
|
};
|
||||||
headersParam = {
|
try {
|
||||||
...headersParam,
|
this?.appMain?.appLoader?.start?.();
|
||||||
Authorization: `BEARER ${this.appMain?.authStore?.token}`,
|
const response = await this.httpClient.put(url, data, headersParam);
|
||||||
};
|
this?.appMain?.appLoader?.stop?.();
|
||||||
try {
|
if (response?.statusCode == 400 || response?.statusCode == 500 || response?.statusCode == 401) {
|
||||||
this?.appMain?.appLoader?.start?.();
|
if (response?.statusCode == 401) {
|
||||||
const response = await this.httpClient.put(url, data, headersParam);
|
this.appMain.authStore.token = null;
|
||||||
this?.appMain?.appLoader?.stop?.();
|
this.appMain.routerService.goTo('/token-expired');
|
||||||
if (
|
}
|
||||||
response?.statusCode == 400 ||
|
throw response;
|
||||||
response?.statusCode == 500 ||
|
}
|
||||||
response?.statusCode == 401
|
return response;
|
||||||
) {
|
} catch (err) {
|
||||||
if (response?.statusCode == 401) {
|
this?.appMain?.appLoader?.stop?.();
|
||||||
this.appMain.authStore.token = null;
|
throw err;
|
||||||
this.appMain.routerService.goTo("/token-expired");
|
}
|
||||||
}
|
};
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
} catch (err) {
|
|
||||||
this?.appMain?.appLoader?.stop?.();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
delete = async (
|
delete = async (url: string, data: Object, headersParam: HeadersInit): Promise<any> => {
|
||||||
url: string,
|
headersParam = {
|
||||||
data: Object,
|
...headersParam,
|
||||||
headersParam: HeadersInit
|
Authorization: `BEARER ${this.appMain?.authStore?.token}`,
|
||||||
): Promise<any> => {
|
};
|
||||||
headersParam = {
|
try {
|
||||||
...headersParam,
|
this?.appMain?.appLoader?.start?.();
|
||||||
Authorization: `BEARER ${this.appMain?.authStore?.token}`,
|
const response = await this.httpClient.delete(url, data, headersParam);
|
||||||
};
|
this?.appMain?.appLoader?.stop?.();
|
||||||
try {
|
if (response?.statusCode == 400 || response?.statusCode == 500 || response?.statusCode == 401) {
|
||||||
this?.appMain?.appLoader?.start?.();
|
if (response?.statusCode == 401) {
|
||||||
const response = await this.httpClient.delete(
|
this.appMain.authStore.token = null;
|
||||||
url,
|
this.appMain.routerService.goTo('/token-expired');
|
||||||
data,
|
}
|
||||||
headersParam
|
throw response;
|
||||||
);
|
}
|
||||||
this?.appMain?.appLoader?.stop?.();
|
return response;
|
||||||
if (
|
} catch (err) {
|
||||||
response?.statusCode == 400 ||
|
this?.appMain?.appLoader?.stop?.();
|
||||||
response?.statusCode == 500 ||
|
throw err;
|
||||||
response?.statusCode == 401
|
}
|
||||||
) {
|
};
|
||||||
if (response?.statusCode == 401) {
|
|
||||||
this.appMain.authStore.token = null;
|
|
||||||
this.appMain.routerService.goTo("/token-expired");
|
|
||||||
}
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
} catch (err) {
|
|
||||||
this?.appMain?.appLoader?.stop?.();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
get = async (
|
get = async (url: string, params: Object, headersParam: HeadersInit): Promise<any> => {
|
||||||
url: string,
|
headersParam = {
|
||||||
params: Object,
|
...headersParam,
|
||||||
headersParam: HeadersInit
|
Authorization: `BEARER ${this.appMain?.authStore?.token}`,
|
||||||
): Promise<any> => {
|
};
|
||||||
headersParam = {
|
try {
|
||||||
...headersParam,
|
this?.appMain?.appLoader?.start?.();
|
||||||
Authorization: `BEARER ${this.appMain?.authStore?.token}`,
|
const response = await this.httpClient.get(url, params, headersParam);
|
||||||
};
|
this?.appMain?.appLoader?.stop?.();
|
||||||
try {
|
if (response?.statusCode == 400 || response?.statusCode == 500 || response?.statusCode == 401) {
|
||||||
this?.appMain?.appLoader?.start?.();
|
if (response?.statusCode == 401) {
|
||||||
const response = await this.httpClient.get(
|
this.appMain.routerService.goTo('/token-expired');
|
||||||
url,
|
this.appMain.authStore.token = null;
|
||||||
params,
|
}
|
||||||
headersParam
|
throw response;
|
||||||
);
|
}
|
||||||
this?.appMain?.appLoader?.stop?.();
|
return response;
|
||||||
if (
|
} catch (err) {
|
||||||
response?.statusCode == 400 ||
|
this?.appMain?.appLoader?.stop?.();
|
||||||
response?.statusCode == 500 ||
|
throw err;
|
||||||
response?.statusCode == 401
|
}
|
||||||
) {
|
};
|
||||||
if (response?.statusCode == 401) {
|
|
||||||
this.appMain.routerService.goTo("/token-expired");
|
|
||||||
this.appMain.authStore.token = null;
|
|
||||||
}
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
} catch (err) {
|
|
||||||
this?.appMain?.appLoader?.stop?.();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AppService;
|
export default AppService;
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
import { AppService } from "core/services";
|
import { AppService } from 'core/services';
|
||||||
|
|
||||||
class BaseService {
|
class BaseService {
|
||||||
constructor(public endpoint: string, public appService: AppService) {}
|
constructor(public endpoint: string, public appService: AppService) {}
|
||||||
|
|
||||||
getAll = (params?: Object, headers?: HeadersInit) => {
|
getAll = (params?: Object, headers?: HeadersInit) => {
|
||||||
return this.appService.get(this.endpoint, params, headers);
|
return this.appService.get(this.endpoint, params, headers);
|
||||||
};
|
};
|
||||||
|
|
||||||
get = (params?: Object, headers?: HeadersInit) => {
|
get = (params?: Object, headers?: HeadersInit) => {
|
||||||
return this.appService.get(this.endpoint, params, headers);
|
return this.appService.get(this.endpoint, params, headers);
|
||||||
};
|
};
|
||||||
|
|
||||||
put = (data?: Object, headers?: HeadersInit) => {
|
put = (data?: Object, headers?: HeadersInit) => {
|
||||||
return this.appService.put(this.endpoint, data, headers);
|
return this.appService.put(this.endpoint, data, headers);
|
||||||
};
|
};
|
||||||
|
|
||||||
post = (data?: Object, headers?: HeadersInit) => {
|
post = (data?: Object, headers?: HeadersInit) => {
|
||||||
return this.appService.post(this.endpoint, data, headers);
|
return this.appService.post(this.endpoint, data, headers);
|
||||||
};
|
};
|
||||||
|
|
||||||
delete = (data?: Object, headers?: HeadersInit) => {
|
delete = (data?: Object, headers?: HeadersInit) => {
|
||||||
return this.appService.delete(this.endpoint, data, headers);
|
return this.appService.delete(this.endpoint, data, headers);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BaseService;
|
export default BaseService;
|
||||||
|
|||||||
@@ -1,124 +1,119 @@
|
|||||||
class HttpClient {
|
class HttpClient {
|
||||||
private url: string;
|
private url: string;
|
||||||
constructor() {
|
constructor() {
|
||||||
this.url = `${__CONFIG__.ssl ? "https" : "http"}://${
|
this.url = `${__CONFIG__.ssl ? 'https' : 'http'}://${__CONFIG__.apiUrl}/${__CONFIG__.apiVersion}`;
|
||||||
__CONFIG__.apiUrl
|
}
|
||||||
}/${__CONFIG__.apiVersion}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
post(url: string, data: Object, headersParam: HeadersInit): Promise<any> {
|
post(url: string, data: Object, headersParam: HeadersInit): Promise<any> {
|
||||||
let headers: Headers = new Headers(headersParam);
|
let headers: Headers = new Headers(headersParam);
|
||||||
let body: BodyType = null;
|
let body: BodyType = null;
|
||||||
if (data instanceof FormData) {
|
if (data instanceof FormData) {
|
||||||
body = data;
|
body = data;
|
||||||
} else {
|
} else {
|
||||||
body = JSON.stringify(data);
|
body = JSON.stringify(data);
|
||||||
headers.append("Content-Type", "application/json");
|
headers.append('Content-Type', 'application/json');
|
||||||
}
|
}
|
||||||
let options: OptionsType = {
|
let options: OptionsType = {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: body,
|
body: body,
|
||||||
};
|
};
|
||||||
const req: Request = new Request(resolveUrl(this.url, url), options);
|
const req: Request = new Request(resolveUrl(this.url, url), options);
|
||||||
|
|
||||||
return createRequest(req);
|
return createRequest(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
put(url: string, data: Object, headersParam: HeadersInit): Promise<any> {
|
put(url: string, data: Object, headersParam: HeadersInit): Promise<any> {
|
||||||
let headers: Headers = new Headers(headersParam);
|
let headers: Headers = new Headers(headersParam);
|
||||||
headers.append("Content-Type", "application/json");
|
headers.append('Content-Type', 'application/json');
|
||||||
let options: OptionsType = {
|
let options: OptionsType = {
|
||||||
method: "PUT",
|
method: 'PUT',
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
};
|
};
|
||||||
const req: Request = new Request(resolveUrl(this.url, url), options);
|
const req: Request = new Request(resolveUrl(this.url, url), options);
|
||||||
|
|
||||||
return createRequest(req);
|
return createRequest(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(url: string, data: Object, headersParam: HeadersInit): Promise<any> {
|
delete(url: string, data: Object, headersParam: HeadersInit): Promise<any> {
|
||||||
let headers: Headers = new Headers(headersParam);
|
let headers: Headers = new Headers(headersParam);
|
||||||
headers.append("Content-Type", "application/json");
|
headers.append('Content-Type', 'application/json');
|
||||||
let options: OptionsType = {
|
let options: OptionsType = {
|
||||||
method: "DELETE",
|
method: 'DELETE',
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
};
|
};
|
||||||
const req: Request = new Request(resolveUrl(this.url, url), options);
|
const req: Request = new Request(resolveUrl(this.url, url), options);
|
||||||
|
|
||||||
return createRequest(req);
|
return createRequest(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(url: string, params: Object, headersParam: HeadersInit): Promise<any> {
|
get(url: string, params: Object, headersParam: HeadersInit): Promise<any> {
|
||||||
let headers: Headers = new Headers(headersParam);
|
let headers: Headers = new Headers(headersParam);
|
||||||
let options: OptionsType = {
|
let options: OptionsType = {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: headers,
|
headers: headers,
|
||||||
};
|
};
|
||||||
let paramsPath: string = "";
|
let paramsPath: string = '';
|
||||||
if (params) {
|
if (params) {
|
||||||
let urlParams = new URLSearchParams(Object.entries(params));
|
let urlParams = new URLSearchParams(Object.entries(params));
|
||||||
paramsPath = "?" + urlParams;
|
paramsPath = '?' + urlParams;
|
||||||
}
|
}
|
||||||
const req: Request = new Request(
|
const req: Request = new Request(resolveUrl(this.url, url + paramsPath), options);
|
||||||
resolveUrl(this.url, url + paramsPath),
|
|
||||||
options
|
|
||||||
);
|
|
||||||
|
|
||||||
return createRequest(req);
|
return createRequest(req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HttpClient;
|
export default HttpClient;
|
||||||
|
|
||||||
async function createRequest(request: Request): Promise<Response> {
|
async function createRequest(request: Request): Promise<Response> {
|
||||||
let response: Response = await fetch(request);
|
let response: Response = await fetch(request);
|
||||||
if (
|
if (
|
||||||
!response.ok &&
|
!response.ok &&
|
||||||
response.status !== 403 &&
|
response.status !== 403 &&
|
||||||
response.status !== 400 &&
|
response.status !== 400 &&
|
||||||
response.status !== 401 &&
|
response.status !== 401 &&
|
||||||
response.status !== 500
|
response.status !== 500
|
||||||
) {
|
) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
} else {
|
} else {
|
||||||
if (response.headers.get("Content-Type") !== null) {
|
if (response.headers.get('Content-Type') !== null) {
|
||||||
let newResponse: Response = await createResponse(response);
|
let newResponse: Response = await createResponse(response);
|
||||||
return newResponse;
|
return newResponse;
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createResponse(response: Response): Promise<any> {
|
async function createResponse(response: Response): Promise<any> {
|
||||||
const type: string = response.headers.get("Content-Type");
|
const type: string = response.headers.get('Content-Type');
|
||||||
const body = (): Promise<any> => {
|
const body = (): Promise<any> => {
|
||||||
if (type.indexOf("application/json") !== -1) {
|
if (type.indexOf('application/json') !== -1) {
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
return response.text();
|
return response.text();
|
||||||
};
|
};
|
||||||
|
|
||||||
return body();
|
return body();
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveUrl(url: string, path: string): string {
|
function resolveUrl(url: string, path: string): string {
|
||||||
if (path.includes("http") || path.includes("://")) {
|
if (path.includes('http') || path.includes('://')) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
const fixedPath = path
|
const fixedPath = path
|
||||||
.split("/")
|
.split('/')
|
||||||
.filter((i) => i)
|
.filter((i) => i)
|
||||||
.join("/");
|
.join('/');
|
||||||
const urlWithPath = `${url.endsWith("/") ? url : `${url}/`}${fixedPath}`;
|
const urlWithPath = `${url.endsWith('/') ? url : `${url}/`}${fixedPath}`;
|
||||||
return urlWithPath;
|
return urlWithPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
type BodyType = string | FormData;
|
type BodyType = string | FormData;
|
||||||
type OptionsType = {
|
type OptionsType = {
|
||||||
method: string;
|
method: string;
|
||||||
headers?: Headers;
|
headers?: Headers;
|
||||||
body?: BodyType;
|
body?: BodyType;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export { default as HttpClient } from "./http-service/HttpClient";
|
export { default as HttpClient } from './http-service/HttpClient';
|
||||||
export { default as BaseService } from "./base-service/BaseService";
|
export { default as BaseService } from './base-service/BaseService';
|
||||||
export { default as RouterService } from "./router-service/RouterService";
|
export { default as RouterService } from './router-service/RouterService';
|
||||||
export { default as AppService } from "./app-service/AppService";
|
export { default as AppService } from './app-service/AppService';
|
||||||
|
|||||||
@@ -1,344 +1,284 @@
|
|||||||
import { BaseLayoutElement } from "common/layouts";
|
import { BaseLayoutElement } from 'common/layouts';
|
||||||
import { AppMainElement } from "components/";
|
import { AppMainElement } from 'components/';
|
||||||
|
|
||||||
class RouterService {
|
class RouterService {
|
||||||
private historyStack: Array<RouteState> = [];
|
private historyStack: Array<RouteState> = [];
|
||||||
private _routes: Array<RouteState> = [];
|
private _routes: Array<RouteState> = [];
|
||||||
constructor(
|
constructor(private appMain: AppMainElement, private mainRoot: ShadowRoot | HTMLElement) {}
|
||||||
private appMain: AppMainElement,
|
|
||||||
private mainRoot: ShadowRoot | HTMLElement
|
|
||||||
) {}
|
|
||||||
|
|
||||||
get routerState(): RouteState {
|
get routerState(): RouteState {
|
||||||
const historyLen = this.historyStack?.length;
|
const historyLen = this.historyStack?.length;
|
||||||
if (historyLen < 1) {
|
if (historyLen < 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.historyStack[historyLen - 1];
|
return this.historyStack[historyLen - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
get emptyState(): boolean {
|
get emptyState(): boolean {
|
||||||
const historyLen = this.historyStack?.length;
|
const historyLen = this.historyStack?.length;
|
||||||
if (historyLen < 2) {
|
if (historyLen < 2) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setRoutes = (routes: Array<any>): void => {
|
public setRoutes = (routes: Array<any>): void => {
|
||||||
if (!Array.isArray(this._routes)) this._routes = [];
|
if (!Array.isArray(this._routes)) this._routes = [];
|
||||||
routes.forEach((route) => {
|
routes.forEach((route) => {
|
||||||
const { path, component, data, layout, middleware, children } =
|
const { path, component, data, layout, middleware, children } = route;
|
||||||
route;
|
const _pathArr = path?.split?.('/').filter((a) => a);
|
||||||
const _pathArr = path?.split?.("/").filter((a) => a);
|
let newPath = ['', ..._pathArr].join('/');
|
||||||
let newPath = ["", ..._pathArr].join("/");
|
if (newPath == '') newPath = '/';
|
||||||
if (newPath == "") newPath = "/";
|
const _routeState: RouteState = new RouteState(newPath, component, data, layout, middleware);
|
||||||
const _routeState: RouteState = new RouteState(
|
if (Array.isArray(children) && children?.length > 0) {
|
||||||
newPath,
|
children.forEach((child) => {
|
||||||
component,
|
const _childState: RouteState = this.createChildState(child, route);
|
||||||
data,
|
this._routes?.push(_childState);
|
||||||
layout,
|
});
|
||||||
middleware
|
}
|
||||||
);
|
this._routes?.push(_routeState);
|
||||||
if (Array.isArray(children) && children?.length > 0) {
|
});
|
||||||
children.forEach((child) => {
|
};
|
||||||
const _childState: RouteState = this.createChildState(
|
|
||||||
child,
|
|
||||||
route
|
|
||||||
);
|
|
||||||
this._routes?.push(_childState);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this._routes?.push(_routeState);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
public update = (): void => {
|
public update = (): void => {
|
||||||
if (!this._routes) return;
|
if (!this._routes) return;
|
||||||
const path = window.location.pathname;
|
const path = window.location.pathname;
|
||||||
const [hasDynamic, _dynamicIndex] = this.hasDynamicPath(path);
|
const [hasDynamic, _dynamicIndex] = this.hasDynamicPath(path);
|
||||||
const _mainRoot = this.mainRoot;
|
const _mainRoot = this.mainRoot;
|
||||||
let route: RouteState = this.routerState;
|
let route: RouteState = this.routerState;
|
||||||
if (route?.middleware) {
|
if (route?.middleware) {
|
||||||
if (
|
if (!(typeof route?.middleware == 'function' && route.middleware()) || route.middleware === false) {
|
||||||
!(
|
return this.goTo('/unauthorized');
|
||||||
typeof route?.middleware == "function" && route.middleware()
|
}
|
||||||
) ||
|
}
|
||||||
route.middleware === false
|
if (
|
||||||
) {
|
path == route?.path ||
|
||||||
return this.goTo("/unauthorized");
|
route?.path == '/not-found' ||
|
||||||
}
|
(hasDynamic && this?._routes?.[_dynamicIndex]?.path == route?.path)
|
||||||
}
|
) {
|
||||||
if (
|
let changed: boolean = false;
|
||||||
path == route?.path ||
|
if (_mainRoot?.childNodes.length > 0) {
|
||||||
route?.path == "/not-found" ||
|
_mainRoot?.childNodes?.forEach?.((child: BaseLayoutElement) => {
|
||||||
(hasDynamic && this?._routes?.[_dynamicIndex]?.path == route?.path)
|
if (
|
||||||
) {
|
route.layout &&
|
||||||
let changed: boolean = false;
|
route.layout.toUpperCase() === child.tagName &&
|
||||||
if (_mainRoot?.childNodes.length > 0) {
|
!child.compareTags(route.component.toUpperCase())
|
||||||
_mainRoot?.childNodes?.forEach?.((child: BaseLayoutElement) => {
|
) {
|
||||||
if (
|
changed = true;
|
||||||
route.layout &&
|
child.setElement(route.component);
|
||||||
route.layout.toUpperCase() === child.tagName &&
|
} else if (route.layout && route.layout.toUpperCase() !== child.tagName) {
|
||||||
!child.compareTags(route.component.toUpperCase())
|
changed = true;
|
||||||
) {
|
const _newElement = document.createElement(route.layout);
|
||||||
changed = true;
|
_newElement.setAttribute('data-target', 'app-root.rootElement');
|
||||||
child.setElement(route.component);
|
_mainRoot.replaceChild(_newElement, child);
|
||||||
} else if (
|
(_newElement as BaseLayoutElement).setElement(route.component);
|
||||||
route.layout &&
|
} else if (!route.layout && child.tagName !== route.component) {
|
||||||
route.layout.toUpperCase() !== child.tagName
|
const _newElement = document.createElement(route.component);
|
||||||
) {
|
_newElement.setAttribute('data-target', 'app-root.rootElement');
|
||||||
changed = true;
|
changed = true;
|
||||||
const _newElement = document.createElement(
|
_mainRoot.replaceChild(_newElement, child);
|
||||||
route.layout
|
}
|
||||||
);
|
});
|
||||||
_newElement.setAttribute(
|
} else {
|
||||||
"data-target",
|
if (route.layout) {
|
||||||
"app-root.rootElement"
|
changed = true;
|
||||||
);
|
const _newElement = document.createElement(route.layout);
|
||||||
_mainRoot.replaceChild(_newElement, child);
|
_newElement.setAttribute('data-target', 'app-root.rootElement');
|
||||||
(_newElement as BaseLayoutElement).setElement(
|
_mainRoot.appendChild(_newElement);
|
||||||
route.component
|
(_newElement as BaseLayoutElement).setElement(route.component);
|
||||||
);
|
} else {
|
||||||
} else if (
|
const _newElement = document.createElement(route.component);
|
||||||
!route.layout &&
|
_newElement.setAttribute('data-target', 'app-root.rootElement');
|
||||||
child.tagName !== route.component
|
changed = true;
|
||||||
) {
|
_mainRoot.appendChild(_newElement);
|
||||||
const _newElement = document.createElement(
|
}
|
||||||
route.component
|
}
|
||||||
);
|
} else {
|
||||||
_newElement.setAttribute(
|
const [isDynamic, _dynamicIndex, dynamicProps] = this.hasDynamicPath(path);
|
||||||
"data-target",
|
let newRoute: RouteState;
|
||||||
"app-root.rootElement"
|
if (isDynamic && _dynamicIndex !== -1) {
|
||||||
);
|
newRoute = this._routes[_dynamicIndex];
|
||||||
changed = true;
|
newRoute.data = dynamicProps;
|
||||||
_mainRoot.replaceChild(_newElement, child);
|
} else {
|
||||||
}
|
newRoute = this.findByPath();
|
||||||
});
|
}
|
||||||
} else {
|
this.historyStack.push(newRoute);
|
||||||
if (route.layout) {
|
this.update();
|
||||||
changed = true;
|
}
|
||||||
const _newElement = document.createElement(route.layout);
|
this.appMain.dispatchEvent(this.appMain?.domEvents.routechanged);
|
||||||
_newElement.setAttribute(
|
};
|
||||||
"data-target",
|
|
||||||
"app-root.rootElement"
|
|
||||||
);
|
|
||||||
_mainRoot.appendChild(_newElement);
|
|
||||||
(_newElement as BaseLayoutElement).setElement(
|
|
||||||
route.component
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const _newElement = document.createElement(route.component);
|
|
||||||
_newElement.setAttribute(
|
|
||||||
"data-target",
|
|
||||||
"app-root.rootElement"
|
|
||||||
);
|
|
||||||
changed = true;
|
|
||||||
_mainRoot.appendChild(_newElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const [isDynamic, _dynamicIndex, dynamicProps] =
|
|
||||||
this.hasDynamicPath(path);
|
|
||||||
let newRoute: RouteState;
|
|
||||||
if (isDynamic && _dynamicIndex !== -1) {
|
|
||||||
newRoute = this._routes[_dynamicIndex];
|
|
||||||
newRoute.data = dynamicProps;
|
|
||||||
} else {
|
|
||||||
newRoute = this.findByPath();
|
|
||||||
}
|
|
||||||
this.historyStack.push(newRoute);
|
|
||||||
this.update();
|
|
||||||
}
|
|
||||||
this.appMain.dispatchEvent(this.appMain?.domEvents.routechanged);
|
|
||||||
};
|
|
||||||
|
|
||||||
public goTo = (path: string, data?: any): void => {
|
public goTo = (path: string, data?: any): void => {
|
||||||
if (!Array.isArray(this.historyStack)) this.historyStack = [];
|
if (!Array.isArray(this.historyStack)) this.historyStack = [];
|
||||||
const currentPath = window.location.pathname;
|
const currentPath = window.location.pathname;
|
||||||
if (path == currentPath) return;
|
if (path == currentPath) return;
|
||||||
if (path.includes(":") && data) {
|
if (path.includes(':') && data) {
|
||||||
path = resolvePath(path, data);
|
path = resolvePath(path, data);
|
||||||
}
|
}
|
||||||
const _index = this._routes.findIndex((route) => route.path === path);
|
const _index = this._routes.findIndex((route) => route.path === path);
|
||||||
const _indexOfEmpty = this._routes.findIndex(
|
const _indexOfEmpty = this._routes.findIndex((route) => route.path === '/not-found');
|
||||||
(route) => route.path === "/not-found"
|
const [isDynamic, _dynamicIndex, dynamicProps] = this.hasDynamicPath(path);
|
||||||
);
|
if (isDynamic) {
|
||||||
const [isDynamic, _dynamicIndex, dynamicProps] =
|
const [isCurrentDynamic, currIndex] = this.hasDynamicPath(currentPath);
|
||||||
this.hasDynamicPath(path);
|
if (path == currentPath) return;
|
||||||
if (isDynamic) {
|
}
|
||||||
const [isCurrentDynamic, currIndex] =
|
let newRoute: RouteState;
|
||||||
this.hasDynamicPath(currentPath);
|
if (isDynamic && _dynamicIndex !== -1) {
|
||||||
if (path == currentPath) return;
|
newRoute = this._routes[_dynamicIndex];
|
||||||
}
|
newRoute.data = dynamicProps;
|
||||||
let newRoute: RouteState;
|
} else if (_index === -1 && _indexOfEmpty !== -1) {
|
||||||
if (isDynamic && _dynamicIndex !== -1) {
|
newRoute = this._routes[_indexOfEmpty];
|
||||||
newRoute = this._routes[_dynamicIndex];
|
} else if (_index === -1 && _indexOfEmpty === -1) {
|
||||||
newRoute.data = dynamicProps;
|
newRoute = new RouteState('/not-found', 'not-found');
|
||||||
} else if (_index === -1 && _indexOfEmpty !== -1) {
|
} else {
|
||||||
newRoute = this._routes[_indexOfEmpty];
|
newRoute = this._routes[_index];
|
||||||
} else if (_index === -1 && _indexOfEmpty === -1) {
|
}
|
||||||
newRoute = new RouteState("/not-found", "not-found");
|
|
||||||
} else {
|
|
||||||
newRoute = this._routes[_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.historyStack.push(newRoute);
|
this.historyStack.push(newRoute);
|
||||||
const url = new URL(window.location.toString());
|
const url = new URL(window.location.toString());
|
||||||
url.pathname = path;
|
url.pathname = path;
|
||||||
window.history.pushState({}, "", url.toString());
|
window.history.pushState({}, '', url.toString());
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
public goBack = (): void => {
|
public goBack = (): void => {
|
||||||
if (!Array.isArray(this.historyStack)) this.historyStack = [];
|
if (!Array.isArray(this.historyStack)) this.historyStack = [];
|
||||||
const lenHistory = this.historyStack.length;
|
const lenHistory = this.historyStack.length;
|
||||||
if (this.canGoBack) {
|
if (this.canGoBack) {
|
||||||
const nextRoute = this.historyStack[lenHistory - 2];
|
const nextRoute = this.historyStack[lenHistory - 2];
|
||||||
const url = new URL(window.location.toString());
|
const url = new URL(window.location.toString());
|
||||||
url.pathname = nextRoute.path;
|
url.pathname = nextRoute.path;
|
||||||
window.history.pushState({}, "", url.toString());
|
window.history.pushState({}, '', url.toString());
|
||||||
this.historyStack.pop();
|
this.historyStack.pop();
|
||||||
}
|
}
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
public get canGoBack(): boolean {
|
public get canGoBack(): boolean {
|
||||||
const lenHistory = this.historyStack.length;
|
const lenHistory = this.historyStack.length;
|
||||||
if (lenHistory > 2) {
|
if (lenHistory > 2) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public init = (): void => {
|
public init = (): void => {
|
||||||
window.addEventListener("popstate", () => {
|
window.addEventListener('popstate', () => {
|
||||||
this.historyStack.pop();
|
this.historyStack.pop();
|
||||||
this.update();
|
this.update();
|
||||||
});
|
});
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
public findByPath = (): RouteState => {
|
public findByPath = (): RouteState => {
|
||||||
const path = window.location.pathname;
|
const path = window.location.pathname;
|
||||||
const _index = this._routes.findIndex((route) => route.path === path);
|
const _index = this._routes.findIndex((route) => route.path === path);
|
||||||
const _indexOfEmpty = this._routes.findIndex(
|
const _indexOfEmpty = this._routes.findIndex((route) => route.path === '/not-found');
|
||||||
(route) => route.path === "/not-found"
|
if (_index === -1 && _indexOfEmpty !== -1) {
|
||||||
);
|
return this._routes[_indexOfEmpty];
|
||||||
if (_index === -1 && _indexOfEmpty !== -1) {
|
} else if (_index === -1 && _indexOfEmpty === -1) {
|
||||||
return this._routes[_indexOfEmpty];
|
return new RouteState('/not-found', 'not-found');
|
||||||
} else if (_index === -1 && _indexOfEmpty === -1) {
|
}
|
||||||
return new RouteState("/not-found", "not-found");
|
return this._routes[_index];
|
||||||
}
|
};
|
||||||
return this._routes[_index];
|
|
||||||
};
|
|
||||||
|
|
||||||
public comparePath = (path: string): boolean => {
|
public comparePath = (path: string): boolean => {
|
||||||
if (this.routerState?.fullPath === path) {
|
if (this.routerState?.fullPath === path) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
private createChildState = (child: any, parent: any): RouteState => {
|
private createChildState = (child: any, parent: any): RouteState => {
|
||||||
const { path, middleware, layout, component, data, children } = child;
|
const { path, middleware, layout, component, data, children } = child;
|
||||||
const _pathArr = path?.split?.("/").filter((a) => a);
|
const _pathArr = path?.split?.('/').filter((a) => a);
|
||||||
const _parentArr = parent?.path?.split?.("/").filter((a) => a);
|
const _parentArr = parent?.path?.split?.('/').filter((a) => a);
|
||||||
const newPath = ["", ..._parentArr, ..._pathArr].join("/");
|
const newPath = ['', ..._parentArr, ..._pathArr].join('/');
|
||||||
const _child = new RouteState(
|
const _child = new RouteState(newPath, component, data, layout, middleware ? middleware : parent?.middleware);
|
||||||
newPath,
|
|
||||||
component,
|
|
||||||
data,
|
|
||||||
layout,
|
|
||||||
middleware ? middleware : parent?.middleware
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Array.isArray(children) && children?.length > 0) {
|
if (Array.isArray(children) && children?.length > 0) {
|
||||||
children.forEach((child2) => {
|
children.forEach((child2) => {
|
||||||
const _childState: RouteState = this.createChildState(
|
const _childState: RouteState = this.createChildState(child2, _child);
|
||||||
child2,
|
this._routes?.push(_childState);
|
||||||
_child
|
});
|
||||||
);
|
}
|
||||||
this._routes?.push(_childState);
|
return _child;
|
||||||
});
|
};
|
||||||
}
|
|
||||||
return _child;
|
|
||||||
};
|
|
||||||
|
|
||||||
private hasDynamicPath = (path: string): [boolean, number, any] => {
|
private hasDynamicPath = (path: string): [boolean, number, any] => {
|
||||||
const _pathArr = path.split("/").filter((a) => a);
|
const _pathArr = path.split('/').filter((a) => a);
|
||||||
let matchedIndex: number = 0;
|
let matchedIndex: number = 0;
|
||||||
let matched: boolean = false;
|
let matched: boolean = false;
|
||||||
let dynamicProps: any = {};
|
let dynamicProps: any = {};
|
||||||
let shouldSkip = false;
|
let shouldSkip = false;
|
||||||
this._routes.forEach((route, _routeId) => {
|
this._routes.forEach((route, _routeId) => {
|
||||||
if (shouldSkip) {
|
if (shouldSkip) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (path == route.path) {
|
if (path == route.path) {
|
||||||
matched = path?.includes(":") ? true : false;
|
matched = path?.includes(':') ? true : false;
|
||||||
matchedIndex = _routeId;
|
matchedIndex = _routeId;
|
||||||
shouldSkip = true;
|
shouldSkip = true;
|
||||||
}
|
}
|
||||||
const _routeArr = route.path.split("/").filter((a) => a);
|
const _routeArr = route.path.split('/').filter((a) => a);
|
||||||
if (_pathArr.length === _routeArr.length) {
|
if (_pathArr.length === _routeArr.length) {
|
||||||
let pathMatches: number = 0;
|
let pathMatches: number = 0;
|
||||||
let hasDynamic: boolean = false;
|
let hasDynamic: boolean = false;
|
||||||
_pathArr.forEach((pathr, i) => {
|
_pathArr.forEach((pathr, i) => {
|
||||||
if (pathr == _routeArr[i]) {
|
if (pathr == _routeArr[i]) {
|
||||||
pathMatches++;
|
pathMatches++;
|
||||||
} else if (_routeArr[i].startsWith?.(":")) {
|
} else if (_routeArr[i].startsWith?.(':')) {
|
||||||
pathMatches++;
|
pathMatches++;
|
||||||
hasDynamic = true;
|
hasDynamic = true;
|
||||||
dynamicProps[_routeArr[i].substr(1)] = pathr;
|
dynamicProps[_routeArr[i].substr(1)] = pathr;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (pathMatches === _pathArr.length && hasDynamic) {
|
if (pathMatches === _pathArr.length && hasDynamic) {
|
||||||
matchedIndex = _routeId;
|
matchedIndex = _routeId;
|
||||||
matched = true;
|
matched = true;
|
||||||
shouldSkip = true;
|
shouldSkip = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return [matched, matchedIndex, dynamicProps];
|
return [matched, matchedIndex, dynamicProps];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class RouteState {
|
class RouteState {
|
||||||
constructor(
|
constructor(
|
||||||
public path: string,
|
public path: string,
|
||||||
public component: string,
|
public component: string,
|
||||||
public data?: any,
|
public data?: any,
|
||||||
public layout?: string,
|
public layout?: string,
|
||||||
public middleware?: any
|
public middleware?: any
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
get fullPath(): string {
|
get fullPath(): string {
|
||||||
return resolvePath(this.path, this.data);
|
return resolvePath(this.path, this.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DynamicProp = {
|
type DynamicProp = {
|
||||||
index: string;
|
index: string;
|
||||||
path: string;
|
path: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function resolvePath(path: string, data: any): string {
|
function resolvePath(path: string, data: any): string {
|
||||||
const _pathArr = path
|
const _pathArr = path
|
||||||
.split("/")
|
.split('/')
|
||||||
.filter((a) => a)
|
.filter((a) => a)
|
||||||
.map((pathPart) => {
|
.map((pathPart) => {
|
||||||
if (pathPart.startsWith(":")) {
|
if (pathPart.startsWith(':')) {
|
||||||
pathPart = data?.[pathPart.substr(1)];
|
pathPart = data?.[pathPart.substr(1)];
|
||||||
}
|
}
|
||||||
return pathPart;
|
return pathPart;
|
||||||
});
|
});
|
||||||
let _return = ["", ..._pathArr].join("/");
|
let _return = ['', ..._pathArr].join('/');
|
||||||
if (_return == "") {
|
if (_return == '') {
|
||||||
_return = "/";
|
_return = '/';
|
||||||
}
|
}
|
||||||
return _return;
|
return _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RouterService;
|
export default RouterService;
|
||||||
|
|||||||
@@ -1,98 +1,94 @@
|
|||||||
import { AppMainElement } from "components/";
|
import { AppMainElement } from 'components/';
|
||||||
import { AppService } from "core/services";
|
import { AppService } from 'core/services';
|
||||||
import { isTrue } from "core/utils";
|
import { isTrue } from 'core/utils';
|
||||||
import { AuthService } from "services/";
|
import { AuthService } from 'services/';
|
||||||
|
|
||||||
class AuthStore {
|
class AuthStore {
|
||||||
private _token: string;
|
private _token: string;
|
||||||
private _userDetails: UserDetails;
|
private _userDetails: UserDetails;
|
||||||
private authService: AuthService;
|
private authService: AuthService;
|
||||||
constructor(
|
constructor(private appMain: AppMainElement, private appService: AppService) {
|
||||||
private appMain: AppMainElement,
|
const _token = localStorage.getItem('token');
|
||||||
private appService: AppService
|
if (_token) this.token = _token;
|
||||||
) {
|
this.authService = new AuthService(this.appService);
|
||||||
const _token = localStorage.getItem("token");
|
this.checkToken(_token);
|
||||||
if (_token) this.token = _token;
|
}
|
||||||
this.authService = new AuthService(this.appService);
|
|
||||||
this.checkToken(_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
get token(): string {
|
get token(): string {
|
||||||
if (this._token == "null") return null;
|
if (this._token == 'null') return null;
|
||||||
if (this._token == "undefined") return undefined;
|
if (this._token == 'undefined') return undefined;
|
||||||
return this._token;
|
return this._token;
|
||||||
}
|
}
|
||||||
|
|
||||||
set token(token: string) {
|
set token(token: string) {
|
||||||
const { _token } = this;
|
const { _token } = this;
|
||||||
const _changed = token != _token;
|
const _changed = token != _token;
|
||||||
console.log(token);
|
if (_changed) {
|
||||||
if (_changed) {
|
this._token = token;
|
||||||
this._token = token;
|
localStorage.setItem('token', token);
|
||||||
localStorage.setItem("token", token);
|
this.appMain.dispatchEvent(this.appMain?.domEvents.tokenchange);
|
||||||
this.appMain.dispatchEvent(this.appMain?.domEvents.tokenchange);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
get user(): UserDetails {
|
get user(): UserDetails {
|
||||||
return this._userDetails;
|
return this._userDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
set user(userDetails: UserDetails) {
|
set user(userDetails: UserDetails) {
|
||||||
this._userDetails = userDetails;
|
this._userDetails = userDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkToken = async (token: string) => {
|
checkToken = async (token: string) => {
|
||||||
try {
|
try {
|
||||||
if (token && token !== "null") {
|
if (token && token !== 'null') {
|
||||||
const response = await this.authService.checkToken({ token });
|
const response = await this.authService.checkToken({ token });
|
||||||
if (!(response && response.valid)) {
|
if (!(response && response.valid)) {
|
||||||
this.token = null;
|
this.token = null;
|
||||||
this.appMain.routerService.goTo("/token-expired");
|
this.appMain.routerService.goTo('/token-expired');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.token = null;
|
this.token = null;
|
||||||
this.appMain.routerService.goTo("/token-expired");
|
this.appMain.routerService.goTo('/token-expired');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
userLogin = async (formObject) => {
|
userLogin = async (formObject) => {
|
||||||
try {
|
try {
|
||||||
const response = await this.authService.login(formObject);
|
const response = await this.authService.login(formObject);
|
||||||
if (response?.token) {
|
if (response?.token) {
|
||||||
this.token = response.token;
|
this.token = response.token;
|
||||||
} else {
|
} else {
|
||||||
this.token = null;
|
this.token = null;
|
||||||
localStorage.removeItem("token");
|
localStorage.removeItem('token');
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
userRegister = async (formObject) => {
|
userRegister = async (formObject) => {
|
||||||
try {
|
try {
|
||||||
const response = await this.authService.register(formObject);
|
const response = await this.authService.register(formObject);
|
||||||
return response;
|
return response;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
userLogout = (): void => {
|
userLogout = (): void => {
|
||||||
this.token = null;
|
this.token = null;
|
||||||
localStorage.removeItem("token");
|
localStorage.removeItem('token');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AuthStore;
|
export default AuthStore;
|
||||||
|
|
||||||
export type UserDetails = {
|
export type UserDetails = {
|
||||||
id: string;
|
id: string;
|
||||||
username: string;
|
username: string;
|
||||||
email: string;
|
email: string;
|
||||||
dateCreated: string;
|
dateCreated: string;
|
||||||
dateUpdated: string;
|
dateUpdated: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export { default as AuthStore } from "./AuthStore";
|
export { default as AuthStore } from './AuthStore';
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { toKebabCase } from "core/utils";
|
import { toKebabCase } from 'core/utils';
|
||||||
|
|
||||||
export default function closest(proto: Object, key: string): any {
|
export default function closest(proto: Object, key: string): any {
|
||||||
const kebab: string = toKebabCase(key);
|
const kebab: string = toKebabCase(key);
|
||||||
return Object.defineProperty(proto, key, {
|
return Object.defineProperty(proto, key, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get() {
|
get() {
|
||||||
return findClosest(this, kebab);
|
return findClosest(this, kebab);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function findClosest(element: HTMLElement, key: string): HTMLElement {
|
function findClosest(element: HTMLElement, key: string): HTMLElement {
|
||||||
return element.closest(key);
|
return element.closest(key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
import { AppMainElement } from "components/";
|
import { AppMainElement } from 'components/';
|
||||||
|
|
||||||
export default function findMethod(
|
export default function findMethod(actionString: string, appMain: AppMainElement): Function {
|
||||||
actionString: string,
|
if (actionString && appMain) {
|
||||||
appMain: AppMainElement
|
const methodSep = actionString.lastIndexOf('#');
|
||||||
): Function {
|
const tag = actionString.slice(0, methodSep);
|
||||||
if (actionString) {
|
const method = actionString.slice(methodSep + 1);
|
||||||
const methodSep = actionString.lastIndexOf("#");
|
|
||||||
const tag = actionString.slice(0, methodSep);
|
|
||||||
const method = actionString.slice(methodSep + 1);
|
|
||||||
|
|
||||||
const element = appMain.querySelector(tag);
|
const element = appMain.querySelector(tag);
|
||||||
if (element) {
|
if (element) {
|
||||||
return element?.[method];
|
return element?.[method];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return () => {};
|
return () => {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export default function firstUpper(s: string): string {
|
export default function firstUpper(s: string): string {
|
||||||
if (typeof s !== "string") return "";
|
if (typeof s !== 'string') return '';
|
||||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export default function index(proto: Object, key: string): Object {
|
export default function index(proto: Object, key: string): Object {
|
||||||
return Object.defineProperty(proto, key, {
|
return Object.defineProperty(proto, key, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get() {
|
get() {
|
||||||
return Array.from(this.parentNode.children).indexOf(this);
|
return Array.from(this.parentNode.children).indexOf(this);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
export { default as toKebabCase } from "./toKebabCase";
|
export * from './library';
|
||||||
export { default as update } from "./update-deco";
|
export * from './templating';
|
||||||
export { default as index } from "./index-deco";
|
|
||||||
export { default as closest } from "./closest-deco";
|
export { default as toKebabCase } from './toKebabCase';
|
||||||
export { default as isTrue } from "./isTrue";
|
export { default as update } from './update-deco';
|
||||||
export { default as firstUpper } from "./first-upper";
|
export { default as index } from './index-deco';
|
||||||
export { default as query } from "./query-deco";
|
export { default as closest } from './closest-deco';
|
||||||
export { default as querys } from "./querys-deco";
|
export { default as isTrue } from './isTrue';
|
||||||
export { default as findMethod } from "./find-method";
|
export { default as firstUpper } from './first-upper';
|
||||||
|
export { default as query } from './query-deco';
|
||||||
|
export { default as querys } from './querys-deco';
|
||||||
|
export { default as findMethod } from './find-method';
|
||||||
|
export { default as validator } from './validator';
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export default function isTrue(text: string): boolean {
|
export default function isTrue(text: string): boolean {
|
||||||
return text === "true";
|
return text === 'true';
|
||||||
}
|
}
|
||||||
|
|||||||
3
src/core/utils/library.ts
Normal file
3
src/core/utils/library.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { attr, controller, target, targets} from '@github/catalyst';
|
||||||
|
|
||||||
|
export { attr, controller, target, targets }
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { toKebabCase } from "core/utils";
|
import { toKebabCase } from 'core/utils';
|
||||||
|
|
||||||
export default function query(proto: Object, key: string): any {
|
export default function query(proto: Object, key: string): any {
|
||||||
const kebab: string = toKebabCase(key);
|
const kebab: string = toKebabCase(key);
|
||||||
return Object.defineProperty(proto, key, {
|
return Object.defineProperty(proto, key, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get() {
|
get() {
|
||||||
return findQuery(this, kebab);
|
return findQuery(this, kebab);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function findQuery(element: HTMLElement, key: string): HTMLElement {
|
function findQuery(element: HTMLElement, key: string): HTMLElement {
|
||||||
return element.querySelector(key);
|
return element.querySelector(key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
import { toKebabCase } from "core/utils";
|
import { toKebabCase } from 'core/utils';
|
||||||
|
|
||||||
export default function querys(proto: Object, key: string): any {
|
export default function querys(proto: Object, key: string): any {
|
||||||
const kebab: string = toKebabCase(key);
|
const kebab: string = toKebabCase(key);
|
||||||
return Object.defineProperty(proto, key, {
|
return Object.defineProperty(proto, key, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get() {
|
get() {
|
||||||
return findQuerys(this, kebab);
|
return findQuerys(this, kebab);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function findQuerys(
|
function findQuerys(element: HTMLElement, key: string): NodeListOf<HTMLElement> {
|
||||||
element: HTMLElement,
|
return element.querySelectorAll(key);
|
||||||
key: string
|
|
||||||
): NodeListOf<HTMLElement> {
|
|
||||||
return element.querySelectorAll(key);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export default function randomId(): string {
|
export default function randomId(): string {
|
||||||
return "_" + Math.random().toString(36).substr(2, 5);
|
return '_' + Math.random().toString(36).substr(2, 5);
|
||||||
}
|
}
|
||||||
|
|||||||
3
src/core/utils/templating.ts
Normal file
3
src/core/utils/templating.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { render, html, TemplateResult } from 'lit-html';
|
||||||
|
|
||||||
|
export { render, html, TemplateResult };
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
export default function toKebabCase(text: string): string {
|
export default function toKebabCase(text: string): string {
|
||||||
return text
|
return text
|
||||||
.replace(/([a-z])([A-Z])/g, "$1-$2")
|
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
||||||
.replace(/\s+/g, "-")
|
.replace(/\s+/g, '-')
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export default function update(proto: any, key?: string, dir?: any): any {
|
export default function update(proto: any, key?: string, dir?: any): any {
|
||||||
const method: Function = dir.value!;
|
const method: Function = dir.value!;
|
||||||
dir.value = function () {
|
dir.value = function () {
|
||||||
const _return = method.apply(this, arguments);
|
const _return = method.apply(this, arguments);
|
||||||
if (proto.update) proto.update.call(this);
|
if (proto.update) proto.update.call(this);
|
||||||
return _return;
|
return _return;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/core/utils/validator.ts
Normal file
25
src/core/utils/validator.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import isEmail from 'validator/lib/isEmail';
|
||||||
|
import isDate from 'validator/lib/isDate';
|
||||||
|
import isNumeric from 'validator/lib/isNumeric';
|
||||||
|
import matches from 'validator/lib/matches';
|
||||||
|
|
||||||
|
const validator = {
|
||||||
|
is_email: [isEmail, '{- name} needs to be email format.'],
|
||||||
|
is_date: isDate,
|
||||||
|
is_numeric: isNumeric,
|
||||||
|
matches: matches,
|
||||||
|
is_same: [isSame, '{- name} needs to be same to {- field}.'],
|
||||||
|
required: [required, '{- name} is required.'],
|
||||||
|
};
|
||||||
|
|
||||||
|
function required(str: string): boolean {
|
||||||
|
if (!str || str == '') return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSame(str: string, field: string): boolean {
|
||||||
|
if (str === field) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default validator;
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Wallet Web</title>
|
<title>Wallet Web</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: #303030;
|
background-color: #303030;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<app-shadow></app-shadow>
|
<app-shadow></app-shadow>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import "layouts";
|
import 'layouts';
|
||||||
import "components";
|
import 'components';
|
||||||
import "pages";
|
import 'pages';
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export * from "./menu-layout/MenuLayoutElement";
|
export * from './menu-layout/MenuLayoutElement';
|
||||||
export * from "./initial-layout/InitialLayoutElement";
|
export * from './initial-layout/InitialLayoutElement';
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { closest } from "core/utils";
|
import { closest } from 'core/utils';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { BaseLayoutElement } from "common/layouts";
|
import { BaseLayoutElement } from 'common/layouts';
|
||||||
import { AppMainElement } from "components/";
|
import { AppMainElement } from 'components/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class InitialLayoutElement extends BaseLayoutElement {
|
class InitialLayoutElement extends BaseLayoutElement {
|
||||||
@closest appMain: AppMainElement;
|
@closest appMain: AppMainElement;
|
||||||
@target appPage: HTMLDivElement;
|
@target appPage: HTMLDivElement;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
elementDisconnected = (appMain: AppMainElement): void => {};
|
elementDisconnected = (appMain: AppMainElement): void => {};
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`
|
return html`
|
||||||
<div data-target="initial-layout.appPage">
|
<div data-target="initial-layout.appPage">
|
||||||
<app-slot data-target="initial-layout.appSlot"></app-slot>
|
<app-slot data-target="initial-layout.appSlot"></app-slot>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { InitialLayoutElement };
|
export type { InitialLayoutElement };
|
||||||
|
|||||||
@@ -1,50 +1,50 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { closest } from "core/utils";
|
import { closest } from 'core/utils';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { BaseLayoutElement } from "common/layouts";
|
import { BaseLayoutElement } from 'common/layouts';
|
||||||
import { AppMainElement } from "components/";
|
import { AppMainElement } from 'components/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class MenuLayoutElement extends BaseLayoutElement {
|
class MenuLayoutElement extends BaseLayoutElement {
|
||||||
@closest appMain: AppMainElement;
|
@closest appMain: AppMainElement;
|
||||||
@target appPage: HTMLDivElement;
|
@target appPage: HTMLDivElement;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.update();
|
this.update();
|
||||||
this.appMain.addEventListener("tokenchange", this.updateAuth);
|
this.appMain.addEventListener('tokenchange', this.updateAuth);
|
||||||
this.appMain.addEventListener("routechanged", this.updateAuth);
|
this.appMain.addEventListener('routechanged', this.updateAuth);
|
||||||
};
|
};
|
||||||
|
|
||||||
elementDisconnected = (appMain: AppMainElement): void => {
|
elementDisconnected = (appMain: AppMainElement): void => {
|
||||||
appMain?.removeEventListener("tokenchange", this.updateAuth);
|
appMain?.removeEventListener('tokenchange', this.updateAuth);
|
||||||
appMain?.removeEventListener("routechanged", this.updateAuth);
|
appMain?.removeEventListener('routechanged', this.updateAuth);
|
||||||
};
|
};
|
||||||
|
|
||||||
get isAuth(): boolean {
|
get isAuth(): boolean {
|
||||||
const _is = this.appMain?.routerService?.routerState?.middleware;
|
const _is = this.appMain?.routerService?.routerState?.middleware;
|
||||||
if (typeof _is == "function") {
|
if (typeof _is == 'function') {
|
||||||
return _is();
|
return _is();
|
||||||
}
|
}
|
||||||
return !!_is;
|
return !!_is;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAuth = (): void => {
|
updateAuth = (): void => {
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
const _isAuth = this.isAuth;
|
const _isAuth = this.isAuth;
|
||||||
return html`
|
return html`
|
||||||
<div data-target="menu-layout.appPage">
|
<div data-target="menu-layout.appPage">
|
||||||
${_isAuth ? html`<app-menu></app-menu>` : html``}
|
${_isAuth ? html`<app-menu></app-menu>` : html``}
|
||||||
<app-slot data-target="menu-layout.appSlot"></app-slot>
|
<app-slot data-target="menu-layout.appSlot"></app-slot>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { MenuLayoutElement };
|
export type { MenuLayoutElement };
|
||||||
|
|||||||
@@ -1,63 +1,57 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { TransactionsService } from "services/";
|
import { TransactionsService } from 'services/';
|
||||||
import { AppMainElement, AppPaginationElement } from "components/";
|
import { AppMainElement, AppPaginationElement } from 'components/';
|
||||||
import { BasePageElement } from "common/";
|
import { BasePageElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class HistoryPageElement extends BasePageElement {
|
class HistoryPageElement extends BasePageElement {
|
||||||
private transactionsService: TransactionsService;
|
private transactionsService: TransactionsService;
|
||||||
@target pagination: AppPaginationElement;
|
@target pagination: AppPaginationElement;
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
title: "Transaction History",
|
title: 'Transaction History',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.transactionsService = new TransactionsService(
|
this.transactionsService = new TransactionsService(this.appMain?.appService);
|
||||||
this.appMain?.appService
|
this.update();
|
||||||
);
|
this.pagination?.setFetchFunc?.(this.getTransactions, true)!;
|
||||||
this.update();
|
this.appMain.addEventListener('tokenchange', this.update);
|
||||||
this.pagination?.setFetchFunc?.(this.getTransactions, true)!;
|
};
|
||||||
this.appMain.addEventListener("tokenchange", this.update);
|
|
||||||
};
|
|
||||||
|
|
||||||
elementDisconnected = (appMain: AppMainElement): void => {
|
elementDisconnected = (appMain: AppMainElement): void => {
|
||||||
appMain?.removeEventListener("tokenchange", this.update);
|
appMain?.removeEventListener('tokenchange', this.update);
|
||||||
};
|
};
|
||||||
|
|
||||||
getTransactions = async (options): Promise<any> => {
|
getTransactions = async (options): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
if (this?.routerService?.routerState?.data) {
|
if (this?.routerService?.routerState?.data) {
|
||||||
const { walletId } = this?.routerService?.routerState?.data;
|
const { walletId } = this?.routerService?.routerState?.data;
|
||||||
if (walletId) {
|
if (walletId) {
|
||||||
options["walletId"] = walletId;
|
options['walletId'] = walletId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const response = await this.transactionsService.getAll(options);
|
const response = await this.transactionsService.getAll(options);
|
||||||
return response;
|
return response;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
const renderWallet = () => {
|
const renderWallet = () => {
|
||||||
if (this.routerService?.routerState?.data?.walletId) {
|
if (this.routerService?.routerState?.data?.walletId) {
|
||||||
return html`<span
|
return html`<span>${this.routerService?.routerState?.data?.walletId}</span>`;
|
||||||
>${this.routerService?.routerState?.data?.walletId}</span
|
}
|
||||||
>`;
|
return html``;
|
||||||
}
|
};
|
||||||
return html``;
|
return html`<div>
|
||||||
};
|
${renderWallet()}
|
||||||
return html`<div>
|
<app-pagination data-target="history-page.pagination"></app-pagination>
|
||||||
${renderWallet()}
|
</div>`;
|
||||||
<app-pagination
|
};
|
||||||
data-target="history-page.pagination"
|
|
||||||
></app-pagination>
|
|
||||||
</div>`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { HistoryPageElement };
|
export type { HistoryPageElement };
|
||||||
|
|||||||
@@ -1,69 +1,69 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult, until } from "@github/jtml";
|
import { html, TemplateResult, until } from 'core/utils';
|
||||||
import { WalletService } from "services/";
|
import { WalletService } from 'services/';
|
||||||
import { AppMainElement, WalletHeaderElement } from "components/";
|
import { AppMainElement, WalletHeaderElement } from 'components/';
|
||||||
import { BasePageElement } from "common/";
|
import { BasePageElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class HomePageElement extends BasePageElement {
|
class HomePageElement extends BasePageElement {
|
||||||
@target walletHeader: WalletHeaderElement;
|
@target walletHeader: WalletHeaderElement;
|
||||||
private walletService: WalletService;
|
private walletService: WalletService;
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
title: "Home",
|
title: 'Home',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.walletService = new WalletService(this.appMain?.appService);
|
this.walletService = new WalletService(this.appMain?.appService);
|
||||||
this.update();
|
this.update();
|
||||||
this.appMain.addEventListener("tokenchange", this.update);
|
this.appMain.addEventListener('tokenchange', this.update);
|
||||||
this.getBalance();
|
this.getBalance();
|
||||||
};
|
};
|
||||||
|
|
||||||
elementDisconnected = (appMain: AppMainElement): void => {
|
elementDisconnected = (appMain: AppMainElement): void => {
|
||||||
appMain?.removeEventListener("tokenchange", this.update);
|
appMain?.removeEventListener('tokenchange', this.update);
|
||||||
};
|
};
|
||||||
|
|
||||||
getBalance = async (): Promise<void> => {
|
getBalance = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const response = await this.walletService.getBalance();
|
const response = await this.walletService.getBalance();
|
||||||
this.setBalance(response);
|
this.setBalance(response);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setBalance = (header) => {
|
setBalance = (header) => {
|
||||||
if (!this.walletHeader) return;
|
if (!this.walletHeader) return;
|
||||||
this.walletHeader.currency = header.currency;
|
this.walletHeader.currency = header.currency;
|
||||||
this.walletHeader.currentBalance = header.currentBalance || "0";
|
this.walletHeader.currentBalance = header.currentBalance || '0';
|
||||||
this.walletHeader.lastMonth = header.lastMonth || "0";
|
this.walletHeader.lastMonth = header.lastMonth || '0';
|
||||||
this.walletHeader.nextMonth = header.nextMonth || "0";
|
this.walletHeader.nextMonth = header.nextMonth || '0';
|
||||||
};
|
};
|
||||||
|
|
||||||
openModal = (): void => {
|
openModal = (): void => {
|
||||||
const _modal = this.appMain.appModal;
|
const _modal = this.appMain.appModal;
|
||||||
if (_modal) {
|
if (_modal) {
|
||||||
this.appMain.closeModal();
|
this.appMain.closeModal();
|
||||||
} else {
|
} else {
|
||||||
this.appMain.createModal("wallet-create");
|
this.appMain.createModal('wallet-create');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`
|
return html`
|
||||||
<button app-action="click:home-page#openModal">New Wallet</button>
|
<button app-action="click:home-page#openModal">New Wallet</button>
|
||||||
<wallet-header
|
<wallet-header
|
||||||
data-target="home-page.walletHeader"
|
data-target="home-page.walletHeader"
|
||||||
data-current-balance="0"
|
data-current-balance="0"
|
||||||
data-last-month="0"
|
data-last-month="0"
|
||||||
data-next-month="0"
|
data-next-month="0"
|
||||||
data-currency="0"
|
data-currency="0"
|
||||||
data-custom="home-page#getBalance"
|
data-custom="home-page#getBalance"
|
||||||
></wallet-header>
|
></wallet-header>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export { HomePageElement };
|
export { HomePageElement };
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
export * from "./logout-page/LogoutPageElement";
|
export * from './logout-page/LogoutPageElement';
|
||||||
export * from "./home-page/HomePageElement";
|
export * from './home-page/HomePageElement';
|
||||||
export * from "./register-page/RegisterPageElement";
|
export * from './register-page/RegisterPageElement';
|
||||||
export * from "./login-page/LoginPageElement";
|
export * from './login-page/LoginPageElement';
|
||||||
export * from "./not-found/NotFoundElement";
|
export * from './not-found/NotFoundElement';
|
||||||
export * from "./history-page/HistoryPageElement";
|
export * from './history-page/HistoryPageElement';
|
||||||
export * from "./wallet-list/WalletListElement";
|
export * from './wallet-list/WalletListElement';
|
||||||
export * from "./wallet-create/WalletCreateElement";
|
export * from './wallet-create/WalletCreateElement';
|
||||||
export * from "./transaction-create/TransactionCreateElement";
|
export * from './transaction-create/TransactionCreateElement';
|
||||||
export * from "./wallet-page/WalletPageElement";
|
export * from './wallet-page/WalletPageElement';
|
||||||
|
|||||||
@@ -1,114 +1,107 @@
|
|||||||
import { targets, controller, target } from "@github/catalyst";
|
import { targets, controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
//import { html, TemplateResult } from "core/utils";
|
||||||
import { AuthService } from "services/";
|
import { html, render, TemplateResult } from 'core/utils';
|
||||||
import { AppFormElement, InputFieldElement } from "components/";
|
import { AuthService } from 'services/';
|
||||||
import { RouterService } from "core/services";
|
import { AppFormElement, InputFieldElement } from 'components/';
|
||||||
import { BasePageElement } from "common/";
|
import { RouterService } from 'core/services';
|
||||||
|
import { BasePageElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class LoginPageElement extends BasePageElement {
|
class LoginPageElement extends BasePageElement {
|
||||||
@targets inputs: Array<InputFieldElement>;
|
@targets inputs: Array<InputFieldElement>;
|
||||||
@target appForm: AppFormElement;
|
@target appForm: AppFormElement;
|
||||||
authService: AuthService;
|
authService: AuthService;
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
title: "Login",
|
title: 'Login',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.authService = new AuthService(this.appMain.appService);
|
this.authService = new AuthService(this.appMain.appService);
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
get emailInput(): InputFieldElement {
|
get emailInput(): InputFieldElement {
|
||||||
for (const i in this.inputs) {
|
for (const i in this.inputs) {
|
||||||
if (this.inputs[i]?.name == "email") {
|
if (this.inputs[i]?.name == 'email') {
|
||||||
return this.inputs[i];
|
return this.inputs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get passwordInput(): InputFieldElement {
|
get passwordInput(): InputFieldElement {
|
||||||
for (const i in this.inputs) {
|
for (const i in this.inputs) {
|
||||||
if (this.inputs[i]?.name == "password") {
|
if (this.inputs[i]?.name == 'password') {
|
||||||
return this.inputs[i];
|
return this.inputs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get values(): Object {
|
get values(): Object {
|
||||||
const formObject: any = {};
|
const formObject: any = {};
|
||||||
this.inputs.forEach((input: InputFieldElement) => {
|
this.inputs.forEach((input: InputFieldElement) => {
|
||||||
const inputType = input.inp;
|
const inputType = input.inp;
|
||||||
formObject[input.name] = (inputType as HTMLInputElement).value;
|
formObject[input.name] = (inputType as HTMLInputElement).value;
|
||||||
});
|
});
|
||||||
return formObject;
|
return formObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit = async (): Promise<void> => {
|
onSubmit = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
if (!this.validate()) {
|
if (!this.validate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const response = await this.appMain.authStore.userLogin(
|
const response = await this.appMain.authStore.userLogin(this.values);
|
||||||
this.values
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response?.token) {
|
if (response?.token) {
|
||||||
this.routerService.goTo("/");
|
this.routerService.goTo('/');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err?.errorCode == 400103) {
|
if (err?.errorCode == 400103) {
|
||||||
this.emailInput.error = err?.message;
|
this.emailInput.setError(err?.message);
|
||||||
this.emailInput.update();
|
this.emailInput.update();
|
||||||
} else if (err?.errorCode == 400104) {
|
} else if (err?.errorCode == 400104) {
|
||||||
this.passwordInput.error = err?.message;
|
this.passwordInput.setError(err?.message);
|
||||||
this.passwordInput.update();
|
this.passwordInput.update();
|
||||||
} else {
|
} else {
|
||||||
this.appForm?.setError("Unable to log in!");
|
this.appForm?.setError('Unable to log in!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
validate(): boolean {
|
validate(): boolean {
|
||||||
let _return = true;
|
let _return = true;
|
||||||
this.inputs.forEach((input: InputFieldElement) => {
|
this.inputs.forEach((input: InputFieldElement) => {
|
||||||
const valid: boolean = input.validate();
|
const valid: boolean = input.validate();
|
||||||
if (!valid) _return = false;
|
if (!valid) _return = false;
|
||||||
});
|
});
|
||||||
return _return;
|
return _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`
|
return html`
|
||||||
<app-form
|
<app-form data-custom="login-page#onSubmit" data-target="login-page.appForm">
|
||||||
data-custom="login-page#onSubmit"
|
<input-field
|
||||||
data-target="login-page.appForm"
|
data-type="email"
|
||||||
>
|
data-name="email"
|
||||||
<input-field
|
data-label="E-mail"
|
||||||
data-type="email"
|
data-targets="login-page.inputs"
|
||||||
data-name="email"
|
data-rules="required|is_email"
|
||||||
data-label="E-mail"
|
></input-field>
|
||||||
data-targets="login-page.inputs"
|
<input-field
|
||||||
data-rules="required|isEmail"
|
data-type="password"
|
||||||
></input-field>
|
data-name="password"
|
||||||
<input-field
|
data-label="Password"
|
||||||
data-type="password"
|
data-targets="login-page.inputs"
|
||||||
data-name="password"
|
data-rules="required"
|
||||||
data-label="Password"
|
>
|
||||||
data-targets="login-page.inputs"
|
</input-field>
|
||||||
data-rules="required"
|
</app-form>
|
||||||
>
|
<div>
|
||||||
</input-field>
|
<app-link data-to="/register" data-title="Create new account"></app-link>
|
||||||
</app-form>
|
</div>
|
||||||
<div>
|
`;
|
||||||
<app-link
|
};
|
||||||
data-to="/register"
|
|
||||||
data-title="Create new account"
|
|
||||||
></app-link>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { LoginPageElement };
|
export type { LoginPageElement };
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { controller } from "@github/catalyst";
|
import { controller } from '@github/catalyst';
|
||||||
import { AuthService } from "services/";
|
import { AuthService } from 'services/';
|
||||||
import { BasePageElement } from "common/";
|
import { BasePageElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class LogoutPageElement extends BasePageElement {
|
class LogoutPageElement extends BasePageElement {
|
||||||
authService: AuthService;
|
authService: AuthService;
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
title: "Logout",
|
title: 'Logout',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.authService = new AuthService(this.appMain.appService);
|
this.authService = new AuthService(this.appMain.appService);
|
||||||
this.appMain?.authStore?.userLogout();
|
this.appMain?.authStore?.userLogout();
|
||||||
this.appMain?.routerService.goTo("/login");
|
this.appMain?.routerService.goTo('/login');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { LogoutPageElement };
|
export type { LogoutPageElement };
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
import { controller } from "@github/catalyst";
|
import { controller } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { BasePageElement } from "common/";
|
import { BasePageElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class NotFoundElement extends BasePageElement {
|
class NotFoundElement extends BasePageElement {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
title: "404 - Not Found",
|
title: '404 - Not Found',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`
|
return html`
|
||||||
<div>404 - Page not found</div>
|
<div>404 - Page not found</div>
|
||||||
<div><app-link data-to="/" data-title="Homepage"></app-link></div>
|
<div><app-link data-to="/" data-title="Homepage"></app-link></div>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { NotFoundElement };
|
export type { NotFoundElement };
|
||||||
|
|||||||
@@ -1,87 +1,100 @@
|
|||||||
import { targets, controller } from "@github/catalyst";
|
import { targets, controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { AuthService } from "services/";
|
import { AuthService } from 'services/';
|
||||||
import { InputFieldElement } from "components/";
|
import { AppFormElement, InputFieldElement } from 'components/';
|
||||||
import { BasePageElement } from "common/";
|
import { BasePageElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class RegisterPageElement extends BasePageElement {
|
class RegisterPageElement extends BasePageElement {
|
||||||
@targets inputs: Array<InputFieldElement>;
|
@targets inputs: Array<InputFieldElement>;
|
||||||
authService: AuthService;
|
@target appForm: AppFormElement;
|
||||||
constructor() {
|
authService: AuthService;
|
||||||
super({
|
constructor() {
|
||||||
title: "Register",
|
super({
|
||||||
});
|
title: 'Register',
|
||||||
}
|
});
|
||||||
elementConnected = (): void => {
|
}
|
||||||
this.authService = new AuthService(this.appMain.appService);
|
elementConnected = (): void => {
|
||||||
this.update();
|
this.authService = new AuthService(this.appMain.appService);
|
||||||
};
|
this.update();
|
||||||
|
};
|
||||||
|
|
||||||
get values(): Object {
|
get values(): Object {
|
||||||
const formObject = {};
|
const formObject = {};
|
||||||
this.inputs.forEach((input: InputFieldElement) => {
|
this.inputs.forEach((input: InputFieldElement) => {
|
||||||
const inputType = input.inp;
|
const inputType = input.inp;
|
||||||
formObject[input.name] = (inputType as HTMLInputElement).value;
|
formObject[input.name] = (inputType as HTMLInputElement).value;
|
||||||
});
|
});
|
||||||
return formObject;
|
return formObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit = async (): Promise<void> => {
|
onSubmit = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
if (!this.validate()) {
|
if (!this.validate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const response = await this.appMain.authStore.userRegister(
|
const response = await this.appMain.authStore.userRegister(this.values);
|
||||||
this.values
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response?.id) {
|
if (response?.id) {
|
||||||
this.appMain.routerService.goTo("/login");
|
this.appMain.routerService.goTo('/login');
|
||||||
}
|
}
|
||||||
} catch (err) {}
|
} catch (err) {
|
||||||
};
|
if (err?.errorCode == 400103) {
|
||||||
|
this.appForm?.getInput('email')?.setError(err?.message);
|
||||||
|
this.appForm?.getInput('email')?.update();
|
||||||
|
} else if (err?.errorCode == 400104) {
|
||||||
|
this.appForm?.getInput('password')?.setError(err?.message);
|
||||||
|
this.appForm?.getInput('password')?.update();
|
||||||
|
} else {
|
||||||
|
this.appForm?.setError('Unable to log in!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
validate(): boolean {
|
validate(): boolean {
|
||||||
let _return = true;
|
let _return = true;
|
||||||
this.inputs.forEach((input: InputFieldElement) => {
|
this.inputs.forEach((input: InputFieldElement) => {
|
||||||
const valid: boolean = input.validate();
|
const valid: boolean = input.validate();
|
||||||
if (!valid) _return = false;
|
if (!valid) _return = false;
|
||||||
});
|
});
|
||||||
return _return;
|
return _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`
|
return html`
|
||||||
<app-form
|
<app-form data-custom="register-page#onSubmit" data-has-cancel="true" data-target="register-page.appForm">
|
||||||
data-custom="register-page#onSubmit"
|
<input-field
|
||||||
data-has-cancel="true"
|
data-type="text"
|
||||||
>
|
data-name="username"
|
||||||
<input-field
|
data-label="Username"
|
||||||
data-type="text"
|
data-targets="register-page.inputs"
|
||||||
data-name="username"
|
data-rules="required"
|
||||||
data-label="Username"
|
></input-field>
|
||||||
data-targets="register-page.inputs"
|
<input-field
|
||||||
data-rules="required"
|
data-type="email"
|
||||||
></input-field>
|
data-name="email"
|
||||||
<input-field
|
data-label="E-mail"
|
||||||
data-type="email"
|
data-targets="register-page.inputs"
|
||||||
data-name="email"
|
data-rules="required|is_email"
|
||||||
data-label="E-mail"
|
></input-field>
|
||||||
data-targets="register-page.inputs"
|
<input-field
|
||||||
data-rules="required|isEmail"
|
data-type="password"
|
||||||
></input-field>
|
data-name="password"
|
||||||
<input-field
|
data-label="Password"
|
||||||
data-type="password"
|
data-targets="register-page.inputs"
|
||||||
data-name="password"
|
data-rules="required"
|
||||||
data-label="Password"
|
>
|
||||||
data-targets="register-page.inputs"
|
</input-field>
|
||||||
data-rules="required"
|
<input-field
|
||||||
>
|
data-type="password"
|
||||||
</input-field>
|
data-name="confirmpassword"
|
||||||
</app-form>
|
data-label="Confirm Password"
|
||||||
`;
|
data-targets="register-page.inputs"
|
||||||
};
|
data-rules="required|is_same[field(password)]"
|
||||||
|
>
|
||||||
|
</app-form>
|
||||||
|
`;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { RegisterPageElement };
|
export type { RegisterPageElement };
|
||||||
|
|||||||
@@ -1,130 +1,119 @@
|
|||||||
import { targets, controller } from "@github/catalyst";
|
import { targets, controller } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { AuthService, TransactionsService, WalletService } from "services/";
|
import { AuthService, TransactionsService, WalletService } from 'services/';
|
||||||
import { InputFieldElement } from "components/";
|
import { InputFieldElement } from 'components/';
|
||||||
import { RouterService } from "core/services";
|
import { RouterService } from 'core/services';
|
||||||
import { BasePageElement } from "common/";
|
import { BasePageElement } from 'common/';
|
||||||
import { AppDropdownElement } from "components/app-dropdown/AppDropdownElement";
|
import { AppDropdownElement } from 'components/app-dropdown/AppDropdownElement';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class TransactionCreateElement extends BasePageElement {
|
class TransactionCreateElement extends BasePageElement {
|
||||||
@targets inputs: Array<InputFieldElement | AppDropdownElement>;
|
@targets inputs: Array<InputFieldElement | AppDropdownElement>;
|
||||||
private transactionService: TransactionsService;
|
private transactionService: TransactionsService;
|
||||||
private walletService: WalletService;
|
private walletService: WalletService;
|
||||||
authService: AuthService;
|
authService: AuthService;
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
title: "New Transaction",
|
title: 'New Transaction',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.walletService = new WalletService(this.appMain?.appService);
|
this.walletService = new WalletService(this.appMain?.appService);
|
||||||
this.transactionService = new TransactionsService(
|
this.transactionService = new TransactionsService(this.appMain?.appService);
|
||||||
this.appMain?.appService
|
this.authService = new AuthService(this.appMain.appService);
|
||||||
);
|
this.update();
|
||||||
this.authService = new AuthService(this.appMain.appService);
|
};
|
||||||
this.update();
|
|
||||||
};
|
|
||||||
|
|
||||||
get nameInput(): InputFieldElement | AppDropdownElement {
|
get nameInput(): InputFieldElement | AppDropdownElement {
|
||||||
for (const i in this.inputs) {
|
for (const i in this.inputs) {
|
||||||
if (this.inputs[i]?.name == "name") {
|
if (this.inputs[i]?.name == 'name') {
|
||||||
return this.inputs[i];
|
return this.inputs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get values(): any {
|
get values(): any {
|
||||||
const formObject: any = {};
|
const formObject: any = {};
|
||||||
this.inputs.forEach((input: InputFieldElement) => {
|
this.inputs.forEach((input: InputFieldElement) => {
|
||||||
const inputType = input.inp;
|
const inputType = input.inp;
|
||||||
formObject[input.name] = (inputType as HTMLInputElement).value;
|
formObject[input.name] = (inputType as HTMLInputElement).value;
|
||||||
});
|
});
|
||||||
return formObject;
|
return formObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
getWallets = async (options): Promise<void> => {
|
getWallets = async (options): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const response = await this.walletService.getAll(options);
|
const response = await this.walletService.getAll(options);
|
||||||
return response;
|
return response;
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
onSubmit = async (values): Promise<void> => {
|
onSubmit = async (values): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
if (!this.validate()) {
|
if (!this.validate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const { description: description, wallet: walletId, amount } = values;
|
||||||
description: description,
|
|
||||||
wallet: walletId,
|
|
||||||
amount,
|
|
||||||
} = values;
|
|
||||||
|
|
||||||
const response = await this.transactionService.post({
|
const response = await this.transactionService.post({
|
||||||
description,
|
description,
|
||||||
walletId,
|
walletId,
|
||||||
amount,
|
amount,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response?.id) {
|
if (response?.id) {
|
||||||
this.appMain.triggerWalletUpdate();
|
this.appMain.triggerWalletUpdate();
|
||||||
this.routerService.goTo("/history", {
|
this.routerService.goTo('/history', {
|
||||||
walletId: response.id,
|
walletId: response.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.errorMessage = "Unable to create transaction!";
|
this.errorMessage = 'Unable to create transaction!';
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
validate(): boolean {
|
validate(): boolean {
|
||||||
let _return = true;
|
let _return = true;
|
||||||
this.inputs.forEach((input: InputFieldElement) => {
|
this.inputs.forEach((input: InputFieldElement) => {
|
||||||
const valid: boolean = input.validate();
|
const valid: boolean = input.validate();
|
||||||
if (!valid) _return = false;
|
if (!valid) _return = false;
|
||||||
});
|
});
|
||||||
return _return;
|
return _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`
|
return html`
|
||||||
<div>Create wallet</div>
|
<div>Create wallet</div>
|
||||||
<app-form
|
<app-form data-custom="transaction-create#onSubmit" data-has-cancel="true">
|
||||||
data-custom="transaction-create#onSubmit"
|
<input-field
|
||||||
data-has-cancel="true"
|
data-type="number"
|
||||||
>
|
data-name="amount"
|
||||||
<input-field
|
data-label="Amount"
|
||||||
data-type="number"
|
data-targets="transaction-create.inputs"
|
||||||
data-name="amount"
|
data-rules="required"
|
||||||
data-label="Amount"
|
></input-field>
|
||||||
data-targets="transaction-create.inputs"
|
<input-field
|
||||||
data-rules="required"
|
data-type="text"
|
||||||
></input-field>
|
data-name="description"
|
||||||
<input-field
|
data-label="Description"
|
||||||
data-type="text"
|
data-targets="transaction-create.inputs"
|
||||||
data-name="description"
|
data-rules="required"
|
||||||
data-label="Description"
|
></input-field>
|
||||||
data-targets="transaction-create.inputs"
|
<app-dropdown
|
||||||
data-rules="required"
|
data-name="wallet"
|
||||||
></input-field>
|
data-label="Wallet"
|
||||||
<app-dropdown
|
data-targets="transaction-create.inputs"
|
||||||
data-name="wallet"
|
data-rules="required"
|
||||||
data-label="Wallet"
|
data-fetch="transaction-create#getWallets"
|
||||||
data-targets="transaction-create.inputs"
|
>
|
||||||
data-rules="required"
|
</app-dropdown>
|
||||||
data-fetch="transaction-create#getWallets"
|
${this.errorMessage ? html`<div>${this.errorMessage}</div>` : html``}
|
||||||
>
|
</app-form>
|
||||||
</app-dropdown>
|
`;
|
||||||
${this.errorMessage
|
};
|
||||||
? html`<div>${this.errorMessage}</div>`
|
|
||||||
: html``}
|
|
||||||
</app-form>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { TransactionCreateElement };
|
export type { TransactionCreateElement };
|
||||||
|
|||||||
@@ -1,92 +1,87 @@
|
|||||||
import { targets, controller } from "@github/catalyst";
|
import { targets, controller } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { AuthService, WalletService } from "services/";
|
import { AuthService, WalletService } from 'services/';
|
||||||
import { InputFieldElement } from "components/";
|
import { InputFieldElement } from 'components/';
|
||||||
import { RouterService } from "core/services";
|
import { RouterService } from 'core/services';
|
||||||
import { BasePageElement } from "common/";
|
import { BasePageElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class WalletCreateElement extends BasePageElement {
|
class WalletCreateElement extends BasePageElement {
|
||||||
@targets inputs: Array<InputFieldElement>;
|
@targets inputs: Array<InputFieldElement>;
|
||||||
private walletService: WalletService;
|
private walletService: WalletService;
|
||||||
authService: AuthService;
|
authService: AuthService;
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
title: "New Wallet",
|
title: 'New Wallet',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.walletService = new WalletService(this.appMain?.appService);
|
this.walletService = new WalletService(this.appMain?.appService);
|
||||||
this.authService = new AuthService(this.appMain.appService);
|
this.authService = new AuthService(this.appMain.appService);
|
||||||
this.update();
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
get nameInput(): InputFieldElement {
|
get nameInput(): InputFieldElement {
|
||||||
for (const i in this.inputs) {
|
for (const i in this.inputs) {
|
||||||
if (this.inputs[i]?.name == "name") {
|
if (this.inputs[i]?.name == 'name') {
|
||||||
return this.inputs[i];
|
return this.inputs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get values(): Object {
|
get values(): Object {
|
||||||
const formObject: any = {};
|
const formObject: any = {};
|
||||||
this.inputs.forEach((input: InputFieldElement) => {
|
this.inputs.forEach((input: InputFieldElement) => {
|
||||||
const inputType = input.inp;
|
const inputType = input.inp;
|
||||||
formObject[input.name] = (inputType as HTMLInputElement).value;
|
formObject[input.name] = (inputType as HTMLInputElement).value;
|
||||||
});
|
});
|
||||||
return formObject;
|
return formObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit = async (): Promise<void> => {
|
onSubmit = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
if (!this.validate()) {
|
if (!this.validate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const response = await this.walletService.post(this.values);
|
const response = await this.walletService.post(this.values);
|
||||||
|
|
||||||
if (response?.id) {
|
if (response?.id) {
|
||||||
this.appMain.triggerWalletUpdate();
|
this.appMain.triggerWalletUpdate();
|
||||||
this.routerService.goTo("/wallet/:walletId", {
|
this.routerService.goTo('/wallet/:walletId', {
|
||||||
walletId: response.id,
|
walletId: response.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.errorMessage = "Unable to create wallet!";
|
this.errorMessage = 'Unable to create wallet!';
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
validate(): boolean {
|
validate(): boolean {
|
||||||
let _return = true;
|
let _return = true;
|
||||||
this.inputs.forEach((input: InputFieldElement) => {
|
this.inputs.forEach((input: InputFieldElement) => {
|
||||||
const valid: boolean = input.validate();
|
const valid: boolean = input.validate();
|
||||||
if (!valid) _return = false;
|
if (!valid) _return = false;
|
||||||
});
|
});
|
||||||
return _return;
|
return _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`
|
return html`
|
||||||
<div>Create wallet</div>
|
<div>Create wallet</div>
|
||||||
<app-form
|
<app-form data-custom="wallet-create#onSubmit" data-has-cancel="true">
|
||||||
data-custom="wallet-create#onSubmit"
|
<input-field
|
||||||
data-has-cancel="true"
|
data-type="text"
|
||||||
>
|
data-name="name"
|
||||||
<input-field
|
data-label="Name"
|
||||||
data-type="text"
|
data-targets="wallet-create.inputs"
|
||||||
data-name="name"
|
data-rules="required"
|
||||||
data-label="Name"
|
></input-field>
|
||||||
data-targets="wallet-create.inputs"
|
${this.errorMessage ? html`<div>${this.errorMessage}</div>` : html``}
|
||||||
data-rules="required"
|
</app-form>
|
||||||
></input-field>
|
`;
|
||||||
${this.errorMessage
|
};
|
||||||
? html`<div>${this.errorMessage}</div>`
|
|
||||||
: html``}
|
|
||||||
</app-form>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { WalletCreateElement };
|
export type { WalletCreateElement };
|
||||||
|
|||||||
@@ -1,50 +1,48 @@
|
|||||||
import { targets, controller, target } from "@github/catalyst";
|
import { targets, controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { AuthService, WalletService } from "services/";
|
import { AuthService, WalletService } from 'services/';
|
||||||
import { AppPaginationElement, InputFieldElement } from "components/";
|
import { AppPaginationElement, InputFieldElement } from 'components/';
|
||||||
import { BasePageElement } from "common/";
|
import { BasePageElement } from 'common/';
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class WalletListElement extends BasePageElement {
|
class WalletListElement extends BasePageElement {
|
||||||
@targets inputs: Array<InputFieldElement>;
|
@targets inputs: Array<InputFieldElement>;
|
||||||
private walletService: WalletService;
|
private walletService: WalletService;
|
||||||
@target pagination: AppPaginationElement;
|
@target pagination: AppPaginationElement;
|
||||||
authService: AuthService;
|
authService: AuthService;
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
title: "Wallet List",
|
title: 'Wallet List',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.walletService = new WalletService(this.appMain?.appService);
|
this.walletService = new WalletService(this.appMain?.appService);
|
||||||
this.authService = new AuthService(this.appMain.appService);
|
this.authService = new AuthService(this.appMain.appService);
|
||||||
this.update();
|
this.update();
|
||||||
this.pagination?.setCustomRenderItem(this.renderItem);
|
this.pagination?.setCustomRenderItem(this.renderItem);
|
||||||
this.pagination?.setFetchFunc?.(this.getWallets, true)!;
|
this.pagination?.setFetchFunc?.(this.getWallets, true)!;
|
||||||
};
|
};
|
||||||
|
|
||||||
getWallets = async (options): Promise<any> => {
|
getWallets = async (options): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
const response = await this.walletService.getAll(options);
|
const response = await this.walletService.getAll(options);
|
||||||
return response;
|
return response;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = (item): TemplateResult => html`<tr>
|
renderItem = (item): TemplateResult => html`<tr>
|
||||||
<td><app-link data-to="/wallet/${item.id}">${item.name}</app-link></td>
|
<td><app-link data-to="/wallet/${item.id}">${item.name}</app-link></td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
return html`
|
return html`
|
||||||
<div>Wallets</div>
|
<div>Wallets</div>
|
||||||
<app-pagination
|
<app-pagination data-target="wallet-list.pagination"></app-pagination>
|
||||||
data-target="wallet-list.pagination"
|
`;
|
||||||
></app-pagination>
|
};
|
||||||
`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { WalletListElement };
|
export type { WalletListElement };
|
||||||
|
|||||||
@@ -1,105 +1,95 @@
|
|||||||
import { controller, target } from "@github/catalyst";
|
import { controller, target } from '@github/catalyst';
|
||||||
import { html, TemplateResult } from "@github/jtml";
|
import { html, TemplateResult } from 'core/utils';
|
||||||
import { TransactionsService, WalletService } from "services/";
|
import { TransactionsService, WalletService } from 'services/';
|
||||||
import {
|
import { AppMainElement, AppPaginationElement, WalletHeaderElement } from 'components/';
|
||||||
AppMainElement,
|
import { BasePageElement } from 'common/';
|
||||||
AppPaginationElement,
|
|
||||||
WalletHeaderElement,
|
|
||||||
} from "components/";
|
|
||||||
import { BasePageElement } from "common/";
|
|
||||||
|
|
||||||
@controller
|
@controller
|
||||||
class WalletPageElement extends BasePageElement {
|
class WalletPageElement extends BasePageElement {
|
||||||
private transactionsService: TransactionsService;
|
private transactionsService: TransactionsService;
|
||||||
private walletService: WalletService;
|
private walletService: WalletService;
|
||||||
@target pagination: AppPaginationElement;
|
@target pagination: AppPaginationElement;
|
||||||
@target walletHeader: WalletHeaderElement;
|
@target walletHeader: WalletHeaderElement;
|
||||||
walletId: string;
|
walletId: string;
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
title: "Wallet",
|
title: 'Wallet',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
elementConnected = (): void => {
|
elementConnected = (): void => {
|
||||||
this.walletService = new WalletService(this.appMain?.appService);
|
this.walletService = new WalletService(this.appMain?.appService);
|
||||||
this.transactionsService = new TransactionsService(
|
this.transactionsService = new TransactionsService(this.appMain?.appService);
|
||||||
this.appMain?.appService
|
if (this?.routerService?.routerState?.data) {
|
||||||
);
|
const { walletId } = this?.routerService?.routerState?.data;
|
||||||
if (this?.routerService?.routerState?.data) {
|
if (walletId) {
|
||||||
const { walletId } = this?.routerService?.routerState?.data;
|
this.walletId = walletId;
|
||||||
if (walletId) {
|
}
|
||||||
this.walletId = walletId;
|
}
|
||||||
}
|
this.update();
|
||||||
}
|
this.pagination?.setFetchFunc?.(this.getTransactions, true)!;
|
||||||
this.update();
|
this.appMain.addEventListener('tokenchange', this.update);
|
||||||
this.pagination?.setFetchFunc?.(this.getTransactions, true)!;
|
};
|
||||||
this.appMain.addEventListener("tokenchange", this.update);
|
|
||||||
};
|
|
||||||
|
|
||||||
elementDisconnected = (appMain: AppMainElement): void => {
|
elementDisconnected = (appMain: AppMainElement): void => {
|
||||||
appMain?.removeEventListener("tokenchange", this.update);
|
appMain?.removeEventListener('tokenchange', this.update);
|
||||||
};
|
};
|
||||||
|
|
||||||
getTransactions = async (options): Promise<any> => {
|
getTransactions = async (options): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
if (this?.routerService?.routerState?.data) {
|
if (this?.routerService?.routerState?.data) {
|
||||||
const { walletId } = this?.routerService?.routerState?.data;
|
const { walletId } = this?.routerService?.routerState?.data;
|
||||||
if (walletId) {
|
if (walletId) {
|
||||||
options["walletId"] = walletId;
|
options['walletId'] = walletId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const response = await this.transactionsService.getAll(options);
|
const response = await this.transactionsService.getAll(options);
|
||||||
return response;
|
return response;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getBalance = async (): Promise<void> => {
|
getBalance = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const response = await this.walletService.getBalance({
|
const response = await this.walletService.getBalance({
|
||||||
walletId: this.walletId,
|
walletId: this.walletId,
|
||||||
});
|
});
|
||||||
this.setBalance(response);
|
this.setBalance(response);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setBalance = (header) => {
|
setBalance = (header) => {
|
||||||
if (!this.walletHeader) return;
|
if (!this.walletHeader) return;
|
||||||
this.walletHeader.currency = header.currency;
|
this.walletHeader.currency = header.currency;
|
||||||
this.walletHeader.currentBalance = header.currentBalance || "0";
|
this.walletHeader.currentBalance = header.currentBalance || '0';
|
||||||
this.walletHeader.lastMonth = header.lastMonth || "0";
|
this.walletHeader.lastMonth = header.lastMonth || '0';
|
||||||
this.walletHeader.nextMonth = header.nextMonth || "0";
|
this.walletHeader.nextMonth = header.nextMonth || '0';
|
||||||
};
|
};
|
||||||
|
|
||||||
render = (): TemplateResult => {
|
render = (): TemplateResult => {
|
||||||
const renderHeader = () => html`<wallet-header
|
const renderHeader = () => html`<wallet-header
|
||||||
data-target="wallet-page.walletHeader"
|
data-target="wallet-page.walletHeader"
|
||||||
data-current-balance="0"
|
data-current-balance="0"
|
||||||
data-last-month="0"
|
data-last-month="0"
|
||||||
data-next-month="0"
|
data-next-month="0"
|
||||||
data-currency="0"
|
data-currency="0"
|
||||||
data-custom="wallet-page#getBalance"
|
data-custom="wallet-page#getBalance"
|
||||||
></wallet-header>`;
|
></wallet-header>`;
|
||||||
|
|
||||||
const renderWallet = () => {
|
const renderWallet = () => {
|
||||||
if (this.routerService?.routerState?.data?.walletId) {
|
if (this.routerService?.routerState?.data?.walletId) {
|
||||||
return html`<span
|
return html`<span>${this.routerService?.routerState?.data?.walletId}</span>`;
|
||||||
>${this.routerService?.routerState?.data?.walletId}</span
|
}
|
||||||
>`;
|
return html``;
|
||||||
}
|
};
|
||||||
return html``;
|
return html`<div>
|
||||||
};
|
${renderHeader()} ${renderWallet()}
|
||||||
return html`<div>
|
<app-pagination data-target="wallet-page.pagination"></app-pagination>
|
||||||
${renderHeader()} ${renderWallet()}
|
</div>`;
|
||||||
<app-pagination
|
};
|
||||||
data-target="wallet-page.pagination"
|
|
||||||
></app-pagination>
|
|
||||||
</div>`;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { WalletPageElement };
|
export type { WalletPageElement };
|
||||||
|
|||||||
@@ -1,22 +1,18 @@
|
|||||||
import { AppService, BaseService } from "core/services";
|
import { AppService, BaseService } from 'core/services';
|
||||||
|
|
||||||
class PingService extends BaseService {
|
class PingService extends BaseService {
|
||||||
constructor(appService: AppService) {
|
constructor(appService: AppService) {
|
||||||
super("/auth", appService);
|
super('/auth', appService);
|
||||||
}
|
}
|
||||||
login = (data?: Object, headers?: HeadersInit) => {
|
login = (data?: Object, headers?: HeadersInit) => {
|
||||||
return this.appService.post(this.endpoint + "/login", data, headers);
|
return this.appService.post(this.endpoint + '/login', data, headers);
|
||||||
};
|
};
|
||||||
register = (data?: Object, headers?: HeadersInit) => {
|
register = (data?: Object, headers?: HeadersInit) => {
|
||||||
return this.appService.post(this.endpoint + "/register", data, headers);
|
return this.appService.post(this.endpoint + '/register', data, headers);
|
||||||
};
|
};
|
||||||
checkToken = (params?: Object, headers?: HeadersInit) => {
|
checkToken = (params?: Object, headers?: HeadersInit) => {
|
||||||
return this.appService.get(
|
return this.appService.get(this.endpoint + '/check-token', params, headers);
|
||||||
this.endpoint + "/check-token",
|
};
|
||||||
params,
|
|
||||||
headers
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PingService;
|
export default PingService;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { AppService, BaseService } from "core/services";
|
import { AppService, BaseService } from 'core/services';
|
||||||
|
|
||||||
class PingService extends BaseService {
|
class PingService extends BaseService {
|
||||||
constructor(appService: AppService) {
|
constructor(appService: AppService) {
|
||||||
super("/wallet", appService);
|
super('/wallet', appService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PingService;
|
export default PingService;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { AppService, BaseService } from "core/services";
|
import { AppService, BaseService } from 'core/services';
|
||||||
|
|
||||||
class TransactionsService extends BaseService {
|
class TransactionsService extends BaseService {
|
||||||
constructor(appService: AppService) {
|
constructor(appService: AppService) {
|
||||||
super("/transaction", appService);
|
super('/transaction', appService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TransactionsService;
|
export default TransactionsService;
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
import { AppService, BaseService } from "core/services";
|
import { AppService, BaseService } from 'core/services';
|
||||||
|
|
||||||
class WalletService extends BaseService {
|
class WalletService extends BaseService {
|
||||||
constructor(appService: AppService) {
|
constructor(appService: AppService) {
|
||||||
super("/wallet", appService);
|
super('/wallet', appService);
|
||||||
}
|
}
|
||||||
|
|
||||||
getBalance = (params?: Object, headers?: HeadersInit) => {
|
getBalance = (params?: Object, headers?: HeadersInit) => {
|
||||||
return this.appService.get(
|
return this.appService.get(this.endpoint + '/wallet-header', params, headers);
|
||||||
this.endpoint + "/wallet-header",
|
};
|
||||||
params,
|
|
||||||
headers
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WalletService;
|
export default WalletService;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export { default as PingService } from "./PingService";
|
export { default as PingService } from './PingService';
|
||||||
export { default as AuthService } from "./AuthService";
|
export { default as AuthService } from './AuthService';
|
||||||
export { default as WalletService } from "./WalletService";
|
export { default as WalletService } from './WalletService';
|
||||||
export { default as TransactionsService } from "./TransactionsService";
|
export { default as TransactionsService } from './TransactionsService';
|
||||||
|
|||||||
@@ -1,107 +1,109 @@
|
|||||||
.dropdown-custom {
|
.dropdown-custom {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
div.dropdown-custom-top {
|
position: relative;
|
||||||
position: relative;
|
div.dropdown-custom-top {
|
||||||
background-color: #ffffff;
|
position: relative;
|
||||||
border: 1px solid transparent;
|
background-color: $white;
|
||||||
color: #09090a;
|
color: $black;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
border: 1px solid #767676;
|
border: 1px solid $white;
|
||||||
border-radius: 3px;
|
border-radius: 5px;
|
||||||
&::after {
|
&::after {
|
||||||
content: "";
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
border-left: 8px solid transparent;
|
border-left: 8px solid transparent;
|
||||||
border-right: 8px solid transparent;
|
border-right: 8px solid transparent;
|
||||||
border-top: 8px solid #2e2e2e;
|
border-top: 8px solid #2e2e2e;
|
||||||
}
|
}
|
||||||
&.--open {
|
&.--open {
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0 !important;
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0 !important;
|
||||||
border-bottom: transparent;
|
border-bottom: transparent;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
&::after {
|
&::after {
|
||||||
content: "";
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
border-left: 8px solid transparent;
|
border-left: 8px solid transparent;
|
||||||
border-right: 8px solid transparent;
|
border-right: 8px solid transparent;
|
||||||
border-bottom: 8px solid #2e2e2e;
|
border-bottom: 8px solid #2e2e2e;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
span.dropdown-custom-fieldname {
|
span.dropdown-custom-fieldname {
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-khtml-user-select: none;
|
-khtml-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div.dropdown-custom-open {
|
div.dropdown-custom-open {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: calc(100% - 2 * 1px);
|
||||||
border-top: none;
|
border-top: none;
|
||||||
margin-top: 0 !important;
|
margin-top: 0 !important;
|
||||||
background-color: #fbfafa;
|
background-color: #fbfafa;
|
||||||
border-bottom-right-radius: 0.2em;
|
border-bottom-right-radius: 0.2em;
|
||||||
border-bottom-left-radius: 0.2em;
|
border-bottom-left-radius: 0.2em;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
input.dropdown-custom-search {
|
input.dropdown-custom-search {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: calc(100% - 2 * 2px);
|
box-sizing: border-box;
|
||||||
margin: 2px;
|
padding: 0;
|
||||||
background-color: #fbfbfb;
|
width: calc(100% - 2 * 2px);
|
||||||
border: 1px solid #9c9c9c;
|
margin: 2px;
|
||||||
border-radius: 0.3em;
|
background-color: $white;
|
||||||
&:hover {
|
border: 1px solid $white;
|
||||||
border: 1px solid #b6b6b6;
|
border-radius: 0.3em;
|
||||||
}
|
&:hover {
|
||||||
}
|
border: 1px solid $white;
|
||||||
ul.dropdown-custom-list {
|
}
|
||||||
padding: 1px 0;
|
}
|
||||||
max-height: 100px;
|
ul.dropdown-custom-list {
|
||||||
overflow-y: scroll;
|
padding: 1px 0;
|
||||||
&::-webkit-scrollbar {
|
max-height: 100px;
|
||||||
display: none;
|
overflow-y: scroll;
|
||||||
}
|
&::-webkit-scrollbar {
|
||||||
-ms-overflow-style: none;
|
display: none;
|
||||||
scrollbar-width: none;
|
}
|
||||||
li.dropdown-custom-listitem {
|
-ms-overflow-style: none;
|
||||||
margin: 2px;
|
scrollbar-width: none;
|
||||||
padding: 1px 0;
|
li.dropdown-custom-listitem {
|
||||||
list-style-type: none;
|
margin: 2px;
|
||||||
color: #0e0d0d;
|
padding: 1px 0;
|
||||||
-webkit-touch-callout: none;
|
list-style-type: none;
|
||||||
-webkit-user-select: none;
|
color: #0e0d0d;
|
||||||
-khtml-user-select: none;
|
-webkit-touch-callout: none;
|
||||||
-moz-user-select: none;
|
-webkit-user-select: none;
|
||||||
-ms-user-select: none;
|
-khtml-user-select: none;
|
||||||
user-select: none;
|
-moz-user-select: none;
|
||||||
cursor: pointer;
|
-ms-user-select: none;
|
||||||
&:hover {
|
user-select: none;
|
||||||
background-color: #c6d8ff;
|
cursor: pointer;
|
||||||
}
|
&:hover {
|
||||||
&.--selected {
|
background-color: #c6d8ff;
|
||||||
background-color: #d8e4ff;
|
}
|
||||||
}
|
&.--selected {
|
||||||
}
|
background-color: #d8e4ff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/styles/input-field/index.scss
Normal file
1
src/styles/input-field/index.scss
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@import './input-field.scss';
|
||||||
8
src/styles/input-field/input-field.scss
Normal file
8
src/styles/input-field/input-field.scss
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
input-field {
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
@import "./core/index.scss";
|
@import './core/index.scss';
|
||||||
@import "./menu-item/index.scss";
|
@import './menu-item/index.scss';
|
||||||
@import "./sidebar/index.scss";
|
@import './sidebar/index.scss';
|
||||||
@import "./modal/index.scss";
|
@import './modal/index.scss';
|
||||||
@import "./table/index.scss";
|
@import './table/index.scss';
|
||||||
@import "./app-loader/index.scss";
|
@import './app-loader/index.scss';
|
||||||
@import "./circle-loader/index.scss";
|
@import './circle-loader/index.scss';
|
||||||
@import "./page/index.scss";
|
@import './page/index.scss';
|
||||||
@import "./app-form/index.scss";
|
@import './app-form/index.scss';
|
||||||
@import "./layout/index.scss";
|
@import './layout/index.scss';
|
||||||
@import "./app-dropdown/index.scss";
|
@import './app-dropdown/index.scss';
|
||||||
|
@import './input-field/index.scss';
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
"es2016"
|
"es2016"
|
||||||
],
|
],
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"jsxFactory": "h",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ const path = require('path');
|
|||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
const { DefinePlugin } = require('webpack');
|
const { DefinePlugin } = require('webpack');
|
||||||
|
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||||
|
|
||||||
const alias = {
|
const alias = {
|
||||||
common: path.resolve(__dirname, '/common'),
|
common: path.resolve(__dirname, '/common'),
|
||||||
@@ -52,7 +53,7 @@ module.exports = (env, args) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
minimize: true,
|
minimize: true,
|
||||||
minimizer: [new TerserPlugin()],
|
minimizer: [new TerserPlugin(), new UglifyJsPlugin()],
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: path.join(__dirname, 'public'),
|
path: path.join(__dirname, 'public'),
|
||||||
@@ -62,7 +63,7 @@ module.exports = (env, args) => {
|
|||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.(js|ts)?$/,
|
test: /\.(js|ts)x?$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: {
|
use: {
|
||||||
loader: 'babel-loader'
|
loader: 'babel-loader'
|
||||||
@@ -106,7 +107,7 @@ module.exports = (env, args) => {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.js', '.ts'],
|
extensions: ['.js', '.ts', '.jsx', '.tsx'],
|
||||||
alias: alias
|
alias: alias
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
|
|||||||
Reference in New Issue
Block a user