Adding a setting editor

This commit is contained in:
WolverinDEV 2020-09-17 23:06:02 +02:00
parent 2a8027ec23
commit 3771f40625
13 changed files with 568 additions and 24 deletions

View file

@ -4,7 +4,6 @@ import {Sound} from "../sound/Sounds";
import {ConnectionHandler} from "../ConnectionHandler"; import {ConnectionHandler} from "../ConnectionHandler";
import {server_connections} from "../ui/frames/connection_handlers"; import {server_connections} from "../ui/frames/connection_handlers";
import {createErrorModal, createInfoModal, createInputModal} from "../ui/elements/Modal"; import {createErrorModal, createInfoModal, createInputModal} from "../ui/elements/Modal";
import {settings} from "../settings";
import {spawnConnectModal} from "../ui/modal/ModalConnect"; import {spawnConnectModal} from "../ui/modal/ModalConnect";
import PermissionType from "../permission/PermissionType"; import PermissionType from "../permission/PermissionType";
import {spawnQueryCreate} from "../ui/modal/ModalQuery"; import {spawnQueryCreate} from "../ui/modal/ModalQuery";
@ -14,6 +13,8 @@ import {CommandResult} from "../connection/ServerConnectionDeclaration";
import {spawnSettingsModal} from "../ui/modal/ModalSettings"; import {spawnSettingsModal} from "../ui/modal/ModalSettings";
import {spawnPermissionEditorModal} from "../ui/modal/permission/ModalPermissionEditor"; import {spawnPermissionEditorModal} from "../ui/modal/permission/ModalPermissionEditor";
import {tr} from "../i18n/localize"; import {tr} from "../i18n/localize";
import {spawnGlobalSettingsEditor} from "tc-shared/ui/modal/global-settings-editor/Controller";
import {spawnModalCssVariableEditor} from "tc-shared/ui/modal/css-editor/Controller";
/* /*
function initialize_sounds(event_registry: Registry<ClientGlobalControlEvents>) { function initialize_sounds(event_registry: Registry<ClientGlobalControlEvents>) {
@ -137,10 +138,18 @@ export function initialize(event_registry: Registry<ClientGlobalControlEvents>)
}).open(); }).open();
break; break;
case "css-variable-editor":
spawnModalCssVariableEditor();
break;
case "settings": case "settings":
spawnSettingsModal(); spawnSettingsModal();
break; break;
case "settings-registry":
spawnGlobalSettingsEditor();
break;
default: default:
console.warn(tr("Received open window event for an unknown window: %s"), event.window); console.warn(tr("Received open window event for an unknown window: %s"), event.window);
} }

View file

@ -6,6 +6,8 @@ export interface ClientGlobalControlEvents {
action_open_window: { action_open_window: {
window: window:
"settings" | /* use action_open_window_settings! */ "settings" | /* use action_open_window_settings! */
"settings-registry" |
"css-variable-editor" |
"bookmark-manage" | "bookmark-manage" |
"query-manage" | "query-manage" |
"query-create" | "query-create" |

View file

@ -46,6 +46,7 @@ import "./profiles/ConnectionProfile";
import "./update/UpdaterWeb"; import "./update/UpdaterWeb";
import ContextMenuEvent = JQuery.ContextMenuEvent; import ContextMenuEvent = JQuery.ContextMenuEvent;
import {defaultConnectProfile, findConnectProfile} from "tc-shared/profiles/ConnectionProfile"; import {defaultConnectProfile, findConnectProfile} from "tc-shared/profiles/ConnectionProfile";
import {spawnGlobalSettingsEditor} from "tc-shared/ui/modal/global-settings-editor/Controller";
let preventWelcomeUI = false; let preventWelcomeUI = false;
async function initialize() { async function initialize() {
@ -151,8 +152,11 @@ export function handle_connect_request(properties: ConnectRequestData, connectio
function main() { function main() {
/* initialize font */ /* initialize font */
{ {
const font = settings.static_global(Settings.KEY_FONT_SIZE, 14); //parseInt(getComputedStyle(document.body).fontSize) const font = settings.static_global(Settings.KEY_FONT_SIZE);
$(document.body).css("font-size", font + "px"); $(document.body).css("font-size", font + "px");
settings.globalChangeListener(Settings.KEY_FONT_SIZE, value => {
$(document.body).css("font-size", value + "px");
})
} }
/* context menu prevent */ /* context menu prevent */
@ -308,6 +312,7 @@ function main() {
modal.close_listener.push(() => settings.changeGlobal(Settings.KEY_USER_IS_NEW, false)); modal.close_listener.push(() => settings.changeGlobal(Settings.KEY_USER_IS_NEW, false));
} }
spawnGlobalSettingsEditor();
//spawnVideoPopout(server_connections.active_connection(), "https://www.youtube.com/watch?v=9683D18fyvs"); //spawnVideoPopout(server_connections.active_connection(), "https://www.youtube.com/watch?v=9683D18fyvs");
} }

View file

@ -439,7 +439,7 @@ export class Settings extends StaticSettings {
static readonly KEY_FONT_SIZE: ValuedSettingsKey<number> = { static readonly KEY_FONT_SIZE: ValuedSettingsKey<number> = {
key: "font_size", key: "font_size",
valueType: "number", valueType: "number",
defaultValue: 14 defaultValue: 14 //parseInt(getComputedStyle(document.body).fontSize)
}; };
static readonly KEY_ICON_SIZE: ValuedSettingsKey<number> = { static readonly KEY_ICON_SIZE: ValuedSettingsKey<number> = {

View file

@ -25,6 +25,7 @@ import {control_bar_instance} from "../../ui/frames/control-bar";
import {icon_cache_loader, IconManager, LocalIcon} from "../../file/Icons"; import {icon_cache_loader, IconManager, LocalIcon} from "../../file/Icons";
import {spawnPermissionEditorModal} from "../../ui/modal/permission/ModalPermissionEditor"; import {spawnPermissionEditorModal} from "../../ui/modal/permission/ModalPermissionEditor";
import {spawnModalCssVariableEditor} from "../../ui/modal/css-editor/Controller"; import {spawnModalCssVariableEditor} from "../../ui/modal/css-editor/Controller";
import {global_client_actions} from "tc-shared/events/GlobalEvents";
export interface HRItem { } export interface HRItem { }
@ -523,11 +524,16 @@ export function initialize() {
menu.append_hr(); menu.append_hr();
item = menu.append_item(tr("Modify CSS variables")); item = menu.append_item(tr("Modify CSS variables"));
item.click(() => spawnModalCssVariableEditor()); item.click(() => global_client_actions.fire("action_open_window", { window: "css-variable-editor" }));
item = menu.append_item(tr("Open Registry"));
item.click(() => global_client_actions.fire("action_open_window", { window: "settings-registry" }));
menu.append_hr();
item = menu.append_item(tr("Settings")); item = menu.append_item(tr("Settings"));
item.icon("client-settings"); item.icon("client-settings");
item.click(() => spawnSettingsModal()); item.click(() => global_client_actions.fire("action_open_window_settings"));
} }
{ {

View file

@ -54,8 +54,16 @@ export const ServerLogRenderer = (props: { events: Registry<ServerLogUIEvents>,
}); });
props.events.reactUse("notify_log_add", event => { props.events.reactUse("notify_log_add", event => {
if(logs === "loading") if(logs === "loading") {
return; return;
}
if(__build.mode === "debug") {
const index = logs.findIndex(e => e.uniqueId === event.event.uniqueId);
if(index !== -1) {
debugger;
}
}
logs.push(event.event); logs.push(event.event);
logs.splice(0, Math.max(0, logs.length - 100)); logs.splice(0, Math.max(0, logs.length - 100));

View file

@ -103,17 +103,16 @@ function settings_general_application(container: JQuery, modal: Modal) {
const current_size = parseInt(getComputedStyle(document.body).fontSize); //settings.static_global(Settings.KEY_FONT_SIZE, 12); const current_size = parseInt(getComputedStyle(document.body).fontSize); //settings.static_global(Settings.KEY_FONT_SIZE, 12);
const select = container.find(".option-font-size"); const select = container.find(".option-font-size");
if (select.find("option[value='" + current_size + "']").length) if (select.find("option[value='" + current_size + "']").length) {
select.find("option[value='" + current_size + "']").prop("selected", true); select.find("option[value='" + current_size + "']").prop("selected", true);
else } else {
select.find("option[value='-1']").prop("selected", true); select.find("option[value='-1']").prop("selected", true);
}
select.on('change', event => { select.on('change', event => {
const value = parseInt(select.val() as string); const value = parseInt(select.val() as string);
settings.changeGlobal(Settings.KEY_FONT_SIZE, value); settings.changeGlobal(Settings.KEY_FONT_SIZE, value);
console.log("Changed font size to %dpx", value); console.log("Changed font size to %dpx", value);
$(document.body).css("font-size", value + "px");
}); });
} }

View file

@ -0,0 +1,80 @@
import {spawnReactModal} from "tc-shared/ui/react-elements/Modal";
import {ModalGlobalSettingsEditor} from "tc-shared/ui/modal/global-settings-editor/Renderer";
import {Registry} from "tc-shared/events";
import {ModalGlobalSettingsEditorEvents, Setting} from "tc-shared/ui/modal/global-settings-editor/Definitions";
import {settings, Settings, SettingsKey} from "tc-shared/settings";
export function spawnGlobalSettingsEditor() {
const events = new Registry<ModalGlobalSettingsEditorEvents>();
initializeController(events);
const modal = spawnReactModal(ModalGlobalSettingsEditor, events);
modal.show();
modal.events.on("destroy", () => {
events.fire("notify_destroy");
events.destroy();
});
}
function initializeController(events: Registry<ModalGlobalSettingsEditorEvents>) {
events.on("query_settings", () => {
const settingsList: Setting[] = [];
for(const key of Settings.KEYS) {
const setting = Settings[key] as SettingsKey<ConfigValueTypes>;
settingsList.push({
key: setting.key,
description: setting.description,
type: setting.valueType,
defaultValue: setting.defaultValue
});
}
events.fire_async("notify_settings", { settings: settingsList });
});
events.on("action_select_setting", event => {
events.fire("notify_selected_setting", { setting: event.setting });
});
events.on("query_setting", event => {
const setting = Settings.KEYS.map(setting => Settings[setting] as SettingsKey<ConfigValueTypes>).find(e => e.key === event.setting);
if(typeof setting === "undefined") {
events.fire("notify_setting", {
key: event.setting,
status: "not-found"
});
return;
}
events.fire("notify_setting", {
setting: event.setting,
status: "success",
info: {
key: setting.key,
description: setting.description,
type: setting.valueType,
defaultValue: setting.defaultValue
},
value: settings.global(setting)
});
});
events.on("action_set_value", event => {
const setting = Settings.KEYS.map(setting => Settings[setting] as SettingsKey<ConfigValueTypes>).find(e => e.key === event.setting);
if(typeof setting === "undefined") {
return;
}
/* the change will may already trigger a notify_setting_value, but just to ensure we're fiering it later as well */
settings.changeGlobal(setting, event.value);
events.fire_async("notify_setting_value", { setting: event.setting, value: event.value });
});
events.on("notify_destroy", settings.events.on("notify_setting_changed", event => {
if(event.mode === "global") {
events.fire_async("notify_setting_value", { setting: event.setting, value: event.newValue });
}
}));
}

View file

@ -0,0 +1,36 @@
export interface Setting {
key: string;
type: ConfigValueTypeNames;
description: string | undefined;
defaultValue: string | undefined;
}
export interface ModalGlobalSettingsEditorEvents {
action_select_setting: { setting: string }
action_set_filter: { filter: string },
action_set_value: { setting: string, value: string }
query_settings: {},
query_setting: { setting: string }
notify_settings: {
settings: Setting[]
},
notify_setting: {
setting: string,
status: "success" | "not-found",
info?: Setting,
value?: string
},
notify_selected_setting: {
setting: string
},
notify_setting_value: {
setting: string,
value: string
},
notify_destroy: {}
}

View file

@ -0,0 +1,198 @@
@import "../../../../css/static/mixin";
@import "../../../../css/static/properties";
.container {
display: flex;
flex-direction: row;
justify-content: stretch;
flex-grow: 1;
flex-shrink: 1;
padding: .5em;
width: 50em;
max-width: 50em;
min-width: 20em;
height: 30em;
@include user-select(none);
.subContainer {
display: flex;
flex-direction: column;
justify-content: stretch;
/* allocate as much space as we can get */
width: 100vw;
flex-grow: 1;
flex-shrink: 1;
.header {
flex-grow: 0;
flex-shrink: 0;
font-weight: bold;
color: #e0e0e0;
@include text-dotdotdot();
}
.body {
flex-grow: 1;
flex-shrink: 1;
min-height: 5em;
}
&.containerList {
max-width: 20em;
min-width: 6em;
}
&.containerEdit {
min-width: 10em;
}
}
.list {
flex-grow: 1;
flex-shrink: 1;
margin-right: 1em;
min-height: 6.5em;
position: relative;
display: flex;
flex-direction: column;
justify-content: stretch;
border: 1px #161616 solid;
border-radius: 0.2em;
background-color: #28292b;
.entries {
flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: column;
justify-content: stretch;
overflow-x: hidden;
overflow-y: auto;
min-height: 3em;
@include chat-scrollbar-vertical();
.entry {
flex-grow: 0;
flex-shrink: 0;
padding-left: .5em;
padding-right: .5em;
display: flex;
flex-direction: row;
justify-content: stretch;
height: 1.5em;
cursor: pointer;
&:hover {
background-color: #2c2d2f;
}
&.selected {
background-color: #1a1a1b;
}
}
}
.filter {
border-top: 1px #161616 solid;
display: flex;
flex-direction: row;
justify-content: stretch;
.input {
flex-grow: 1;
flex-shrink: 1;
margin: 0;
padding: .5em 1em;
min-width: 3em;
}
}
.overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
background-color: #28292b;
display: none;
flex-direction: column;
justify-content: center;
&.shown {
display: flex;
}
a {
text-align: center;
font-size: 1.2em;
}
}
}
.editor {
.info {
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: flex-start;
margin-bottom: 1em;
.title {
text-transform: uppercase;
color: var(--modal-query-key);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis
}
.value {
user-select: text;
@include text-dotdotdot();
}
}
.infoDescription {
.value {
white-space: pre-wrap!important;
height: 3.2em!important;
}
}
.infoValue {
.input {
padding: 0;
margin: 0;
}
}
}
}

View file

@ -0,0 +1,196 @@
import {Translatable} from "tc-shared/ui/react-elements/i18n";
import * as React from "react";
import {InternalModal} from "tc-shared/ui/react-elements/internal-modal/Controller";
import {createContext, useContext, useRef, useState} from "react";
import {Registry} from "tc-shared/events";
import {ModalGlobalSettingsEditorEvents, Setting} from "tc-shared/ui/modal/global-settings-editor/Definitions";
import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots";
import {FlatInputField} from "tc-shared/ui/react-elements/InputField";
const ModalEvents = createContext<Registry<ModalGlobalSettingsEditorEvents>>(undefined);
const cssStyle = require("./Renderer.scss");
const SettingInfoRenderer = (props: { children: [React.ReactNode, React.ReactNode ], className?: string }) => (
<div className={cssStyle.info + " " + (props.className || "")}>
<div className={cssStyle.title}>{props.children[0]}</div>
<div className={cssStyle.value}>{props.children[1]}</div>
</div>
);
const SettingEditor = () => {
const events = useContext(ModalEvents);
const [ isApplying, setApplying ] = useState(false);
const [ currentValue, setCurrentValue ] = useState<string>();
const [ currentSetting, setCurrentSetting ] = useState<Setting | "not-found">(false);
const currentSettingKey = useRef();
events.reactUse("notify_selected_setting", event => {
if(event.setting === currentSettingKey.current) {
return;
}
currentSettingKey.current = event.setting;
events.fire("query_setting", { setting: event.setting });
});
events.reactUse("notify_setting", event => {
if(event.setting !== currentSettingKey.current) {
return;
}
setApplying(false);
if(event.status === "not-found") {
setCurrentSetting("not-found");
} else {
setCurrentValue(event.value);
setCurrentSetting(event.info);
}
});
events.reactUse("action_set_value", event => {
if(event.setting !== currentSettingKey.current) {
return;
}
setApplying(true);
});
events.reactUse("notify_setting_value", event => {
if(event.setting !== currentSettingKey.current) {
return;
}
setApplying(false);
setCurrentValue(event.value);
});
if(currentSetting === "not-found") {
return null;
} else if(!currentSetting) {
return null;
}
return (
<div className={cssStyle.body + " " + cssStyle.editor}>
<SettingInfoRenderer>
<Translatable>Setting key</Translatable>
{currentSetting.key}
</SettingInfoRenderer>
<SettingInfoRenderer className={cssStyle.infoDescription}>
<Translatable>Description</Translatable>
{currentSetting.description}
</SettingInfoRenderer>
<SettingInfoRenderer className={cssStyle}>
<Translatable>Default Value</Translatable>
{typeof currentSetting.defaultValue !== "undefined" ? (currentSetting.defaultValue + "") : tr("unset")}
</SettingInfoRenderer>
<SettingInfoRenderer className={cssStyle.infoValue}>
<Translatable>Value</Translatable>
<FlatInputField
className={cssStyle.input}
value={isApplying ? "" : currentValue ? currentValue : " "}
editable={!isApplying}
placeholder={isApplying ? tr("applying...") : tr("setting unset")}
onChange={text => {
setCurrentValue(text);
}}
finishOnEnter={true}
onBlur={() => {
events.fire("action_set_value", { setting: currentSettingKey.current, value: currentValue });
}}
/>
</SettingInfoRenderer>
</div>
);
}
const SettingEntryRenderer = (props: { setting: Setting, selected: boolean }) => {
const events = useContext(ModalEvents);
return (
<div className={cssStyle.entry + " " + (props.selected ? cssStyle.selected : "")} onClick={() => events.fire("action_select_setting", { setting: props.setting.key })}>
{props.setting.key}
</div>
);
}
const SettingList = () => {
const events = useContext(ModalEvents);
const [ settings, setSettings ] = useState<"loading" | Setting[]>(() => {
events.fire("query_settings");
return "loading";
});
const [ selectedSetting, setSelectedSetting ] = useState<string>(undefined);
const [ filter, setFilter ] = useState<string>(undefined);
events.reactUse("notify_settings", event => setSettings(event.settings));
events.reactUse("notify_selected_setting", event => setSelectedSetting(event.setting));
events.reactUse("action_set_filter", event => setFilter((event.filter || "").toLowerCase()));
return (
<div className={cssStyle.body + " " + cssStyle.list}>
<div className={cssStyle.entries}>
{settings === "loading" ? undefined :
settings.map(setting => {
filterBlock:
if(filter) {
if(setting.key.toLowerCase().indexOf(filter) !== -1) {
break filterBlock;
}
if(setting.description && setting.description.toLowerCase().indexOf(filter) !== -1) {
break filterBlock;
}
return undefined;
}
return <SettingEntryRenderer setting={setting} selected={setting.key === selectedSetting} key={setting.key} />;
})
}
</div>
<div className={cssStyle.filter}>
<FlatInputField className={cssStyle.input} onInput={text => events.fire("action_set_filter", { filter: text })} placeholder={tr("Filter settings")} />
</div>
<div className={cssStyle.overlay + " " + (settings === "loading" ? cssStyle.shown : "")}>
<a><Translatable>loading</Translatable> <LoadingDots /></a>
</div>
</div>
);
}
export class ModalGlobalSettingsEditor extends InternalModal {
protected readonly events: Registry<ModalGlobalSettingsEditorEvents>;
constructor(events: Registry<ModalGlobalSettingsEditorEvents>) {
super();
this.events = events;
}
renderBody(): React.ReactElement {
return (
<ModalEvents.Provider value={this.events}>
<div className={cssStyle.container}>
<div className={cssStyle.subContainer + " " + cssStyle.containerList}>
<div className={cssStyle.header}>
<a><Translatable>Setting list</Translatable></a>
</div>
<SettingList />
</div>
<div className={cssStyle.subContainer + " " + cssStyle.containerEdit}>
<div className={cssStyle.header}>
<a><Translatable>Setting editor</Translatable></a>
</div>
<SettingEditor />
</div>
</div>
</ModalEvents.Provider>
);
}
title(): string | React.ReactElement<Translatable> {
return <Translatable>Global settings registry</Translatable>;
}
}

View file

@ -157,15 +157,15 @@ html:root {
.containerFlat { .containerFlat {
position: relative; position: relative;
padding-top: 1.75rem; /* the label above (might be floating) */ padding-top: 1.75em; /* the label above (might be floating) */
margin-bottom: 1rem; /* for invalid label/help label */ margin-bottom: 1em; /* for invalid label/help label */
label { label {
color: #999999; color: #999999;
top: 1rem; top: 1em;
left: 0; left: 0;
font-size: .75rem; font-size: .75em;
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;
@ -182,13 +182,13 @@ html:root {
&.type-floating { &.type-floating {
will-change: left, top, contents; will-change: left, top, contents;
color: #999999; color: #999999;
top: 2.42rem; top: 2.42em;
font-size: 1rem; font-size: 1em;
} }
&.type-static { &.type-static {
top: 1rem; top: 1em;
font-size: .75rem; font-size: .75em;
} }
@include transition(color $button_hover_animation_time ease-in-out, top $button_hover_animation_time ease-in-out, font-size $button_hover_animation_time ease-in-out); @include transition(color $button_hover_animation_time ease-in-out, top $button_hover_animation_time ease-in-out, font-size $button_hover_animation_time ease-in-out);
@ -199,8 +199,8 @@ html:root {
color: #3c74a2; color: #3c74a2;
&.type-floating { &.type-floating {
font-size: .75rem; font-size: .75em;
top: 1rem; top: 1em;
} }
} }
} }
@ -211,7 +211,7 @@ html:root {
height: 2.25em; height: 2.25em;
width: 100%; width: 100%;
font-size: 1rem; font-size: 1em;
line-height: 1.5; line-height: 1.5;
color: #cdd1d0; color: #cdd1d0;
@ -226,7 +226,7 @@ html:root {
box-shadow: none; box-shadow: none;
transition: background 0s ease-out; transition: background 0s ease-out;
padding: .4375rem 0; padding: .4375em 0;
@include transition(all .15s ease-in-out); @include transition(all .15s ease-in-out);
@ -248,7 +248,7 @@ html:root {
position: absolute; position: absolute;
opacity: 0; opacity: 0;
width: 100%; width: 100%;
margin-top: .25rem; margin-top: .25em;
font-size: 80%; font-size: 80%;
color: #f44336; color: #f44336;
@ -274,7 +274,7 @@ html:root {
position: absolute; position: absolute;
opacity: 0; opacity: 0;
width: 100%; width: 100%;
margin-top: .25rem; margin-top: .25em;
font-size: .75em; font-size: .75em;

View file

@ -111,6 +111,8 @@ export class BoxedInputField extends React.Component<BoxedInputFieldProperties,
export interface FlatInputFieldProperties { export interface FlatInputFieldProperties {
defaultValue?: string; defaultValue?: string;
value?: string;
placeholder?: string; placeholder?: string;
className?: string; className?: string;
@ -165,6 +167,7 @@ export class FlatInputField extends React.Component<FlatInputFieldProperties, Fl
const disabled = typeof this.state.disabled === "boolean" ? this.state.disabled : typeof this.props.disabled === "boolean" ? this.props.disabled : false; const disabled = typeof this.state.disabled === "boolean" ? this.state.disabled : typeof this.props.disabled === "boolean" ? this.props.disabled : false;
const readOnly = typeof this.state.editable === "boolean" ? !this.state.editable : typeof this.props.editable === "boolean" ? !this.props.editable : false; const readOnly = typeof this.state.editable === "boolean" ? !this.state.editable : typeof this.props.editable === "boolean" ? !this.props.editable : false;
const placeholder = typeof this.state.placeholder === "string" ? this.state.placeholder : typeof this.props.placeholder === "string" ? this.props.placeholder : undefined; const placeholder = typeof this.state.placeholder === "string" ? this.state.placeholder : typeof this.props.placeholder === "string" ? this.props.placeholder : undefined;
return ( return (
<div className={cssStyle.containerFlat + " " + (this.state.isInvalid ? cssStyle.isInvalid : "") + " " + (this.state.filled ? cssStyle.isFilled : "") + " " + (this.props.className || "")}> <div className={cssStyle.containerFlat + " " + (this.state.isInvalid ? cssStyle.isInvalid : "") + " " + (this.state.filled ? cssStyle.isFilled : "") + " " + (this.props.className || "")}>
{this.props.label ? {this.props.label ?
@ -174,6 +177,8 @@ export class FlatInputField extends React.Component<FlatInputFieldProperties, Fl
(this.props.labelFloatingClassName && this.state.filled ? this.props.labelFloatingClassName : "")}>{this.props.label}</label> : undefined} (this.props.labelFloatingClassName && this.state.filled ? this.props.labelFloatingClassName : "")}>{this.props.label}</label> : undefined}
<input <input
defaultValue={this.props.defaultValue} defaultValue={this.props.defaultValue}
value={this.props.value}
type={"text"} type={"text"}
ref={this.refInput} ref={this.refInput}
readOnly={readOnly} readOnly={readOnly}