WIP: Visual Console Refactor
Former-commit-id: f2f8c724920358a790ff99779c4b6eba7963c141
This commit is contained in:
parent
a80372fda8
commit
367d1f2b7e
|
@ -1,12 +1,16 @@
|
||||||
{
|
{
|
||||||
"env": {
|
"env": {
|
||||||
"browser": true
|
"browser": true,
|
||||||
|
"node": true
|
||||||
},
|
},
|
||||||
"parser": "@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
"plugins": ["@typescript-eslint", "prettier"],
|
"plugins": ["@typescript-eslint", "prettier"],
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:prettier/recommended",
|
||||||
"plugin:prettier/recommended"
|
"plugin:@typescript-eslint/recommended"
|
||||||
]
|
],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/indent": "off"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
/build
|
/build
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
|
# editor
|
||||||
|
.vscode
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env.local
|
.env.local
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
export interface Listener<T> {
|
||||||
|
(event: T): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Disposable {
|
||||||
|
dispose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** passes through events as they happen. You will not get events from before you start listening */
|
||||||
|
export default class TypedEvent<T> {
|
||||||
|
private listeners: Listener<T>[] = [];
|
||||||
|
private listenersOncer: Listener<T>[] = [];
|
||||||
|
|
||||||
|
on = (listener: Listener<T>): Disposable => {
|
||||||
|
this.listeners.push(listener);
|
||||||
|
return {
|
||||||
|
dispose: () => this.off(listener)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
once = (listener: Listener<T>): void => {
|
||||||
|
this.listenersOncer.push(listener);
|
||||||
|
};
|
||||||
|
|
||||||
|
off = (listener: Listener<T>): void => {
|
||||||
|
const callbackIndex = this.listeners.indexOf(listener);
|
||||||
|
if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
emit = (event: T): void => {
|
||||||
|
/** Update any general listeners */
|
||||||
|
this.listeners.forEach(listener => listener(event));
|
||||||
|
|
||||||
|
/** Clear the `once` queue */
|
||||||
|
this.listenersOncer.forEach(listener => listener(event));
|
||||||
|
this.listenersOncer = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
pipe = (te: TypedEvent<T>): Disposable => {
|
||||||
|
return this.on(e => te.emit(e));
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
class VisualConsole {}
|
||||||
|
|
||||||
|
export default VisualConsole;
|
|
@ -1,40 +1,244 @@
|
||||||
// interface VisualConsoleElement<VCItemProps> extends EventEmitter {
|
import { Position, Size, UnknownObject } from "./types";
|
||||||
// private itemProps: VCItemProps extends VCGenericItemProps:
|
import {
|
||||||
// private containerRef: HTMLElement;
|
sizePropsDecoder,
|
||||||
// private itemBoxRef: HTMLElement;
|
positionPropsDecoder,
|
||||||
// protected elementRef: HTMLElement;
|
parseIntOr,
|
||||||
|
parseBoolean
|
||||||
|
} from "./lib";
|
||||||
|
import TypedEvent, { Listener, Disposable } from "./TypedEvent";
|
||||||
|
|
||||||
// new (container: HTMLElement, props: VCItemProps): VisualConsoleElement;
|
// Base item properties. This interface should be extended by the item implementations.
|
||||||
|
export interface VisualConsoleItemProps extends Position, Size {
|
||||||
|
readonly id: number;
|
||||||
|
readonly type: number;
|
||||||
|
label: string | null;
|
||||||
|
isLinkEnabled: boolean;
|
||||||
|
isOnTop: boolean;
|
||||||
|
parentId: number | null;
|
||||||
|
aclGroupId: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
// get props (): VCItemProps;
|
export type ItemClickEvent<ItemProps extends VisualConsoleItemProps> = {
|
||||||
// set props (newProps: VCItemProps): void;
|
data: ItemProps;
|
||||||
|
};
|
||||||
|
|
||||||
// protected shouldBeUpdated (newProps: VCItemProps): boolean;
|
/**
|
||||||
// abstract createDomElement (): HTMLElement;
|
* Build a valid typed object from a raw object.
|
||||||
// render (lastProps: VCItemProps): void;
|
* This will allow us to ensure the type safety.
|
||||||
// remove (): void;
|
*
|
||||||
// move (x: number, y: number): void;
|
* @param data Raw object.
|
||||||
// resize (width: number, height: number): void;
|
* @return An object representing the size.
|
||||||
// }
|
* @throws Will throw a TypeError if some property
|
||||||
|
* is missing from the raw object or have an invalid type.
|
||||||
class EventEmitter {}
|
*/
|
||||||
type VisualConsoleItemProps = {};
|
export function itemPropsDecoder(
|
||||||
|
data: UnknownObject
|
||||||
abstract class VisualConsoleItem extends EventEmitter {
|
): VisualConsoleItemProps | never {
|
||||||
private itemProps: VisualConsoleItemProps;
|
if (data.id == null || isNaN(parseInt(data.id))) {
|
||||||
private containerRef: HTMLElement;
|
throw new TypeError("invalid id.");
|
||||||
private itemBoxRef: HTMLElement;
|
}
|
||||||
protected elementRef: HTMLElement;
|
// TODO: Check valid types.
|
||||||
|
if (data.type == null || isNaN(parseInt(data.type))) {
|
||||||
constructor(container: HTMLElement, props: VisualConsoleItemProps) {
|
throw new TypeError("invalid type.");
|
||||||
super();
|
|
||||||
this.containerRef = container;
|
|
||||||
this.itemProps = props;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get props(): VisualConsoleItemProps {
|
return {
|
||||||
|
id: parseInt(data.id),
|
||||||
|
type: parseInt(data.type),
|
||||||
|
label:
|
||||||
|
typeof data.label === "string" && data.label.length > 0
|
||||||
|
? data.label
|
||||||
|
: null,
|
||||||
|
isLinkEnabled: parseBoolean(data.isLinkEnabled),
|
||||||
|
isOnTop: parseBoolean(data.isOnTop),
|
||||||
|
parentId: parseIntOr(data.parentId, null),
|
||||||
|
aclGroupId: parseIntOr(data.aclGroupId, null),
|
||||||
|
...sizePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
|
||||||
|
...positionPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class VisualConsoleItem<ItemProps extends VisualConsoleItemProps> {
|
||||||
|
// Properties of the item.
|
||||||
|
private itemProps: ItemProps;
|
||||||
|
// Reference of the DOM element which contain all the items.
|
||||||
|
private readonly containerRef: HTMLElement;
|
||||||
|
// Reference of the DOM element which contain the item box.
|
||||||
|
private readonly itemBoxRef: HTMLElement;
|
||||||
|
// Reference of the DOM element which contain the view of the item which extends this class.
|
||||||
|
protected readonly elementRef: HTMLElement;
|
||||||
|
// Event manager for click events.
|
||||||
|
private readonly clickEventManager = new TypedEvent<
|
||||||
|
ItemClickEvent<ItemProps>
|
||||||
|
>();
|
||||||
|
// List of references to clean the event listeners.
|
||||||
|
private readonly disposables: Disposable[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To create a new element which will be inside the item box.
|
||||||
|
* @return Item.
|
||||||
|
*/
|
||||||
|
abstract createDomElement(): HTMLElement;
|
||||||
|
|
||||||
|
constructor(container: HTMLElement, props: ItemProps) {
|
||||||
|
this.containerRef = container;
|
||||||
|
this.itemProps = props;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a HTMLElement which represents the container box
|
||||||
|
* of the Visual Console item. This element will manage
|
||||||
|
* all the common things like click events, show a border
|
||||||
|
* when hovered, etc.
|
||||||
|
*/
|
||||||
|
this.itemBoxRef = this.createItemBoxDomElement();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a HTMLElement which represents the custom view
|
||||||
|
* of the Visual Console item. This element will be
|
||||||
|
* different depending on the item implementation.
|
||||||
|
*/
|
||||||
|
this.elementRef = this.createDomElement();
|
||||||
|
|
||||||
|
// Insert the elements into their parents.
|
||||||
|
// Visual Console Container > Generic Item Box > Custom Item View.
|
||||||
|
this.itemBoxRef.append(this.elementRef);
|
||||||
|
this.containerRef.append(this.itemBoxRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To create a new box for the visual console item.
|
||||||
|
* @return Item box.
|
||||||
|
*/
|
||||||
|
private createItemBoxDomElement(): HTMLElement {
|
||||||
|
const box: HTMLDivElement = document.createElement("div");
|
||||||
|
box.className = "visual-console-item";
|
||||||
|
box.style.width = `${this.props.width}px`;
|
||||||
|
box.style.height = `${this.props.height}px`;
|
||||||
|
box.onclick = () => this.clickEventManager.emit({ data: this.props });
|
||||||
|
// TODO: Add label.
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public accessor of the `props` property.
|
||||||
|
* @return Properties.
|
||||||
|
*/
|
||||||
|
get props(): ItemProps {
|
||||||
return this.itemProps;
|
return this.itemProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public setter of the `props` property.
|
||||||
|
* If the new props are different enough than the
|
||||||
|
* stored props, a render would be fired.
|
||||||
|
* @param newProps
|
||||||
|
*/
|
||||||
|
set props(newProps: ItemProps) {
|
||||||
|
const prevProps = this.props;
|
||||||
|
// Update the internal props.
|
||||||
|
this.itemProps = newProps;
|
||||||
|
|
||||||
|
// From this point, things which rely on this.props can access to the changes.
|
||||||
|
|
||||||
|
// Check if we should re-render.
|
||||||
|
if (this.shouldBeUpdated(newProps)) this.render(prevProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To compare the previous and the new props and returns a boolean value
|
||||||
|
* in case the difference is meaningfull enough to perform DOM changes.
|
||||||
|
*
|
||||||
|
* Here, the only comparision is done by reference.
|
||||||
|
*
|
||||||
|
* Override this function to perform a different comparision depending on the item needs.
|
||||||
|
*
|
||||||
|
* @param newProps
|
||||||
|
* @return Whether the difference is meaningful enough to perform DOM changes or not.
|
||||||
|
*/
|
||||||
|
protected shouldBeUpdated(newProps: ItemProps): boolean {
|
||||||
|
return this.props !== newProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To recreate or update the HTMLElement which represents the item into the DOM.
|
||||||
|
* @param prevProps If exists it will be used to only perform
|
||||||
|
* perform DOM updates instead of a full replace.
|
||||||
|
*/
|
||||||
|
render(prevProps: ItemProps | null): void {
|
||||||
|
// Move box.
|
||||||
|
if (!prevProps || prevProps.x !== this.props.x) {
|
||||||
|
this.itemBoxRef.style.left = `${this.props.x}px`;
|
||||||
|
}
|
||||||
|
if (!prevProps || prevProps.y !== this.props.y) {
|
||||||
|
this.itemBoxRef.style.top = `${this.props.y}px`;
|
||||||
|
}
|
||||||
|
// Resize box.
|
||||||
|
if (!prevProps || prevProps.width !== this.props.width) {
|
||||||
|
this.itemBoxRef.style.width = `${this.props.width}px`;
|
||||||
|
}
|
||||||
|
if (!prevProps || prevProps.height !== this.props.height) {
|
||||||
|
this.itemBoxRef.style.height = `${this.props.height}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.elementRef.replaceWith(this.createDomElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To remove the event listeners and the elements from the DOM.
|
||||||
|
*/
|
||||||
|
remove(): void {
|
||||||
|
// Event listeners.
|
||||||
|
this.disposables.forEach(_ => _.dispose());
|
||||||
|
// VisualConsoleItem extension DOM element.
|
||||||
|
this.elementRef.remove();
|
||||||
|
// VisualConsoleItem DOM element.
|
||||||
|
this.itemBoxRef.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To move the item.
|
||||||
|
* @param x Horizontal axis position.
|
||||||
|
* @param y Vertical axis position.
|
||||||
|
*/
|
||||||
|
move(x: number, y: number): void {
|
||||||
|
// Compare position.
|
||||||
|
if (x === this.props.x && y === this.props.y) return;
|
||||||
|
// Update position. Change itemProps instead of props to avoid re-render.
|
||||||
|
this.itemProps.x = x;
|
||||||
|
this.itemProps.y = y;
|
||||||
|
// Move element.
|
||||||
|
this.itemBoxRef.style.left = `${x}px`;
|
||||||
|
this.itemBoxRef.style.top = `${y}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To resize the item.
|
||||||
|
* @param width Width.
|
||||||
|
* @param height Height.
|
||||||
|
*/
|
||||||
|
resize(width: number, height: number): void {
|
||||||
|
// Compare size.
|
||||||
|
if (width === this.props.width && height === this.props.height) return;
|
||||||
|
// Update size. Change itemProps instead of props to avoid re-render.
|
||||||
|
this.itemProps.width = width;
|
||||||
|
this.itemProps.height = height;
|
||||||
|
// Resize element.
|
||||||
|
this.itemBoxRef.style.width = `${width}px`;
|
||||||
|
this.itemBoxRef.style.height = `${height}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To add an event handler to the click of the linked visual console elements.
|
||||||
|
* @param listener Function which is going to be executed when a linked console is clicked.
|
||||||
|
*/
|
||||||
|
onClick(listener: Listener<ItemClickEvent<ItemProps>>): void {
|
||||||
|
/*
|
||||||
|
* The '.on' function returns a function which will clean the event
|
||||||
|
* listener when executed. We store all the 'dispose' functions to
|
||||||
|
* call them when the item should be cleared.
|
||||||
|
*/
|
||||||
|
this.disposables.push(this.clickEventManager.on(listener));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VisualConsoleItem;
|
export default VisualConsoleItem;
|
||||||
|
|
|
@ -1,5 +1,41 @@
|
||||||
function hello(): void {
|
// import VisualConsole from "./VisualConsole";
|
||||||
console.log("Hello world!");
|
import StaticGraphItem from "./items/StaticGraph";
|
||||||
|
|
||||||
|
// declare global {
|
||||||
|
// interface Window {
|
||||||
|
// VisualConsole: VisualConsole;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// window.VisualConsole = VisualConsole;
|
||||||
|
|
||||||
|
const container = document.getElementById("visual-console-container");
|
||||||
|
|
||||||
|
if (container != null) {
|
||||||
|
const item = new StaticGraphItem(container, {
|
||||||
|
// Generic props.
|
||||||
|
id: 1,
|
||||||
|
type: 1,
|
||||||
|
label: null,
|
||||||
|
isLinkEnabled: false,
|
||||||
|
isOnTop: false,
|
||||||
|
parentId: null,
|
||||||
|
aclGroupId: null,
|
||||||
|
// Position props.
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
// Size props.
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
// Agent props.
|
||||||
|
agentId: null,
|
||||||
|
agentName: null,
|
||||||
|
// Module props.
|
||||||
|
moduleId: null,
|
||||||
|
moduleName: null,
|
||||||
|
// Custom props.
|
||||||
|
imageSrc:
|
||||||
|
"https://brutus.artica.lan:8081/uploads/-/system/project/avatar/1/1.png",
|
||||||
|
showLastValueTooltip: "default"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const asd: string = "";
|
|
||||||
hello();
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { WithModuleProps, LinkedVisualConsoleProps } from "../types";
|
||||||
|
|
||||||
|
import VisualConsoleItem, {
|
||||||
|
VisualConsoleItemProps
|
||||||
|
} from "../VisualConsoleItem";
|
||||||
|
|
||||||
|
export type StaticGraphProps = {
|
||||||
|
imageSrc: string; // URL?
|
||||||
|
showLastValueTooltip: "default" | "enabled" | "disabled";
|
||||||
|
} & VisualConsoleItemProps &
|
||||||
|
(WithModuleProps | LinkedVisualConsoleProps);
|
||||||
|
|
||||||
|
export default class StaticGraph extends VisualConsoleItem<StaticGraphProps> {
|
||||||
|
createDomElement(): HTMLElement {
|
||||||
|
const img: HTMLImageElement = document.createElement("img");
|
||||||
|
img.className = "static-graph";
|
||||||
|
img.src = this.props.imageSrc;
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { Position, Size, UnknownObject } from "./types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a number or a default value from a raw value.
|
||||||
|
* @param value Raw value from which we will try to extract a valid number.
|
||||||
|
* @param defaultValue Default value to use if we cannot extract a valid number.
|
||||||
|
* @return A valid number or the default value.
|
||||||
|
*/
|
||||||
|
export function parseIntOr<T>(value: any, defaultValue: T): number | T {
|
||||||
|
if (typeof value === "number") return value;
|
||||||
|
if (typeof value === "string" && value.length > 0 && isNaN(parseInt(value)))
|
||||||
|
return parseInt(value);
|
||||||
|
else return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a boolean from a raw value.
|
||||||
|
* @param value Raw value from which we will try to extract the boolean.
|
||||||
|
* @return A valid boolean value. false by default.
|
||||||
|
*/
|
||||||
|
export function parseBoolean(value: any): boolean {
|
||||||
|
if (typeof value === "boolean") return value;
|
||||||
|
else if (typeof value === "number") return value > 0;
|
||||||
|
else if (typeof value === "string") return value === "1" || value === "true";
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a valid typed object from a raw object.
|
||||||
|
* @param data Raw object.
|
||||||
|
* @return An object representing the position.
|
||||||
|
*/
|
||||||
|
export function positionPropsDecoder(data: UnknownObject): Position {
|
||||||
|
return {
|
||||||
|
x: parseIntOr(data.x, 0),
|
||||||
|
y: parseIntOr(data.y, 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a valid typed object from a raw object.
|
||||||
|
* @param data Raw object.
|
||||||
|
* @return An object representing the size.
|
||||||
|
* @throws Will throw a TypeError if the width and height are not valid numbers.
|
||||||
|
*/
|
||||||
|
export function sizePropsDecoder(data: UnknownObject): Size | never {
|
||||||
|
if (
|
||||||
|
data.width == null ||
|
||||||
|
isNaN(parseInt(data.width)) ||
|
||||||
|
data.height == null ||
|
||||||
|
isNaN(parseInt(data.height))
|
||||||
|
) {
|
||||||
|
throw new TypeError("invalid size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: parseInt(data.width),
|
||||||
|
height: parseInt(data.height)
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
export type UnknownObject = {
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface Position {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Size {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WithAgentProps {
|
||||||
|
metaconsoleId?: number | null;
|
||||||
|
agentId: number | null;
|
||||||
|
agentName: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WithModuleProps extends WithAgentProps {
|
||||||
|
moduleId: number | null;
|
||||||
|
moduleName: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LinkedVisualConsoleProps = {
|
||||||
|
metaconsoleId?: number | null;
|
||||||
|
linkedLayoutId: number | null;
|
||||||
|
linkedLayoutAgentId: number | null;
|
||||||
|
} & (
|
||||||
|
| {
|
||||||
|
linkedLayoutStatusType: "default";
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
linkedLayoutStatusType: "weight";
|
||||||
|
linkedLayoutStatusTypeWeight: number;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
linkedLayoutStatusType: "service";
|
||||||
|
linkedLayoutStatusTypeWarningThreshold: number;
|
||||||
|
linkedLayoutStatusTypeCriticalThreshold: number;
|
||||||
|
});
|
|
@ -3,12 +3,12 @@
|
||||||
<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" />
|
||||||
<title>Page Title</title>
|
<title>Visual Console Sandbox</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
|
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
|
||||||
<script src="visual-console.bundle.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
This is the body
|
<div id="visual-console-container"></div>
|
||||||
</body>
|
</body>
|
||||||
|
<script src="visual-console.bundle.js"></script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
.visual-console-item > * {
|
||||||
|
width: inherit;
|
||||||
|
height: inherit;
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: process.env.NODE_ENV,
|
mode: process.env.NODE_ENV,
|
||||||
entry: __dirname + "/src/index.ts",
|
entry: __dirname + "/src/index.ts",
|
||||||
devtool: "inline-source-map",
|
devtool: "source-map",
|
||||||
|
resolve: {
|
||||||
|
extensions: [".ts", ".js", ".json"]
|
||||||
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue