implemented toasts

This commit is contained in:
Fran Jurmanović
2021-06-12 21:21:03 +02:00
parent ecedbb8b57
commit 64b54b3568
17 changed files with 7186 additions and 11 deletions

View File

@@ -46,6 +46,11 @@ class AppDropdownElement extends BaseComponentElement {
this.validator = new Validator(this, this.appForm, this.rules);
this.randId = `${name}${randomId()}`;
this.update();
this.appMain.addEventListener('click', this.outsideClick);
this.elementDisconnectCallbacks.push((appMain) => {
console.log('oslo');
appMain.removeEventListener('click', this.outsideClick);
});
const options = {
rpp: this.rpp,
@@ -54,6 +59,13 @@ class AppDropdownElement extends BaseComponentElement {
this.getItems(options);
};
elementDisconnected = (): void => {};
outsideClick = (e) => {
console.log(e.target);
this.closeDropdown(e);
};
attributeChangedCallback(): void {
this.update();
}
@@ -135,10 +147,16 @@ class AppDropdownElement extends BaseComponentElement {
this.isOpen = isOpen;
};
openDropdown = () => {
openDropdown = (e?) => {
if (e?.target?.closest('app-dropdown > .dropdown-custom')?.randId == this.randId) return;
this.setOpen(true);
};
closeDropdown = (e?) => {
if (e?.target?.closest('app-dropdown')?.randId == this.randId) return;
this.setOpen(false);
};
stopPropagation = (e) => {
e.stopPropagation();
};
@@ -179,9 +197,9 @@ class AppDropdownElement extends BaseComponentElement {
return html`
<div>
<label app-action="click:app-dropdown#openDropdown">
<label>
${label ? html`<div>${label}</div>` : html``}
<div class="dropdown-custom" app-action="click:app-dropdown#stopPropagation">
<div class="dropdown-custom">
<div class="dropdown-custom-top${isOpen ? ' --open' : ''}" app-action="click:app-dropdown#toggleDropdown">
<span class="dropdown-custom-fieldname">${selectedItem ? selectedItem[displaykey] : 'Select'}</span>
</div>

View File

@@ -4,6 +4,7 @@ import { AuthStore } from 'core/store';
import { AppModalElement, AppRootElement } from 'components/';
import { closest } from 'core/utils';
import { AppLoaderElement } from 'components/app-loader/AppLoaderElement';
import { ToastPortalElement } from 'components/toast-portal/ToastPortalElement';
@controller
class AppMainElement extends HTMLElement {
@@ -11,9 +12,11 @@ class AppMainElement extends HTMLElement {
public authStore: AuthStore;
private httpClient: HttpClient;
public appService: AppService;
public shadow: any;
@target appModal: AppModalElement;
@target mainRoot: AppRootElement;
@target appLoader: AppLoaderElement;
@target toastPortal;
@closest appMain: AppMainElement;
public domEvents: any = {
routechanged: new Event('routechanged'),
@@ -148,7 +151,7 @@ class AppMainElement extends HTMLElement {
const _divEl = document.createElement('div');
_modalElement.setAttribute('data-target', 'app-modal.modalElement');
_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);
return _divEl;
};
@@ -168,12 +171,36 @@ class AppMainElement extends HTMLElement {
return _mainRoot;
};
preventClosing = (e: Event) => {
e.stopPropagation();
private createToastPortal = () => {
const _toastPortal = document.createElement('toast-portal');
_toastPortal.setAttribute('data-target', 'app-main.toastPortal');
this.appendChild(_toastPortal);
return _toastPortal;
};
closeModal = () => {
if (this.appModal) this.removeChild(this.appModal);
removeToastPortal = () => {
if (this.toastPortal) this.removeChild(this.toastPortal);
};
pushToast = (type, message) => {
const toastPortal: ToastPortalElement = this.toastPortal
? this.toastPortal
: this.appendChild(this.createToastPortal());
toastPortal?.pushToast(type, message);
};
closeModal = (e?) => {
const selector = "[data-target='app-modal.modalContent']";
if (this.appModal) {
if (e?.target) {
if (e?.target?.closest(selector)) return;
if (e?.target?.closest('app-main')) {
this.removeChild(this.appModal);
}
} else {
this.removeChild(this.appModal);
}
}
this.appMain.removeEventListener('routechanged', this.closeModal);
};

View File

@@ -75,6 +75,7 @@ class AppMenuElement extends BaseComponentElement {
this.appMain.closeModal();
} else {
this.appMain.createModal('wallet-create');
this.appMain.pushToast(null, 'Da');
}
};

View File

@@ -4,6 +4,7 @@ import { BaseComponentElement } from 'common/';
@controller
class AppModalElement extends BaseComponentElement {
@target modalElement: HTMLElement;
@target modalContent: HTMLElement;
constructor() {
super();
}

View File

@@ -1,4 +1,5 @@
import { controller } from '@github/catalyst';
import { AppMainElement } from 'components/app-main/AppMainElement';
import style from 'styles/main.scss';
(function () {
@@ -14,6 +15,7 @@ import style from 'styles/main.scss';
connectedCallback() {
const _root = _shadow.get(this);
const _appMain = document.createElement('app-main');
(_appMain as AppMainElement).shadow = _root;
const _style = document.createElement('style');
_style.innerHTML = style;

View File

@@ -11,6 +11,7 @@ export * from './app-loader/AppLoaderElement';
export * from './circle-loader/CircleLoaderElement';
export * from './app-form/AppFormElement';
export * from './wallet-header/WalletHeaderElement';
export * from './toast-portal/ToastPortalElement';
// LAST
export * from './app-main/AppMainElement';

View File

@@ -0,0 +1,57 @@
import { controller, targets } from '@github/catalyst';
import { delay, html, until } from 'core/utils';
import { BaseComponentElement } from 'common/';
@controller
class ToastPortalElement extends BaseComponentElement {
@targets toastElement: HTMLElement;
toasts: Array<Toast> = [];
constructor() {
super();
}
elementConnected = (): void => {
this.update();
};
pushToast = (type: string, message: string): void => {
this.toasts = [{ type, message }, ...this.toasts];
const interval = setInterval(() => {
this.popToast();
clearInterval(interval);
}, 5000);
this.update();
};
popToast = () => {
this.toasts?.pop();
if (this.toasts?.length < 1) {
this.appMain?.removeToastPortal();
}
this.update();
};
render = () => {
const renderToast = (note: string, type: string) => {
const message = () => html` <div class="toast ${type ? `--${type}` : '--default'}">${note}</div> `;
return html`${message()}`;
};
const renderToasts = (toasts: Array<Toast>) => {
if (toasts) {
return html`<div class="toast-list">
${toasts.map(({ type, message }, i) => (i < 3 ? renderToast(message, type) : html``))}
</div>`;
}
return html``;
};
return html`<div class="toast-portal">${renderToasts(this.toasts)}</div>`;
};
}
type Toast = {
type: string;
message: string;
};
export type { ToastPortalElement };