mirror of
https://github.com/BorysLevytskyi/BitwiseCmd.git
synced 2025-12-15 01:12:47 +01:00
Simplify bitwisecmm (#16)
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InputBox from './components/InputBox';
|
import InputBox from './components/InputBox';
|
||||||
import DisplayResultView from './components/DisplayResultView';
|
import DisplayResultView from './components/DisplayResultView';
|
||||||
import AppState from './core/AppState';
|
import AppState, { CommandResultView } from './core/AppState';
|
||||||
import cmd from './core/cmd';
|
import cmd from './core/cmd';
|
||||||
import CommandResult from './models/CommandResult';
|
|
||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import Indicators from './components/Indicators';
|
import Indicators from './components/Indicators';
|
||||||
import CommandLink from './components/CommandLink';
|
import hash from './core/hash';
|
||||||
|
|
||||||
type AppRootProps = {
|
type AppRootProps = {
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
@@ -15,7 +14,7 @@ type AppRootProps = {
|
|||||||
type AppRootState = {
|
type AppRootState = {
|
||||||
uiTheme: string,
|
uiTheme: string,
|
||||||
emphasizeBytes: boolean,
|
emphasizeBytes: boolean,
|
||||||
commandResults: CommandResult[]
|
commandResults: CommandResultView[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class AppRoot extends React.Component<AppRootProps, AppRootState> {
|
export default class AppRoot extends React.Component<AppRootProps, AppRootState> {
|
||||||
@@ -35,7 +34,10 @@ export default class AppRoot extends React.Component<AppRootProps, AppRootState>
|
|||||||
|
|
||||||
getResultViews() : JSX.Element[] {
|
getResultViews() : JSX.Element[] {
|
||||||
log.debug('getting result views')
|
log.debug('getting result views')
|
||||||
var results = this.state.commandResults.map((r, i) => <DisplayResultView key={i} content={r} input={r.input} inputHash={r.inputHash} appState={this.props.appState} />);
|
var results = this.state.commandResults.map((r, i) =>
|
||||||
|
<DisplayResultView key={r.key} input={r.input} inputHash={hash.encodeHash(r.input)} appState={this.props.appState}>
|
||||||
|
{r.view}
|
||||||
|
</DisplayResultView>);
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +68,7 @@ export default class AppRoot extends React.Component<AppRootProps, AppRootState>
|
|||||||
<InputBox onCommandEntered={(input) => cmd.execute(input)} />
|
<InputBox onCommandEntered={(input) => cmd.execute(input)} />
|
||||||
|
|
||||||
<span className="configPnl">
|
<span className="configPnl">
|
||||||
<span id="emphasizeBytes" data-cmd="em" className={"indicator " + this.getIndicator(this.state.emphasizeBytes)} title="Toggle Emphasize Bytes" onClick={e => this.toggleEmphasizeBytes()}>[em]</span>
|
<span id="emphasizeBytes" data-cmd="em" className={"indicator " + this.getIndicator(this.state.emphasizeBytes)} title="Toggle Emphasize Bytes" onClick={() => this.toggleEmphasizeBytes()}>[em]</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
import HelpResult from './models/HelpResult';
|
|
||||||
import AboutResult from './models/AboutResult';
|
|
||||||
import UnknownCommandResult from './models/UnknownCommandResult';
|
|
||||||
import ExpressionResult from './models/ExpressionResult';
|
|
||||||
import {UnhandledErrorResult, ErrorResult} from './models/ErrorResults';
|
|
||||||
import WahtsnewResult from './models/WhatsnewResult';
|
|
||||||
import StringResult from './models/StringResult';
|
|
||||||
import * as expression from './expression/expression';
|
import * as expression from './expression/expression';
|
||||||
|
import React from 'react';
|
||||||
import uuid from 'uuid/v4';
|
import uuid from 'uuid/v4';
|
||||||
import { CommandInput, CmdShell } from './core/cmd';
|
import { CommandInput, CmdShell } from './core/cmd';
|
||||||
import { ExpressionInput } from './expression/expression-interfaces';
|
|
||||||
import AppState from './core/AppState';
|
import AppState from './core/AppState';
|
||||||
import {ParsingError, IpAddress, ipAddressParser, IpAddressWithSubnetMask, ParsedIpObject} from './ipaddress/ip'
|
import {ParsingError, IpAddress, ipAddressParser, IpAddressWithSubnetMask, ParsedIpObject} from './ipaddress/ip'
|
||||||
import IpAddressResult from './models/IpAddressResult';
|
import ErrorResultView from './components/results/ErrorResultView';
|
||||||
import { isGetAccessor, isPrefixUnaryExpression } from 'typescript';
|
import HelpResultView from './components/results/HelpResultView';
|
||||||
|
import AboutResultView from './components/results/AboutResultView';
|
||||||
|
import WhatsnewResultView from './components/results/WhatsNewResultView';
|
||||||
|
import TextResultView from './components/results/TextResultView';
|
||||||
|
import IpAddressView from './components/results/IpAddressView';
|
||||||
|
import UnknownInputResultView from './components/results/UnknownInputResultView';
|
||||||
|
import BitwiseOperationExpressionView from './components/results/expressions/BitwiseOperationExpressionView';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
initialize (cmd: CmdShell, appState: AppState) {
|
initialize (cmd: CmdShell, appState: AppState) {
|
||||||
@@ -20,19 +19,19 @@ export default {
|
|||||||
cmd.debugMode = appState.debugMode;
|
cmd.debugMode = appState.debugMode;
|
||||||
appState.onChange(() => cmd.debugMode = appState.debugMode);
|
appState.onChange(() => cmd.debugMode = appState.debugMode);
|
||||||
|
|
||||||
cmd.command("help", (c: CommandInput) => appState.addCommandResult(new HelpResult(c.input)));
|
cmd.command("help", (c: CommandInput) => appState.addCommandResult(c.input, <HelpResultView />));
|
||||||
cmd.command("clear", (c: CommandInput) => appState.clearCommandResults());
|
cmd.command("clear", () => appState.clearCommandResults());
|
||||||
cmd.command("em", (c: CommandInput) => appState.toggleEmphasizeBytes());
|
cmd.command("em", () => appState.toggleEmphasizeBytes());
|
||||||
cmd.command("dark", (c: CommandInput) => appState.setUiTheme('dark'));
|
cmd.command("dark", () => appState.setUiTheme('dark'));
|
||||||
cmd.command("light", (c: CommandInput) => appState.setUiTheme('light'));
|
cmd.command("light", () => appState.setUiTheme('light'));
|
||||||
cmd.command("midnight", (c: CommandInput) => appState.setUiTheme('midnight'));
|
cmd.command("midnight", () => appState.setUiTheme('midnight'));
|
||||||
cmd.command("about", (c: CommandInput) => appState.addCommandResult(new AboutResult(c.input)));
|
cmd.command("about", (c: CommandInput) => appState.addCommandResult(c.input, <AboutResultView />));
|
||||||
cmd.command("whatsnew", (c: CommandInput) => appState.addCommandResult(new WahtsnewResult(c.input)));
|
cmd.command("whatsnew", (c: CommandInput) => appState.addCommandResult(c.input, <WhatsnewResultView />));
|
||||||
cmd.command("guid", (c: CommandInput) => appState.addCommandResult(new StringResult(c.input, uuid())));
|
cmd.command("guid", (c: CommandInput) => appState.addCommandResult(c.input, <TextResultView text={uuid()} />));
|
||||||
cmd.command("-notrack", (c: CommandInput) => {});
|
cmd.command("-notrack", () => {});
|
||||||
cmd.command("-debug", (c: CommandInput) => {
|
cmd.command("-debug", (c: CommandInput) => {
|
||||||
appState.toggleDebugMode();
|
appState.toggleDebugMode();
|
||||||
appState.addCommandResult(new StringResult(c.input, `Debug Mode: ${appState.debugMode}`))
|
appState.addCommandResult(c.input, <TextResultView text={`Debug Mode: ${appState.debugMode}`}/>);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@ export default {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if(result instanceof ParsingError) {
|
if(result instanceof ParsingError) {
|
||||||
appState.addCommandResult(new ErrorResult(c.input, result.errorMessage));
|
appState.addCommandResult(c.input, <ErrorResultView errorMessage={result.errorMessage} />);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +62,7 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
appState.addCommandResult(new IpAddressResult(c.input, ipAddresses));
|
appState.addCommandResult(c.input, <IpAddressView ipAddresses={ipAddresses} />);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -72,16 +71,16 @@ export default {
|
|||||||
canHandle: (input:string) => expression.parser.canParse(input),
|
canHandle: (input:string) => expression.parser.canParse(input),
|
||||||
handle: function(c: CommandInput) {
|
handle: function(c: CommandInput) {
|
||||||
var expr = expression.parser.parse(c.input);
|
var expr = expression.parser.parse(c.input);
|
||||||
appState.addCommandResult(new ExpressionResult(c.input, expr as ExpressionInput));
|
appState.addCommandResult(c.input, <BitwiseOperationExpressionView expression={expr!} emphasizeBytes={appState.emphasizeBytes} />);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Last command handler reports that input is unknown
|
// Last command handler reports that input is unknown
|
||||||
cmd.command({
|
cmd.command({
|
||||||
canHandle: () => true,
|
canHandle: () => true,
|
||||||
handle: (c: CommandInput) => appState.addCommandResult(new UnknownCommandResult(c.input))
|
handle: (c: CommandInput) => appState.addCommandResult(c.input, <UnknownInputResultView input={c.input}/>)
|
||||||
});
|
});
|
||||||
|
|
||||||
cmd.onError((input: string, err: Error) => appState.addCommandResult(new UnhandledErrorResult(input, err)));
|
cmd.onError((input: string, err: Error) => appState.addCommandResult(input, <ErrorResultView errorMessage={err.toString()} />));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,81 +1,23 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import HelpResult from '../models/HelpResult';
|
|
||||||
import AboutResult from '../models/AboutResult';
|
|
||||||
import HelpResultView from './results/HelpResultView';
|
|
||||||
import AboutResultView from './results/AboutResultView';
|
|
||||||
import ExpressionResult from '../models/ExpressionResult';
|
|
||||||
import BitwiseOperationExpressionView from './results/expressions/BitwiseOperationExpressionView';
|
|
||||||
import WhatsnewResult from '../models/WhatsnewResult';
|
|
||||||
import WhatsnewResultView from './results/WhatsNewResultView';
|
|
||||||
import {UnhandledErrorResult, ErrorResult} from '../models/ErrorResults';
|
|
||||||
import StringResult from '../models/StringResult';
|
|
||||||
import IpAddressView from './results/IpAddressView';
|
|
||||||
|
|
||||||
import CommandResult from '../models/CommandResult';
|
|
||||||
import AppState from '../core/AppState';
|
import AppState from '../core/AppState';
|
||||||
import IpAddressResult from '../models/IpAddressResult';
|
|
||||||
|
|
||||||
type DisplayResultProps = {
|
type DisplayResultProps = {
|
||||||
content : CommandResult,
|
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
inputHash: string,
|
inputHash: string,
|
||||||
input: string,
|
input: string,
|
||||||
key: number
|
key: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class DisplayResult extends React.Component<DisplayResultProps> {
|
export default class DisplayResultView extends React.Component<DisplayResultProps> {
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
return <div className="result">
|
return <div className="result">
|
||||||
<div className="input mono"><span className="cur">></span>{this.props.content.input}<a className="hashLink" title="Link for this expression" href={window.location.pathname + '#' + this.props.inputHash}>#</a></div>
|
<div className="input mono"><span className="cur">></span>{this.props.input}<a className="hashLink" title="Link for this expression" href={window.location.pathname + '#' + this.props.inputHash}>#</a></div>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
{this.findResultComponent(this.props.content)}
|
{this.props.children}
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
findResultComponent(result: CommandResult) : JSX.Element {
|
|
||||||
|
|
||||||
if(result instanceof HelpResult) {
|
|
||||||
return <HelpResultView />
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result instanceof AboutResult) {
|
|
||||||
return <AboutResultView />
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result instanceof ExpressionResult) {
|
|
||||||
return <BitwiseOperationExpressionView expression={result.expression} emphasizeBytes={this.props.appState.emphasizeBytes} />
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result instanceof WhatsnewResult) {
|
|
||||||
return <WhatsnewResultView />
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result instanceof StringResult) {
|
|
||||||
return <p>{result.value}</p>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result instanceof UnhandledErrorResult) {
|
|
||||||
return <div className="result">
|
|
||||||
<div className="error">(X_X) Ooops.. Something ain' right: <strong>{result.error.message}</strong></div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result instanceof ErrorResult) {
|
|
||||||
return <div className="result">
|
|
||||||
<div className="error">{result.errorMessage}</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result instanceof IpAddressResult) {
|
|
||||||
const ipResult = result as IpAddressResult;
|
|
||||||
|
|
||||||
return <IpAddressView ipAddresses={ipResult.ipAddresses} />
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className="result">
|
|
||||||
<div className="error">¯\_(ツ)_/¯ Sorry, i don′t know what <strong>{this.props.content.input}</strong> is</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
10
src/components/results/ErrorResultView.tsx
Normal file
10
src/components/results/ErrorResultView.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
function ErrorResultView(props : {errorMessage:string}) {
|
||||||
|
|
||||||
|
return <div className="result">
|
||||||
|
<div className="error">{props.errorMessage}</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ErrorResultView;
|
||||||
7
src/components/results/TextResultView.tsx
Normal file
7
src/components/results/TextResultView.tsx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
function TextResultView(props : { text: string }) {
|
||||||
|
return <p>{props.text}</p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TextResultView;
|
||||||
10
src/components/results/UnknownInputResultView.tsx
Normal file
10
src/components/results/UnknownInputResultView.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
function UnknownInputResultView(props : {input:string}) {
|
||||||
|
|
||||||
|
return <div className="result">
|
||||||
|
<div className="error">¯\_(ツ)_/¯ Sorry, i don′t know what <strong>{props.input}</strong> is</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UnknownInputResultView;
|
||||||
@@ -9,6 +9,12 @@ export type PersistedAppData = {
|
|||||||
debugMode: boolean | null;
|
debugMode: boolean | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type CommandResultView = {
|
||||||
|
key: number,
|
||||||
|
input: string,
|
||||||
|
view: JSX.Element
|
||||||
|
};
|
||||||
|
|
||||||
export type AppStateChangeHandler = (state: AppState) => void;
|
export type AppStateChangeHandler = (state: AppState) => void;
|
||||||
|
|
||||||
export default class AppState {
|
export default class AppState {
|
||||||
@@ -17,15 +23,15 @@ export default class AppState {
|
|||||||
emphasizeBytes: boolean;
|
emphasizeBytes: boolean;
|
||||||
debugMode: boolean = false;
|
debugMode: boolean = false;
|
||||||
uiTheme: string;
|
uiTheme: string;
|
||||||
handlers: AppStateChangeHandler[];
|
changeHandlers: AppStateChangeHandler[];
|
||||||
commandResults: any[];
|
commandResults: CommandResultView[];
|
||||||
persistedVersion: number;
|
persistedVersion: number;
|
||||||
wasOldVersion: boolean;
|
wasOldVersion: boolean;
|
||||||
env: string;
|
env: string;
|
||||||
|
|
||||||
constructor(persistData : PersistedAppData, env: string) {
|
constructor(persistData : PersistedAppData, env: string) {
|
||||||
this.commandResults = [];
|
this.commandResults = [];
|
||||||
this.handlers = [];
|
this.changeHandlers = [];
|
||||||
this.uiTheme = persistData.uiTheme || 'midnight';
|
this.uiTheme = persistData.uiTheme || 'midnight';
|
||||||
this.env = env;
|
this.env = env;
|
||||||
|
|
||||||
@@ -35,9 +41,10 @@ export default class AppState {
|
|||||||
this.debugMode = env !== 'prod' || persistData.debugMode === true;
|
this.debugMode = env !== 'prod' || persistData.debugMode === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommandResult(result : any) {
|
addCommandResult(input : string, view : JSX.Element) {
|
||||||
this.commandResults.unshift(result);
|
const key = generateKey();
|
||||||
log.debug("result added", result);
|
this.commandResults.unshift({key, input, view});
|
||||||
|
log.debug(`command result added: ${input}`);
|
||||||
this.triggerChanged();
|
this.triggerChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,11 +59,11 @@ export default class AppState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onChange(handler : AppStateChangeHandler) {
|
onChange(handler : AppStateChangeHandler) {
|
||||||
this.handlers.push(handler);
|
this.changeHandlers.push(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerChanged() {
|
triggerChanged() {
|
||||||
this.handlers.forEach(h => h(this));
|
this.changeHandlers.forEach(h => h(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
setUiTheme(theme: string) {
|
setUiTheme(theme: string) {
|
||||||
@@ -77,4 +84,8 @@ export default class AppState {
|
|||||||
debugMode: this.debugMode
|
debugMode: this.debugMode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function generateKey() : number {
|
||||||
|
return Math.ceil(Math.random()*10000000) ^ Date.now(); // Because why the hell not...
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import CommandResult from './CommandResult';
|
|
||||||
|
|
||||||
export default class AboutResult extends CommandResult {
|
|
||||||
constructor(input:string) {
|
|
||||||
super(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
export default class CommandResult {
|
|
||||||
input: string;
|
|
||||||
inputHash: string;
|
|
||||||
|
|
||||||
constructor(input: string) {
|
|
||||||
this.input = input;
|
|
||||||
this.inputHash = this.encodeHash(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
encodeHash (input: string) {
|
|
||||||
return encodeURI(input.trim().replace(/\s/g,','));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import CommandResult from './CommandResult';
|
|
||||||
|
|
||||||
export class UnhandledErrorResult extends CommandResult {
|
|
||||||
error: Error;
|
|
||||||
constructor(input: string, error : Error) {
|
|
||||||
super(input);
|
|
||||||
this.error = error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ErrorResult extends CommandResult {
|
|
||||||
errorMessage: string;
|
|
||||||
constructor(input: string, errorMessage : string) {
|
|
||||||
super(input);
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import CommandResult from './CommandResult';
|
|
||||||
import { ExpressionInput } from '../expression/expression-interfaces';
|
|
||||||
|
|
||||||
export default class ExpressionResult extends CommandResult {
|
|
||||||
expression: ExpressionInput;
|
|
||||||
constructor(input: string, expression: ExpressionInput) {
|
|
||||||
super(input);
|
|
||||||
this.expression = expression;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import CommandResult from './CommandResult';
|
|
||||||
|
|
||||||
export default class HelpResult extends CommandResult {
|
|
||||||
constructor(input: string) {
|
|
||||||
super(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { IpAddress, ipAddressParser, IpAddressWithSubnetMask } from '../ipaddress/ip';
|
|
||||||
import CommandResult from './CommandResult';
|
|
||||||
|
|
||||||
export default class IpAddressResult extends CommandResult {
|
|
||||||
ipAddresses: IpAddress[];
|
|
||||||
constructor(input: string, ipAddresses: IpAddress[]) {
|
|
||||||
super(input);
|
|
||||||
this.ipAddresses = ipAddresses;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import CommandResult from './CommandResult';
|
|
||||||
|
|
||||||
export default class StringResult extends CommandResult {
|
|
||||||
value:string;
|
|
||||||
constructor(input: string, value : string) {
|
|
||||||
super(input);
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import CommandResult from './CommandResult';
|
|
||||||
|
|
||||||
export default class UnknownCommandResult extends CommandResult {
|
|
||||||
message:string;
|
|
||||||
constructor(input : string) {
|
|
||||||
super(input);
|
|
||||||
this.message = `Sorry, i don''t know what ${input} is :(`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import CommandResult from './CommandResult';
|
|
||||||
|
|
||||||
export default class WhatsnewResult extends CommandResult {
|
|
||||||
constructor(input: string) {
|
|
||||||
super(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user