added simple notifications (#3184)

Co-authored-by: Ivan Hrynevytskyi <ivan.hrynevytskyi@IHRYNEVYTSKYIL.local>
This commit is contained in:
Ivan Hrynevytskyi (FE-underwriting) 2022-07-07 23:12:21 +03:00 committed by GitHub
parent 92bc89b10c
commit c67cb6ebdc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 176 additions and 1437 deletions

File diff suppressed because it is too large Load diff

View file

@ -26,18 +26,19 @@
},
"dependencies": {
"@antv/x6": "^1.32.2",
"@ctrl/tinycolor": "^3.4.1",
"@stencil/core": "^2.13.0",
"@stencil/state-tunnel": "^1.0.1",
"@stencil/store": "^1.5.0",
"@ctrl/tinycolor": "^3.4.1",
"axios": "^0.27.2",
"axios-middleware": "^0.3.1",
"el-transition": "^0.0.7",
"lodash": "^4.17.21",
"moment": "^2.29.3",
"notyf": "^3.10.0",
"reflect-metadata": "^0.1.13",
"typedi": "^0.10.0",
"lodash": "^4.17.21",
"uuid": "^8.3.2",
"el-transition": "^0.0.7",
"moment": "^2.29.3"
"uuid": "^8.3.2"
},
"peerDependencies": {
"monaco-editor": ""

View file

@ -166,6 +166,8 @@ export namespace Components {
interface ElsaMultiTextInput {
"inputContext": ActivityInputContext;
}
interface ElsaNotificationsManager {
}
interface ElsaPager {
"page": number;
"pageSize": number;
@ -440,6 +442,12 @@ declare global {
prototype: HTMLElsaMultiTextInputElement;
new (): HTMLElsaMultiTextInputElement;
};
interface HTMLElsaNotificationsManagerElement extends Components.ElsaNotificationsManager, HTMLStencilElement {
}
var HTMLElsaNotificationsManagerElement: {
prototype: HTMLElsaNotificationsManagerElement;
new (): HTMLElsaNotificationsManagerElement;
};
interface HTMLElsaPagerElement extends Components.ElsaPager, HTMLStencilElement {
}
var HTMLElsaPagerElement: {
@ -617,6 +625,7 @@ declare global {
"elsa-monaco-editor": HTMLElsaMonacoEditorElement;
"elsa-multi-line-input": HTMLElsaMultiLineInputElement;
"elsa-multi-text-input": HTMLElsaMultiTextInputElement;
"elsa-notifications-manager": HTMLElsaNotificationsManagerElement;
"elsa-pager": HTMLElsaPagerElement;
"elsa-panel": HTMLElsaPanelElement;
"elsa-radio-list-input": HTMLElsaRadioListInputElement;
@ -782,6 +791,8 @@ declare namespace LocalJSX {
interface ElsaMultiTextInput {
"inputContext"?: ActivityInputContext;
}
interface ElsaNotificationsManager {
}
interface ElsaPager {
"onPaginated"?: (event: CustomEvent<PagerData>) => void;
"page"?: number;
@ -911,6 +922,7 @@ declare namespace LocalJSX {
"elsa-monaco-editor": ElsaMonacoEditor;
"elsa-multi-line-input": ElsaMultiLineInput;
"elsa-multi-text-input": ElsaMultiTextInput;
"elsa-notifications-manager": ElsaNotificationsManager;
"elsa-pager": ElsaPager;
"elsa-panel": ElsaPanel;
"elsa-radio-list-input": ElsaRadioListInput;
@ -968,6 +980,7 @@ declare module "@stencil/core" {
"elsa-monaco-editor": LocalJSX.ElsaMonacoEditor & JSXBase.HTMLAttributes<HTMLElsaMonacoEditorElement>;
"elsa-multi-line-input": LocalJSX.ElsaMultiLineInput & JSXBase.HTMLAttributes<HTMLElsaMultiLineInputElement>;
"elsa-multi-text-input": LocalJSX.ElsaMultiTextInput & JSXBase.HTMLAttributes<HTMLElsaMultiTextInputElement>;
"elsa-notifications-manager": LocalJSX.ElsaNotificationsManager & JSXBase.HTMLAttributes<HTMLElsaNotificationsManagerElement>;
"elsa-pager": LocalJSX.ElsaPager & JSXBase.HTMLAttributes<HTMLElsaPagerElement>;
"elsa-panel": LocalJSX.ElsaPanel & JSXBase.HTMLAttributes<HTMLElsaPanelElement>;
"elsa-radio-list-input": LocalJSX.ElsaRadioListInput & JSXBase.HTMLAttributes<HTMLElsaRadioListInputElement>;

View file

@ -1,7 +1,7 @@
import {Component, Element, h, Listen, Prop, Watch} from '@stencil/core';
import 'reflect-metadata';
import {Container} from 'typedi';
import {ElsaApiClientProvider, ElsaClient, ServerSettings} from '../../../services';
import {ElsaApiClientProvider, ElsaClient, EventBus, ServerSettings} from '../../../services';
import {ActivityDescriptor, VersionOptions, WorkflowDefinition, WorkflowDefinitionSummary, WorkflowInstanceSummary} from '../../../models';
import {PublishClickedArgs} from "../../toolbar/workflow-publish-button/workflow-publish-button";
import {MonacoEditorSettings} from "../../../services/monaco-editor-settings";
@ -11,17 +11,20 @@ import {WorkflowDefinitionManager} from "../../../services/workflow-definition-m
import {WorkflowDefinitionUpdatedArgs} from "../../designer/workflow-definition-editor/models";
import {Flowchart} from "../../activities/flowchart/models";
import descriptorsStore from '../../../data/descriptors-store';
import { NotificationEventTypes } from '../../../modules/notifications/event-types';
@Component({
tag: 'elsa-studio'
})
export class Studio {
private readonly eventBus: EventBus;
private readonly workflowDefinitionManager: WorkflowDefinitionManager;
private activityDescriptors: Array<ActivityDescriptor>;
private elsaClient: ElsaClient;
private workflowManagerElement?: HTMLElsaWorkflowManagerElement;
constructor() {
this.eventBus = Container.get(EventBus);
this.workflowDefinitionManager = Container.get(WorkflowDefinitionManager);
}
@ -85,12 +88,13 @@ export class Studio {
private async handlePublishClicked(e: CustomEvent<PublishClickedArgs>) {
const workflowManagerElement = this.workflowManagerElement;
if (!workflowManagerElement)
return;
if (!workflowManagerElement) return;
e.detail.begin();
const workflowDefinition = await workflowManagerElement.getWorkflowDefinition();
this.eventBus.emit(NotificationEventTypes.Add, this, { id: workflowDefinition.definitionId, message: `Starting publishing ${workflowDefinition.name}` });
await this.saveWorkflowDefinition(workflowDefinition, true);
this.eventBus.emit(NotificationEventTypes.Update, this, { id: workflowDefinition.definitionId, message: `${workflowDefinition.name} publish finished` });
e.detail.complete();
}
@ -98,11 +102,12 @@ export class Studio {
private async handleUnPublishClicked(e: CustomEvent) {
const workflowManagerElement = this.workflowManagerElement;
if (!workflowManagerElement)
return;
if (!workflowManagerElement) return;
const workflow = await workflowManagerElement.getWorkflowDefinition();
this.eventBus.emit(NotificationEventTypes.Add, this, { id: workflow.definitionId, message: `Starting unpublishing ${workflow.name}` });
await this.retractWorkflowDefinition(workflow);
this.eventBus.emit(NotificationEventTypes.Update, this, { id: workflow.definitionId, message: `${workflow.name} unpublish finished` });
}
@Listen('newClicked')

View file

@ -1,36 +1,57 @@
import {Component, h} from '@stencil/core';
import { Component, h } from '@stencil/core';
import Container from 'typedi';
import { NotificationEventTypes } from '../../../modules/notifications/event-types';
import { EventBus } from '../../../services';
@Component({
tag: 'elsa-workflow-toolbar'
tag: 'elsa-workflow-toolbar',
})
export class WorkflowToolbar {
private readonly eventBus: EventBus;
constructor() {
this.eventBus = Container.get(EventBus);
}
onNotificationClick = e => {
e.stopPropagation();
this.eventBus.emit(NotificationEventTypes.Toggle, this);
};
render() {
return <nav class="bg-gray-800">
<div class="mx-auto px-2 sm:px-6 lg:px-6">
<div class="relative flex items-center justify-end h-16">
return (
<nav class="bg-gray-800">
<div class="mx-auto px-2 sm:px-6 lg:px-6">
<div class="relative flex items-center justify-end h-16">
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0 z-20">
{/* Notifications*/}
<button
onClick={e => this.onNotificationClick(e)}
type="button"
class="bg-gray-800 p-1 rounded-full text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white mr-4"
>
<span class="sr-only">View notifications</span>
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
/>
</svg>
</button>
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0 z-20">
{/* Publish */}
<div class="flex-shrink-0">
<elsa-workflow-publish-button />
</div>
{/* Notifications*/}
<button type="button" class="bg-gray-800 p-1 rounded-full text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white mr-4">
<span class="sr-only">View notifications</span>
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/>
</svg>
</button>
{/* Publish */}
<div class="flex-shrink-0">
<elsa-workflow-publish-button/>
{/* Menu */}
<elsa-workflow-toolbar-menu />
</div>
{/* Menu */}
<elsa-workflow-toolbar-menu/>
</div>
</div>
</div>
</nav>;
</nav>
);
}
}

View file

@ -17,6 +17,7 @@
<div class="absolute inset-0" style="top: 64px;">
<elsa-workflow-manager></elsa-workflow-manager>
<elsa-labels-widget></elsa-labels-widget>
<elsa-notifications-manager></elsa-notifications-manager>
</div>
<!-- <elsa-workflow-editor></elsa-workflow-editor>-->
</elsa-studio>

View file

@ -0,0 +1,5 @@
export const NotificationEventTypes = {
Add: 'notification-added',
Update: 'notification-updated',
Toggle: 'notification-toggle',
};

View file

@ -0,0 +1,4 @@
export interface Notification {
message: string;
id: string;
}

View file

@ -0,0 +1,65 @@
import { Component, h, State } from '@stencil/core';
import { Container } from 'typedi';
import notificationStore from './notification-store';
import { EventBus } from '../../services';
import { Notyf, NotyfNotification } from 'notyf';
import { Notification } from './models';
import { NotificationEventTypes } from './event-types';
@Component({
tag: 'elsa-notifications-manager',
shadow: false,
styleUrl: 'notification.scss',
})
export class LabelsManager {
private readonly eventBus: EventBus;
private readonly notyf: Notyf;
@State() private isOpened = false;
private notyfs: Map<string, NotyfNotification> = new Map();
constructor() {
this.notyf = new Notyf({ types: [{ type: 'regular', className: 'notif p-4 rounded bg-white shadow-lg' }] });
this.eventBus = Container.get(EventBus);
this.eventBus.on(NotificationEventTypes.Add, this.handleAddNotification);
this.eventBus.on(NotificationEventTypes.Update, this.handleUpdateNotification);
this.eventBus.on(NotificationEventTypes.Toggle, this.handleToggle);
}
handleAddNotification = (e: Notification) => {
if (!this.isOpened) {
this.notyfs.set(e.id, this.notyf.success({ message: e.message, type: 'regular', duration: 2000, position: { x: 'right', y: 'top' } }));
}
notificationStore.notifications = [e, ...notificationStore.notifications];
};
handleUpdateNotification = (e: Notification) => {
if (!this.isOpened) {
this.notyf.dismiss(this.notyfs.get(e.id));
this.notyfs.set(e.id, this.notyf.success({ message: e.message, type: 'regular', duration: 2000, position: { x: 'right', y: 'top' } }));
}
notificationStore.notifications = [e, ...notificationStore.notifications];
};
handleToggle = () => {
if (!this.isOpened) {
this.notyf.dismissAll();
this.notyfs.clear();
}
this.isOpened = !this.isOpened;
};
render() {
const { notifications } = notificationStore;
return (
<div class={`notifications-container absolute bg-white z-10 right-0 w-80 ${this.isOpened ? 'block' : 'hidden'} `}>
{notifications.length === 0 && <div class="m-4 p-4 rounded border border-black bg-white shadow-lg">There is no notifications yet</div>}
{notifications.map(notif => (
<div class="m-4 p-4 rounded border border-black bg-white shadow-lg">{notif.message}</div>
))}
</div>
);
}
}

View file

@ -0,0 +1,7 @@
import { createStore } from '@stencil/store';
const { state, onChange } = createStore({
notifications: [],
});
export default state;

View file

@ -0,0 +1,11 @@
@import url('../../../node_modules/notyf/notyf.min.css');
.notif {
.notyf__message {
@apply text-black
}
}
.notifications-container {
height: calc(100vh - 64px);
}