Fixing Bridge
This commit is contained in:
parent
cb5fb7c808
commit
20d8d313f0
@ -63,11 +63,11 @@ const UNSPECIFIC_TO_METHODS: {
|
||||
subscribe: keyof ICommunicationInterface;
|
||||
};
|
||||
} = {
|
||||
aurevoir: {
|
||||
Aurevoir: {
|
||||
emit: "emitAurevoir",
|
||||
subscribe: "onAurevoir"
|
||||
},
|
||||
bonjour: {
|
||||
Bonjour: {
|
||||
emit: "emitBonjour",
|
||||
subscribe: "onBonjour"
|
||||
},
|
||||
@ -102,7 +102,11 @@ const LAYER_METHOD_TO_EVENT: {
|
||||
} = {
|
||||
// Specific:
|
||||
onEvent: "event/",
|
||||
emitEvent: "event/"
|
||||
emitEvent: "event/",
|
||||
onRpcRequest: "",
|
||||
emitRpcRequest: "",
|
||||
onRpcResponse: "",
|
||||
emitRpcResponse: ""
|
||||
};
|
||||
|
||||
for (const eventName in UNSPECIFIC_TO_METHODS) {
|
||||
@ -117,12 +121,12 @@ const MIRROR_METHOD_TO_EVENT: {
|
||||
[P in keyof ICommunicationInterface]: ValidEventTypesOfMirror;
|
||||
} = copy(LAYER_METHOD_TO_EVENT) as any;
|
||||
|
||||
MIRROR_METHOD_TO_EVENT.onEvent = "event";
|
||||
MIRROR_METHOD_TO_EVENT.emitEvent = "event";
|
||||
MIRROR_METHOD_TO_EVENT.onRpcRequest = "rpcRequest";
|
||||
MIRROR_METHOD_TO_EVENT.emitRpcRequest = "rpcRequest";
|
||||
MIRROR_METHOD_TO_EVENT.onRpcResponse = "rpcResponse";
|
||||
MIRROR_METHOD_TO_EVENT.emitRpcResponse = "rpcResponse";
|
||||
MIRROR_METHOD_TO_EVENT.onEvent = "Event";
|
||||
MIRROR_METHOD_TO_EVENT.emitEvent = "Event";
|
||||
MIRROR_METHOD_TO_EVENT.onRpcRequest = "RpcRequest";
|
||||
MIRROR_METHOD_TO_EVENT.emitRpcRequest = "RpcRequest";
|
||||
MIRROR_METHOD_TO_EVENT.onRpcResponse = "RpcResponse";
|
||||
MIRROR_METHOD_TO_EVENT.emitRpcResponse = "RpcResponse";
|
||||
|
||||
const MIRROR_EVENT_TO_EMIT: {
|
||||
[P in keyof ValidEventTypesOfMirror]: keyof ICommunicationInterface;
|
||||
@ -143,28 +147,6 @@ const OFF_METHODS: Array<keyof ICommunicationInterface> = [
|
||||
"offRpcResponse"
|
||||
];
|
||||
|
||||
const MAPPING_METHODS: {
|
||||
[P in keyof ICommunicationInterface]: keyof ICommunicationInterface;
|
||||
} = {
|
||||
onAurevoir: "emitAurevoir",
|
||||
onBonjour: "emitBonjour",
|
||||
onEvent: "emitEvent",
|
||||
onNewInstanceGeneratorsAvailable: "emitNewInstanceGeneratorsAvailable",
|
||||
onNewInstancesAvailable: "emitNewInstancesAvailable",
|
||||
onNewObservablesAvailable: "emitNewObersvablesAvailable",
|
||||
onNewServicesAvailable: "emitNewServicesAvailable",
|
||||
onRpcRequest: "emitRpcRequest",
|
||||
onRpcResponse: "emitRpcResponse",
|
||||
onTaskCancelation: "emitTaskCancelation",
|
||||
onStatusUpdate: "emitStatusUpdate"
|
||||
};
|
||||
|
||||
const METHODS_WITH_NAME: Array<keyof ICommunicationInterface> = [
|
||||
"onRpcResponse",
|
||||
"onRpcRequest",
|
||||
"onEvent"
|
||||
];
|
||||
|
||||
//@ts-ignore Ignore the Interface. Its implemented manually
|
||||
export class Bridge implements ICommunicationBridge {
|
||||
public connected: INopeObservable<boolean>;
|
||||
@ -243,6 +225,8 @@ export class Bridge implements ICommunicationBridge {
|
||||
for (const method of EMITTING_METHODS) {
|
||||
const eventName = LAYER_METHOD_TO_EVENT[method];
|
||||
this[method] = async (data) => {
|
||||
if (method !== "emitStatusUpdate")
|
||||
console.log("emitting", method, eventName, data);
|
||||
_this._emit(eventName, null, data);
|
||||
};
|
||||
}
|
||||
@ -291,7 +275,7 @@ export class Bridge implements ICommunicationBridge {
|
||||
): void {
|
||||
const _this = this;
|
||||
|
||||
if (METHODS_WITH_NAME.includes(method)) {
|
||||
if (ON_SPECIFIC_METHODS.includes(method)) {
|
||||
layer[method as any](event, (data) => {
|
||||
// Define the Method to Forward data.
|
||||
_this._internalEmitter.emit(event, data);
|
||||
@ -424,7 +408,7 @@ export class Bridge implements ICommunicationBridge {
|
||||
toExclude: ICommunicationInterface | ICommunicationMirror = null,
|
||||
dataToSend: any
|
||||
): void {
|
||||
if (this._logger.enabledFor(Logger.DEBUG) && eventName !== "StatusUpdate") {
|
||||
if (this._logger.enabledFor(Logger.WARN) && eventName !== "StatusUpdate") {
|
||||
this._logger.debug("emitting", eventName, dataToSend);
|
||||
}
|
||||
// Emit the Event on the internal Layer.
|
||||
@ -584,14 +568,7 @@ export class Bridge implements ICommunicationBridge {
|
||||
UNSPECIFIC_TO_METHODS[eventName].emit
|
||||
);
|
||||
}
|
||||
|
||||
// Now Forward the Data.
|
||||
console.log(
|
||||
"Fowarding",
|
||||
eventName,
|
||||
"->",
|
||||
MIRROR_EVENT_TO_EMIT[eventName]
|
||||
);
|
||||
_this._emit(eventName, mirror, data);
|
||||
});
|
||||
} else {
|
||||
|
@ -9,21 +9,22 @@
|
||||
import * as io from "socket.io";
|
||||
import { getNopeLogger } from "../../logger/getLogger";
|
||||
import { LoggerLevel } from "../../logger/nopeLogger";
|
||||
import { ValidEventTypesOfMirror } from "../../types/nope/nopeCommunication.interface";
|
||||
import { EventMirror } from "./eventMirror";
|
||||
|
||||
const EVENTS_TO_FORWARD: Set<string> = new Set([
|
||||
const EVENTS_TO_FORWARD: Set<ValidEventTypesOfMirror> = new Set([
|
||||
// Default emitters
|
||||
"aurevoir",
|
||||
"bonjour",
|
||||
"Aurevoir",
|
||||
"Bonjour",
|
||||
"NewInstanceGeneratorsAvailable",
|
||||
"NewInstancesAvailable",
|
||||
"NewObersvablesAvailable",
|
||||
"NewServicesAvailable",
|
||||
"StatusUpdate",
|
||||
"TaskCancelation",
|
||||
"event",
|
||||
"rpcRequest",
|
||||
"rpcResponse"
|
||||
"Event",
|
||||
"RpcRequest",
|
||||
"RpcResponse"
|
||||
]);
|
||||
|
||||
/**
|
||||
@ -69,6 +70,7 @@ export class IoSocketMirrorServer extends EventMirror {
|
||||
// are forwarding the data.
|
||||
for (const event of EVENTS_TO_FORWARD) {
|
||||
client.on(event, (data) => {
|
||||
if (event !== "StatusUpdate") console.log("Forwarding", event, data);
|
||||
_this._forward(client, event, data);
|
||||
});
|
||||
}
|
||||
|
@ -141,8 +141,11 @@ export class NopeBaseModule implements INopeModule {
|
||||
this.identifier = null;
|
||||
this._registeredFunctions = new Map();
|
||||
this._registeredProperties = new Map();
|
||||
this.uiLinks = [];
|
||||
}
|
||||
|
||||
public uiLinks: { name: string; description: string; link: string }[];
|
||||
|
||||
/**
|
||||
* Helper Function to register an Observable (a Property.)
|
||||
*
|
||||
@ -401,7 +404,8 @@ export class NopeBaseModule implements INopeModule {
|
||||
identifier: this.identifier,
|
||||
properties: this.properties,
|
||||
type: this.type,
|
||||
version: this.version
|
||||
version: this.version,
|
||||
uiLinks: this.uiLinks
|
||||
};
|
||||
|
||||
return ret;
|
||||
|
@ -338,17 +338,17 @@ export interface ICommunicationBridge extends ICommunicationInterface {
|
||||
|
||||
export type ValidEventTypesOfMirror =
|
||||
// Default emitters
|
||||
| "aurevoir"
|
||||
| "bonjour"
|
||||
| "Aurevoir"
|
||||
| "Bonjour"
|
||||
| "NewInstanceGeneratorsAvailable"
|
||||
| "NewInstancesAvailable"
|
||||
| "NewObersvablesAvailable"
|
||||
| "NewServicesAvailable"
|
||||
| "StatusUpdate"
|
||||
| "TaskCancelation"
|
||||
| "event"
|
||||
| "rpcRequest"
|
||||
| "rpcResponse";
|
||||
| "Event"
|
||||
| "RpcRequest"
|
||||
| "RpcResponse";
|
||||
|
||||
export const ValidEventTypesOfMirror = [
|
||||
// Default emitters
|
||||
|
@ -81,6 +81,8 @@ export interface INopeModuleDescription {
|
||||
readonly functions: { [index: string]: IFunctionOptions };
|
||||
|
||||
readonly properties: { [index: string]: IPropertyOptions };
|
||||
|
||||
readonly uiLinks: Array<{ name: string; description: string; link: string }>;
|
||||
}
|
||||
|
||||
export interface INopeModule extends INopeModuleDescription {
|
||||
|
@ -192,7 +192,7 @@ export class WaMOBaseModule
|
||||
}) => Promise<string | false>,
|
||||
resetPlc = true,
|
||||
autoStart = true,
|
||||
demo = false,
|
||||
demo = false
|
||||
): Promise<void> {
|
||||
// Define the Author.
|
||||
this.author = {
|
||||
@ -308,7 +308,11 @@ export class WaMOBaseModule
|
||||
|
||||
// Only if there exists a Carrier, proceed.
|
||||
if (value) {
|
||||
|
||||
if (demo) {
|
||||
// Demo-Mode
|
||||
// Wait 10 Seconds at least spend additional 0-5000 Seconds
|
||||
await sleep(Math.random() * 5000 + 10 * 1000);
|
||||
} else {
|
||||
let tasks: MESTask[] = _this._xetics.availableTasks.getContent();
|
||||
|
||||
// Only if no tasks are available, try to update the
|
||||
@ -328,30 +332,28 @@ export class WaMOBaseModule
|
||||
|
||||
// Try to assign the new Task for the Product
|
||||
if (
|
||||
!demo &&
|
||||
productToStartTaskWith &&
|
||||
_this._xetics.selectTaskForProduct(productToStartTaskWith)
|
||||
(await _this._xetics.selectTaskForProduct(
|
||||
productToStartTaskWith
|
||||
))
|
||||
) {
|
||||
// We are not running in the demo-mode and we have
|
||||
// a task to start, which we are able to select.
|
||||
await _this.performCurrentTask();
|
||||
} else if (demo) {
|
||||
// Demo-Mode
|
||||
// Wait 10 Seconds at least spend additional 0-5000 Seconds
|
||||
await sleep(Math.random() * 5000 + 10*1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Now we are done or we dont have a task.
|
||||
// we release the carrier and wait for a new
|
||||
// product.
|
||||
await _this.releaseCarrier();
|
||||
|
||||
} else {
|
||||
// Updating the State of the System. The System
|
||||
// Waits for a new Carrier
|
||||
const baseInformation = copy(_this.baseInformation.getContent());
|
||||
baseInformation.logical.currentState =
|
||||
"waiting";
|
||||
const baseInformation = copy(
|
||||
_this.baseInformation.getContent()
|
||||
);
|
||||
baseInformation.logical.currentState = "waiting";
|
||||
_this.baseInformation.setContent(baseInformation);
|
||||
}
|
||||
} catch (e) {
|
||||
@ -735,7 +737,6 @@ export class WaMOBaseModule
|
||||
observers = [
|
||||
// Subscribe to the connectorReplica of the Process Module.
|
||||
_this._processModule.connector.subscribe((value) => {
|
||||
|
||||
// If we have waited to finish a Task, we are able
|
||||
// to proceed with the task.
|
||||
if (value.active == false && first == false) {
|
||||
@ -750,7 +751,9 @@ export class WaMOBaseModule
|
||||
first = false;
|
||||
}
|
||||
}),
|
||||
_this._plc.dynamicInstanceProperties["input.GVL_IOS.bInputTasterQuittieren"].subscribe((value) => {
|
||||
_this._plc.dynamicInstanceProperties[
|
||||
"input.GVL_IOS.bInputTasterQuittieren"
|
||||
].subscribe((value) => {
|
||||
console.log("bInputTasterQuittieren =>", value);
|
||||
if (value) {
|
||||
// Unsubscribe the Observer
|
||||
|
@ -93,14 +93,16 @@ export class WaMOCarrierMapper
|
||||
// Define the File Name. It is based on the identifier.
|
||||
this._file = join(_path, this.identifier + "_file.json");
|
||||
|
||||
// Now Test if the File exists:
|
||||
if (!(await exists(this._file))) {
|
||||
|
||||
this._logger.warn("No configuration File defined. Creating a new one under:",this._file);
|
||||
|
||||
this.carriers.setContent([]);
|
||||
this.mapping.setContent({});
|
||||
|
||||
// Now Test if the File exists:
|
||||
if (!(await exists(this._file))) {
|
||||
this._logger.warn(
|
||||
"No configuration File defined. Creating a new one under:",
|
||||
this._file
|
||||
);
|
||||
|
||||
// Create an Empty File.
|
||||
await this.storeConfig();
|
||||
}
|
||||
@ -133,10 +135,13 @@ export class WaMOCarrierMapper
|
||||
paramsHasNoCallback: true
|
||||
})
|
||||
public async storeConfig() {
|
||||
await createFile(this._file, JSON.stringify({
|
||||
await createFile(
|
||||
this._file,
|
||||
JSON.stringify({
|
||||
carriers: this.carriers.getContent(),
|
||||
mapping: this.mapping.getContent()
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,13 +241,13 @@ export class XeticsInterfaceClient
|
||||
})
|
||||
async startCurrentTask() {
|
||||
if (this.currentTask.getContent()) {
|
||||
|
||||
// We have to consinder, whether the job is allready active or not
|
||||
if (this.taskActive.getContent()) {
|
||||
console.log("already active");
|
||||
return true;
|
||||
}
|
||||
|
||||
return startTask(
|
||||
return await startTask(
|
||||
this._station,
|
||||
this.currentTask.getContent().id,
|
||||
this._user,
|
||||
@ -277,7 +277,9 @@ export class XeticsInterfaceClient
|
||||
// Call the Finish-Task Operation. Use the parameters of the current Task.
|
||||
// Returns the sucess of the Operation.
|
||||
if (this._logger) {
|
||||
this._logger.info("Finishing Task " + this.currentTask.getContent().id.toString());
|
||||
this._logger.info(
|
||||
"Finishing Task " + this.currentTask.getContent().id.toString()
|
||||
);
|
||||
}
|
||||
|
||||
const finished = await finishTask(
|
||||
@ -328,6 +330,9 @@ export class XeticsInterfaceClient
|
||||
this._uri,
|
||||
this._token
|
||||
);
|
||||
|
||||
console.log(this.identifier, "got active tasks", activeTasks);
|
||||
|
||||
if (activeTasks.length > 0) {
|
||||
// If there are multiple Tasks.
|
||||
this.currentTask.setContent(activeTasks[0]);
|
||||
|
@ -10,6 +10,8 @@ import React from "react";
|
||||
import { Card, ListGroup, Table } from "react-bootstrap";
|
||||
import { ENopeDispatcherStatus } from "../../../lib/types/nope/nopeDispatcher.interface";
|
||||
import { INopeModuleDescription } from "../../../lib/types/nope/nopeModule.interface";
|
||||
import { CustomIFrame } from "../../ui/iframe";
|
||||
import { StaticPopup } from "../../ui/popup/component";
|
||||
import { StatusBadgeComponent } from "../generic/StatusBadge";
|
||||
|
||||
type ValidColors = "danger" | "warning" | "info" | "success";
|
||||
@ -31,6 +33,11 @@ export class InstanceDetailsComponent extends React.Component<
|
||||
},
|
||||
{
|
||||
renderDetails: boolean;
|
||||
customUiProps: {
|
||||
name: string;
|
||||
description: string;
|
||||
link: string;
|
||||
} | null;
|
||||
variant: ValidColors;
|
||||
}
|
||||
> {
|
||||
@ -63,7 +70,8 @@ export class InstanceDetailsComponent extends React.Component<
|
||||
|
||||
this.state = {
|
||||
renderDetails: this.props.renderDetails,
|
||||
variant: dict[this.props.description.status]
|
||||
variant: dict[this.props.description.status],
|
||||
customUiProps: null
|
||||
};
|
||||
}
|
||||
|
||||
@ -76,13 +84,17 @@ export class InstanceDetailsComponent extends React.Component<
|
||||
});
|
||||
}
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return this.state.customUiProps === null;
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
const renderMethods =
|
||||
Object.getOwnPropertyNames(this.props.description.functions).length > 0;
|
||||
const renderProperties =
|
||||
Object.getOwnPropertyNames(this.props.description.properties).length > 0;
|
||||
|
||||
return (
|
||||
const elements = [
|
||||
<Card border={this.state.variant}>
|
||||
<Card.Body>
|
||||
<Card.Title>
|
||||
@ -112,8 +124,17 @@ export class InstanceDetailsComponent extends React.Component<
|
||||
<td>UI</td>
|
||||
<td>
|
||||
<ListGroup>
|
||||
{this.props.description.uiLinks?.map((link, idx) => (
|
||||
<ListGroup.Item key={idx}>{link}</ListGroup.Item>
|
||||
{this.props.description.uiLinks?.map((data, idx) => (
|
||||
<ListGroup.Item
|
||||
key={idx}
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
customUiProps: data
|
||||
});
|
||||
}}
|
||||
>
|
||||
{data.name}
|
||||
</ListGroup.Item>
|
||||
))}
|
||||
</ListGroup>
|
||||
</td>
|
||||
@ -174,6 +195,47 @@ export class InstanceDetailsComponent extends React.Component<
|
||||
</small>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
];
|
||||
|
||||
if (this.state.customUiProps) {
|
||||
elements.push(
|
||||
<StaticPopup
|
||||
content={{
|
||||
component: () => {
|
||||
return (
|
||||
<CustomIFrame
|
||||
link={this.state.customUiProps.link}
|
||||
height={500}
|
||||
></CustomIFrame>
|
||||
);
|
||||
},
|
||||
props: {
|
||||
link: this.state.customUiProps.link
|
||||
}
|
||||
}}
|
||||
onHide={() => {
|
||||
this.setState({ customUiProps: null });
|
||||
}}
|
||||
header={
|
||||
"Visualization for " +
|
||||
this.props.description.identifier +
|
||||
" - " +
|
||||
this.state.customUiProps.name
|
||||
}
|
||||
closeButton={true}
|
||||
withoutBorder={false}
|
||||
footer={
|
||||
this.props.description.author.forename +
|
||||
" " +
|
||||
this.props.description.author.surename +
|
||||
" is responsible for the content. Report Bugs to " +
|
||||
this.props.description.author.mail
|
||||
}
|
||||
size="xl"
|
||||
></StaticPopup>
|
||||
);
|
||||
}
|
||||
|
||||
return React.createElement("div", {}, ...elements);
|
||||
}
|
||||
}
|
||||
|
80
resources/ui/iframe.tsx
Normal file
80
resources/ui/iframe.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @author Martin Karkowski
|
||||
* @email m.karkowski@zema.de
|
||||
* @create date 2021-04-20 18:51:42
|
||||
* @modify date 2021-04-20 18:55:10
|
||||
* @desc [description]
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
/**
|
||||
* A Component, used to Render the Staus of a Host.
|
||||
*
|
||||
*/
|
||||
export class CustomIFrame extends React.Component<
|
||||
{
|
||||
height?: number;
|
||||
width?: number;
|
||||
link: string;
|
||||
altText?: string;
|
||||
},
|
||||
{
|
||||
height: number;
|
||||
width: number;
|
||||
}
|
||||
> {
|
||||
ref: React.RefObject<HTMLDivElement>;
|
||||
|
||||
/**
|
||||
* Create the Status to Render.
|
||||
* @param props
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.ref = React.createRef();
|
||||
this.state = {
|
||||
height: 200,
|
||||
width: 500
|
||||
};
|
||||
}
|
||||
|
||||
protected _handleResize: () => void;
|
||||
|
||||
componentDidMount() {
|
||||
const _this = this;
|
||||
this._handleResize = () => {
|
||||
setTimeout(() => {
|
||||
const size = {
|
||||
width:
|
||||
_this.props.width |
|
||||
(_this.ref.current.parentElement.clientWidth - 40),
|
||||
height:
|
||||
_this.props.height |
|
||||
(_this.ref.current.parentElement.clientHeight - 40)
|
||||
};
|
||||
console.log(size, _this.ref);
|
||||
_this.setState(size);
|
||||
}, 200);
|
||||
};
|
||||
|
||||
this._handleResize();
|
||||
window.addEventListener("resize", this._handleResize);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("resize", this._handleResize);
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<div ref={this.ref}>
|
||||
<iframe
|
||||
src={this.props.link}
|
||||
height={this.state.height}
|
||||
width={this.state.width}
|
||||
></iframe>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
import { IDynamicRenderSettings } from '../../dynamic/interfaces/IDynamicRenderSettings';
|
||||
import { IDynamicRenderSettings } from "../../dynamic/interfaces/IDynamicRenderSettings";
|
||||
|
||||
export interface IModalSettings {
|
||||
content: IDynamicRenderSettings;
|
||||
backdrop?: 'staic' | boolean
|
||||
centered?: boolean
|
||||
backdrop?: "static" | boolean;
|
||||
centered?: boolean;
|
||||
header?: string;
|
||||
size?: 'sm' | 'lg' | 'xl',
|
||||
closeButton?: boolean,
|
||||
closeLabel?: boolean,
|
||||
size?: "sm" | "lg" | "xl";
|
||||
closeButton?: boolean;
|
||||
closeLabel?: boolean;
|
||||
onHide?: (closeCallback: () => void) => void;
|
||||
renderInBody?: boolean,
|
||||
renderInBody?: boolean;
|
||||
}
|
72
resources/ui/popup/component.tsx
Normal file
72
resources/ui/popup/component.tsx
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @author Martin Karkowski
|
||||
* @email m.karkowski@zema.de
|
||||
* @create date 2021-04-20 19:04:57
|
||||
* @modify date 2021-04-20 19:04:57
|
||||
* @desc [description]
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { Modal } from "react-bootstrap";
|
||||
import DynamicRenderer from "../dynamic/dynamicRenderer";
|
||||
import { IModalSettings } from "./interfaces/IModalSettings";
|
||||
|
||||
export class StaticPopup extends React.Component<
|
||||
{ withoutBorder?: boolean } & IModalSettings
|
||||
> {
|
||||
/**
|
||||
* Create the Status to Render.
|
||||
* @param props
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { modalVisible: true };
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<Modal
|
||||
show={true}
|
||||
backdrop={
|
||||
typeof this.props.backdrop !== undefined
|
||||
? this.props.backdrop
|
||||
: "static"
|
||||
}
|
||||
keyboard={false}
|
||||
size={this.props.size}
|
||||
centered={this.props.centered || false}
|
||||
onHide={this.props.onHide}
|
||||
scrollable
|
||||
>
|
||||
{this.props.header ? (
|
||||
<Modal.Header closeButton={this.props.closeButton}>
|
||||
<Modal.Title>{this.props.header}</Modal.Title>
|
||||
</Modal.Header>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
|
||||
{this.props.withoutBorder ? (
|
||||
<DynamicRenderer
|
||||
component={this.props.content.component}
|
||||
props={this.props.content.props}
|
||||
/>
|
||||
) : (
|
||||
<Modal.Body style={{ border: 0 }}>
|
||||
{/* Render the dynamic Component */}
|
||||
<DynamicRenderer
|
||||
component={this.props.content.component}
|
||||
props={this.props.content.props}
|
||||
/>
|
||||
</Modal.Body>
|
||||
)}
|
||||
|
||||
{this.props.footer ? (
|
||||
<Modal.Footer>{this.props.footer}</Modal.Footer>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
26
resources/ui/popup/interfaces/IModalSettings.ts
Normal file
26
resources/ui/popup/interfaces/IModalSettings.ts
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @author Martin Karkowski
|
||||
* @email m.karkowski@zema.de
|
||||
* @create date 2021-04-20 19:06:22
|
||||
* @modify date 2021-04-20 19:06:28
|
||||
* @desc [description]
|
||||
*/
|
||||
|
||||
import { IDynamicRenderSettings } from "../../dynamic/interfaces/IDynamicRenderSettings";
|
||||
|
||||
export interface IModalSettings {
|
||||
content: IDynamicRenderSettings;
|
||||
backdrop?: "static" | boolean;
|
||||
centered?: boolean;
|
||||
header?: string;
|
||||
size?: "sm" | "lg" | "xl";
|
||||
closeButton?: boolean;
|
||||
closeLabel?: boolean;
|
||||
onHide?: (closeCallback: () => void) => void;
|
||||
renderInBody?: boolean;
|
||||
footer?:
|
||||
| string
|
||||
| React.Component
|
||||
| React.FunctionComponent
|
||||
| ((...args) => JSX.Element);
|
||||
}
|
Loading…
Reference in New Issue
Block a user