From 8dce1dd0fdfd04f1a938d88c5bdaecfd431edfcd Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Mon, 28 Sep 2020 04:37:53 +0200 Subject: [PATCH] Fix web interface indents Use project standard of tabs for indents. --- packages/master/web/components/App.jsx | 10 +- packages/master/web/components/data-table.jsx | 460 +++++------ packages/master/web/layout/index.jsx | 266 +++--- packages/master/web/pages/dashboard.jsx | 12 +- .../master/web/pages/instances/instance.jsx | 766 +++++++++--------- .../web/pages/instances/instancesTable.jsx | 76 +- .../pages/permissions/permissionsTable.jsx | 46 +- packages/master/web/pages/roles/role.jsx | 182 ++--- .../master/web/pages/roles/rolesTable.jsx | 72 +- .../master/web/pages/settings/settings.jsx | 140 ++-- .../master/web/pages/slaves/slavesTable.jsx | 46 +- packages/master/web/pages/users/user.jsx | 150 ++-- .../master/web/pages/users/usersTable.jsx | 66 +- packages/master/web/util/notify.jsx | 12 +- packages/master/web/util/websocket.jsx | 80 +- packages/master/web/util/wslink.jsx | 150 ++-- 16 files changed, 1267 insertions(+), 1267 deletions(-) diff --git a/packages/master/web/components/App.jsx b/packages/master/web/components/App.jsx index b1db4c6e..10c155b0 100644 --- a/packages/master/web/components/App.jsx +++ b/packages/master/web/components/App.jsx @@ -5,9 +5,9 @@ import basename from "../basename"; import Layout from "../layout"; export default function App() { - return ( - - - - ); + return ( + + + + ); } diff --git a/packages/master/web/components/data-table.jsx b/packages/master/web/components/data-table.jsx index 7d2a5718..ef2791b5 100644 --- a/packages/master/web/components/data-table.jsx +++ b/packages/master/web/components/data-table.jsx @@ -19,28 +19,28 @@ const { Panel } = Collapse; * RecordIdField - String - By default we assume the column "Id" is a unique identifier for a record. If that isn't the case, supply the column name here */ class DataTable extends Component { - constructor(props) { - super(props); - if (!this.props.DataFunction) throw new Error("DataFunction not defined") - this.state = { - pagination: { - pageSize: 100, - current: 1 - }, - filters: this.props.Filters, - sorter: {}, - tableData: [], - showEditModal: false, - record: {}, - } - } + constructor(props) { + super(props); + if (!this.props.DataFunction) throw new Error("DataFunction not defined") + this.state = { + pagination: { + pageSize: 100, + current: 1 + }, + filters: this.props.Filters, + sorter: {}, + tableData: [], + showEditModal: false, + record: {}, + } + } - componentDidMount() { - this.getData() - } + componentDidMount() { + this.getData() + } - async getData(pagination, filters, sorter) { - /* + async getData(pagination, filters, sorter) { + /* pagination = { pageSize: 10, // items per page current: 1, // page number @@ -51,235 +51,235 @@ class DataTable extends Component { } sorter = {} */ - pagination = pagination || this.state.pagination - filters = filters || this.state.filters - sorter = sorter || this.state.sorter - // console.log(pagination, filters, sorter) + pagination = pagination || this.state.pagination + filters = filters || this.state.filters + sorter = sorter || this.state.sorter + // console.log(pagination, filters, sorter) - let data = await this.props.DataFunction() - // await fetchApi(this.state.dataUrl, "post", { - // database: this.props.Database, - // table: this.props.Table, - // dataSource: this.props.DataSource, - // pagination: this.props.RecordCount? {...pagination, pageSize: this.props.RecordCount, current: 1}:pagination, - // filters, - // sorter, - // recordIdField: this.props.RecordIdField || "Id", // Sort by this - // }) - console.log(data) - data = data || {} - this.setState({ - tableData: this.props.CustomDataFilterFunction ? this.props.CustomDataFilterFunction(data) : data, - pagination: { ...pagination, ...data.pagination }, - sorter, - filters, - }) - } + let data = await this.props.DataFunction() + // await fetchApi(this.state.dataUrl, "post", { + // database: this.props.Database, + // table: this.props.Table, + // dataSource: this.props.DataSource, + // pagination: this.props.RecordCount? {...pagination, pageSize: this.props.RecordCount, current: 1}:pagination, + // filters, + // sorter, + // recordIdField: this.props.RecordIdField || "Id", // Sort by this + // }) + console.log(data) + data = data || {} + this.setState({ + tableData: this.props.CustomDataFilterFunction ? this.props.CustomDataFilterFunction(data) : data, + pagination: { ...pagination, ...data.pagination }, + sorter, + filters, + }) + } - showEditModal(record, index) { - if (!this.state.showEditModal) - this.setState({ - record: record, - showEditModal: true, - }) - } - hideEditModal() { - this.setState({ - showEditModal: false, - inserting: false, - record: {} - }) - } - async onEditFinish(values) { - console.log("Finished editing", values) + showEditModal(record, index) { + if (!this.state.showEditModal) + this.setState({ + record: record, + showEditModal: true, + }) + } + hideEditModal() { + this.setState({ + showEditModal: false, + inserting: false, + record: {} + }) + } + async onEditFinish(values) { + console.log("Finished editing", values) - if (this.state.inserting) { // Create new record - var status = {} - await this.props.AddRecord.insert(values) - } else { // Edit existing record, capable of doing sparse updates - var status = {} - await this.props.Editable.insert(values) - } - this.setState({ - showEditModal: false, - inserting: false, - record: {}, - }) - // Force refresh of data - this.getData() - } - async deleteRecord(record) { - delete record.key - // Delete "null" values as they seem to cause deletes to fail silently when the value is null and field type is float - for (let key in record) { - if (record[key] === null) delete record[key] - } - var status = {} - // await fetchApi(`/api/${this.props.Server}/tableData/record`, "delete", { - // database: this.props.Database, - // table: this.props.Table, - // dataSource: this.props.DataSource, - // record, - // }, undefined, true) + if (this.state.inserting) { // Create new record + var status = {} + await this.props.AddRecord.insert(values) + } else { // Edit existing record, capable of doing sparse updates + var status = {} + await this.props.Editable.insert(values) + } + this.setState({ + showEditModal: false, + inserting: false, + record: {}, + }) + // Force refresh of data + this.getData() + } + async deleteRecord(record) { + delete record.key + // Delete "null" values as they seem to cause deletes to fail silently when the value is null and field type is float + for (let key in record) { + if (record[key] === null) delete record[key] + } + var status = {} + // await fetchApi(`/api/${this.props.Server}/tableData/record`, "delete", { + // database: this.props.Database, + // table: this.props.Table, + // dataSource: this.props.DataSource, + // record, + // }, undefined, true) - console.log("Deleted record", status) + console.log("Deleted record", status) - if (status.ok) notify("success", status.msg, "success") - if (!status.ok) notify("error", status.msg, "error") + if (status.ok) notify("success", status.msg, "success") + if (!status.ok) notify("error", status.msg, "error") - // Force refresh of data - this.getData() - } - render() { - let tableProps = { - ...this.props.TableProps || {}, - onRow: (record, rowIndex) => { - /* + // Force refresh of data + this.getData() + } + render() { + let tableProps = { + ...this.props.TableProps || {}, + onRow: (record, rowIndex) => { + /* To allow for extending functionality, we take a TableProps argument from props and pass it through to the Table component. Since we are also using onRow internaly here, we handle the externally provided events ourselves by passing along the event object. This way the end user isn't affected by our event handlers. */ - let externalOnRow = { - ...(this.props.TableProps && this.props.TableProps.onRow && this.props.TableProps.onRow(record, rowIndex)), - } - return { - onClick: event => { - if (event.target.type !== "button") { - console.log("onRow", record, rowIndex) - if (this.props.Editable) this.showEditModal(record, rowIndex) - if (externalOnRow.onClick) externalOnRow.onClick(event) - } - }, - onDoubleClick: event => { - if (externalOnRow.onDoubleClick) externalOnRow.onDoubleClick(event) - }, - onContextMenu: event => { - if (externalOnRow.onContextMenu) externalOnRow.onContextMenu(event) - }, - onMouseEnter: event => { - if (externalOnRow.onMouseEnter) externalOnRow.onMouseEnter(event) - }, - onMouseLeave: event => { - if (externalOnRow.onMouseLeave) externalOnRow.onMouseLeave(event) - }, - } - } - } - let columns = this.props.columns || this.inferColumns(this.state.tableData) - if (this.props.DeleteRecord && !columns.find(x => x.dataIndex === "notInUse")) columns.push({ - // Add delete button on the right - dataIndex: "notInUse", - title: "", - render: (text, record) => { - this.deleteRecord(record) - }} - > + let externalOnRow = { + ...(this.props.TableProps && this.props.TableProps.onRow && this.props.TableProps.onRow(record, rowIndex)), + } + return { + onClick: event => { + if (event.target.type !== "button") { + console.log("onRow", record, rowIndex) + if (this.props.Editable) this.showEditModal(record, rowIndex) + if (externalOnRow.onClick) externalOnRow.onClick(event) + } + }, + onDoubleClick: event => { + if (externalOnRow.onDoubleClick) externalOnRow.onDoubleClick(event) + }, + onContextMenu: event => { + if (externalOnRow.onContextMenu) externalOnRow.onContextMenu(event) + }, + onMouseEnter: event => { + if (externalOnRow.onMouseEnter) externalOnRow.onMouseEnter(event) + }, + onMouseLeave: event => { + if (externalOnRow.onMouseLeave) externalOnRow.onMouseLeave(event) + }, + } + } + } + let columns = this.props.columns || this.inferColumns(this.state.tableData) + if (this.props.DeleteRecord && !columns.find(x => x.dataIndex === "notInUse")) columns.push({ + // Add delete button on the right + dataIndex: "notInUse", + title: "", + render: (text, record) => { + this.deleteRecord(record) + }} + > Slett permanent - - } - trigger="click" - > - - - }) + + } + trigger="click" + > + + + }) - return <> - - - - { - return { - ...x, // Add a 4th parameter to the stock render function with all of our table data - render: x.render ? (...originalParams) => x.render(...originalParams, this.state.tableData) : undefined - } - })} - dataSource={this.state.tableData} - pagination={this.state.pagination.total > 10 ? this.state.pagination : false} - onChange={this.getData.bind(this)} - /> - {this.props.AddRecord && } - - {this.state.inserting ? "Legg til" : "Rediger"} - } - > - {this.state.showEditModal &&
- { + +
{ + return { + ...x, // Add a 4th parameter to the stock render function with all of our table data + render: x.render ? (...originalParams) => x.render(...originalParams, this.state.tableData) : undefined + } + })} + dataSource={this.state.tableData} + pagination={this.state.pagination.total > 10 ? this.state.pagination : false} + onChange={this.getData.bind(this)} + /> + {this.props.AddRecord && } + + {this.state.inserting ? "Legg til" : "Rediger"} + } + > + {this.state.showEditModal && + { - ( - (this.state.inserting && this.props.AddRecord && this.props.AddRecord.fields) // Use externally supplied form input fields + ( + (this.state.inserting && this.props.AddRecord && this.props.AddRecord.fields) // Use externally supplied form input fields || this.props.columns.filter && this.props.columns.filter(x => x.dataIndex !== "notInUse") // Generate input fields from external columns || this.inferColumns(this.state.tableData)).map(col => { // Generate input fields from autogenerated columns (only works with existing data) - console.log(this.state.record) - return - {col.renderEdit && col.renderEdit(this.state.record[col.dataIndex], this.state.record, undefined /* Non spec compliant, is supposed to be index of record */, this.state.tableData) || } - - }) - } - - - - } - - - - } - inferColumns(data) { - // Look at the data and find columns and how to display them. Can be overridden by props.Columns if more customization is needed - let columns = [] - data.forEach(row => { - Object.keys(row).filter(x => x !== "key").forEach(key => { - let existing = columns.find(col => col.key === key) - if (!existing) { - columns.push({ - key: key, - title: key, - dataIndex: key, - }) - } - }) - }) - return columns - } + console.log(this.state.record) + return + {col.renderEdit && col.renderEdit(this.state.record[col.dataIndex], this.state.record, undefined /* Non spec compliant, is supposed to be index of record */, this.state.tableData) || } + + }) + } + + + + } + + + + } + inferColumns(data) { + // Look at the data and find columns and how to display them. Can be overridden by props.Columns if more customization is needed + let columns = [] + data.forEach(row => { + Object.keys(row).filter(x => x !== "key").forEach(key => { + let existing = columns.find(col => col.key === key) + if (!existing) { + columns.push({ + key: key, + title: key, + dataIndex: key, + }) + } + }) + }) + return columns + } } export default DataTable; diff --git a/packages/master/web/layout/index.jsx b/packages/master/web/layout/index.jsx index 4893ccd9..5a2900ca 100644 --- a/packages/master/web/layout/index.jsx +++ b/packages/master/web/layout/index.jsx @@ -19,148 +19,148 @@ const { SubMenu } = Menu; class SiteLayout extends Component { - constructor(props) { - super(props); - const { location } = props; + constructor(props) { + super(props); + const { location } = props; - this.state = { - collapsed: false, - setcollapsed: false, - tags: [], - setTags: [], - location, - siteSettings: {}, - factoryModel: [] - }; - } + this.state = { + collapsed: false, + setcollapsed: false, + tags: [], + setTags: [], + location, + siteSettings: {}, + factoryModel: [] + }; + } - onCollapse() { - this.setState({ collapsed: !this.state.collapsed }) - } + onCollapse() { + this.setState({ collapsed: !this.state.collapsed }) + } - titleCase(text) { - return text.substring(0, 1).toUpperCase() + text.substring(1); - } + titleCase(text) { + return text.substring(0, 1).toUpperCase() + text.substring(1); + } - replaceParametersInUrl({ endpoint, params }) { - let path = endpoint; - console.log("endpoint", params) - Object.keys(params).forEach(key => { - path = path.replace(":" + key, params[key]) - }) + replaceParametersInUrl({ endpoint, params }) { + let path = endpoint; + console.log("endpoint", params) + Object.keys(params).forEach(key => { + path = path.replace(":" + key, params[key]) + }) - return path; - } + return path; + } - render() { - return ( - - {document.location.search !== "?hideExtras" ? ( - -

-
- {" "} - {this.state.collapsed ? ( - - ) : ( - - )} -
-

-

+ render() { + return ( + + {document.location.search !== "?hideExtras" ? ( + +

+
+ {" "} + {this.state.collapsed ? ( + + ) : ( + + )} +
+

+

- { - let x = this.state.location.pathname.split("/"); - x.shift(); - return x; - })()} - mode="inline" - > - - Slaves - - - - Instances - - - - Users - - - - Roles - - - - Permissions - - - - Settings - - - -
- ) : ( - "" - )} - - - - - - - - - - - - - - - -
+ { + let x = this.state.location.pathname.split("/"); + x.shift(); + return x; + })()} + mode="inline" + > + + Slaves + + + + Instances + + + + Users + + + + Roles + + + + Permissions + + + + Settings + + + + + ) : ( + "" + )} + + + + + + + + + + + + + + + +
Clusterio 2.0 web interface https://github.com/clusterio -
-
- - ); - } +
+
+
+ ); + } } export default withRouter(SiteLayout); diff --git a/packages/master/web/pages/dashboard.jsx b/packages/master/web/pages/dashboard.jsx index 059a6d69..7fcf6c94 100644 --- a/packages/master/web/pages/dashboard.jsx +++ b/packages/master/web/pages/dashboard.jsx @@ -1,10 +1,10 @@ import React, {Component} from "react" export class Dashboard extends Component { - constructor(props){ - super(props) - } - render(){ - return

Dashboard

- } + constructor(props){ + super(props) + } + render(){ + return

Dashboard

+ } } \ No newline at end of file diff --git a/packages/master/web/pages/instances/instance.jsx b/packages/master/web/pages/instances/instance.jsx index d5d51cb6..81024e50 100644 --- a/packages/master/web/pages/instances/instance.jsx +++ b/packages/master/web/pages/instances/instance.jsx @@ -1,17 +1,17 @@ import React, { Component } from "react" import { Card, Button, Popover, Select, Divider, Input, Form, Col, Row, Checkbox, Space } from "antd" import { - listSlaves, - listInstances, - startInstance, - stopInstance, - setInstanceOutputSubscriptions, - deleteInstance, - assignInstance, - createSave, - getInstanceConfig, - setInstanceConfigField, - sendRcon, + listSlaves, + listInstances, + startInstance, + stopInstance, + setInstanceOutputSubscriptions, + deleteInstance, + assignInstance, + createSave, + getInstanceConfig, + setInstanceConfigField, + sendRcon, } from "../../util/wslink" import DataTable from "../../components/data-table" import notify from "../../util/notify" @@ -22,208 +22,208 @@ import PlusOutlined from "@ant-design/icons/PlusOutlined" const { Option } = Select export class InstanceView extends Component { - constructor(props) { - super(props) - this.state = { - instance: {}, - slaves: [], - logLines: [{ message: "Logviewer. Follows the latest logs if you scroll to the bottom. Does not store logs past the lifetime of this tab" }], - } - this.messagesEndRef = React.createRef() - } - navigate(url) { - this.props.history.push(url); - } - async componentDidMount() { - let id = this.props.match.params.id + constructor(props) { + super(props) + this.state = { + instance: {}, + slaves: [], + logLines: [{ message: "Logviewer. Follows the latest logs if you scroll to the bottom. Does not store logs past the lifetime of this tab" }], + } + this.messagesEndRef = React.createRef() + } + navigate(url) { + this.props.history.push(url); + } + async componentDidMount() { + let id = this.props.match.params.id - await this.getData() + await this.getData() - await setInstanceOutputSubscriptions({ - instance_id: Number(id), - }) - window.instanceOutputEventHandler = ({ instance_id, output }) => { - if (instance_id === Number(id)) { - this.setState({ - logLines: [...this.state.logLines, output], - }) - } - // Automatically scroll to bottom on new line. - // this.messagesEndRef.current.scrollIntoView({ behavior: 'smooth' }) - } - } - async getData() { - let id = this.props.match.params.id + await setInstanceOutputSubscriptions({ + instance_id: Number(id), + }) + window.instanceOutputEventHandler = ({ instance_id, output }) => { + if (instance_id === Number(id)) { + this.setState({ + logLines: [...this.state.logLines, output], + }) + } + // Automatically scroll to bottom on new line. + // this.messagesEndRef.current.scrollIntoView({ behavior: 'smooth' }) + } + } + async getData() { + let id = this.props.match.params.id - let instances = await listInstances() - let slaves = await listSlaves() + let instances = await listInstances() + let slaves = await listSlaves() - this.setState({ - instance: instances.find(x => x.id === Number(id)), - slaves, - }) + this.setState({ + instance: instances.find(x => x.id === Number(id)), + slaves, + }) - let config = await getInstanceConfig({ instance_id: Number(id) }) - console.log(config) - this.setState({ - config - }) - } - async start() { - this.setState({ - starting: true, - }) - try { - await startInstance({ - instance_id: this.state.instance.id, - save: null, - }) - } catch (e) { - notify("Error starting instance", "error", e.message) - return this.setState({ - starting: false, - }) - } - notify("Instance started") - this.setState({ - starting: false, - }) - this.getData() - } - async stop() { - this.setState({ - stopping: true, - }) - try { - await stopInstance({ - instance_id: this.state.instance.id, - }) - } catch (e) { - notify("Error stopping instance", "error", e.message) - return this.setState({ - stopping: false, - }) - } - notify("Instance stopped") - this.setState({ - stopping: false, - }) - this.getData() - } - async createSave() { - this.setState({ - creatingSave: true, - }) - try { - await createSave({ - instance_id: this.state.instance.id, - }) - } catch (e) { - notify("Error creating save", "error", e.message) - return this.setState({ - creatingSave: false, - }) - } - notify("Save created", "success") - this.setState({ - creatingSave: false, - }) - } - async onConfigEditFinish(values) { - console.log("Completed config edit with", values) - for (let k in values) { - if (values[k] !== this.getInstanceConfigAsKvObject(this.state.config)[k]) { - let value = values[k] - if (typeof value === "boolean") value = value.toString() - console.log("Setting", k, value) - await setInstanceConfigField({ - instance_id: this.state.instance.id, - field: k, - value: value, - }) - } - } - notify("Set configuration fields", "success") - this.setState({ - editingConfig: false - }) - this.getData() - } - render() { - console.log(this.state) - let { instance, slaves } = this.state - let slave = slaves && slaves.find(x => x.id === instance.assigned_slave); - return -

{instance.name}

-

ID: {instance.id}

-

Slave: {slave && slave.name}

- {instance.status !== "running" && } - {instance.status !== "stopped" && } + {instance.status !== "stopped" && } - {instance.status !== "running" && } + {instance.status !== "running" && } - { - let result = await assignInstance({ instance_id: instance.id, slave_id: newSlaveId }) - notify("Assigned to slave", "success") - this.getData() - }} - > - {this.state.slaves.map(slave => )} - - } - trigger="click" - type={instance.status === "unassigned" ? "primary" : "default"} - > - } + { + let result = await assignInstance({ instance_id: instance.id, slave_id: newSlaveId }) + notify("Assigned to slave", "success") + this.getData() + }} + > + {this.state.slaves.map(slave => )} + + } + trigger="click" + type={instance.status === "unassigned" ? "primary" : "default"} + > + - - { - await deleteInstance({ instance_id: instance.id }); - notify("Deleted instance " + instance.id, "success") - this.navigate("/instances") - }} - > + + + { + await deleteInstance({ instance_id: instance.id }); + notify("Deleted instance " + instance.id, "success") + this.navigate("/instances") + }} + > Delete this instance permanently - - } - trigger="click" - > - - - -
- {this.state.logLines.map(item =>

{item.time} {item.level} {item.file}: {item.message}

)} -
-
- {/* rcon input field */} -
{ - await sendRcon({ instance_id: instance.id, command: values.command }) - }} - > - - - - - {this.state.config && this.renderConfig(this.state.config)} -
- } - getInstanceConfigAsKvObject(config) { - let object = {} - for (let group of config.serialized_config.groups) { - for (let fieldName in group.fields) { - object[group.name + "." + fieldName] = group.fields[fieldName] - } - } - return object - } - renderConfig(config) { - const layout = { - labelCol: { - span: 6, - }, - wrapperCol: { - span: 14, - }, - }; - const tailLayout = { - wrapperCol: { - offset: 6, - span: 14, - }, - }; - return -
- {this.state.editingConfig ? - - - - : - - } - - {config && config.serialized_config.groups.map(group => <> -
- {group.name} - {/* {Object.keys(group.fields).map(field => <> + + + : + + } + + {config && config.serialized_config.groups.map(group => <> + + {group.name} + {/* {Object.keys(group.fields).map(field => <> {field}: {JSON.stringify(group.fields[field])}
)} */} - {console.log(group)} - {Object.keys(group.fields).map(field => )} - - )} - - - - } + {console.log(group)} + {Object.keys(group.fields).map(field => )} + + )} + + + + } } function renderDisplayField(value) { - if (typeof value === "object") { - return JSON.stringify(value) - } - if (typeof value === "boolean") { - return - } - return value.toString() + if (typeof value === "object") { + return JSON.stringify(value) + } + if (typeof value === "boolean") { + return + } + return value.toString() } function renderFormField(value) { - if (typeof value === "object") { - return - } - if (typeof value === "boolean") { - return - } - return + if (typeof value === "object") { + return + } + if (typeof value === "boolean") { + return + } + return } class ObjectInput extends Component { - constructor(props) { - super(props) - console.log(this.props) - /* + constructor(props) { + super(props) + console.log(this.props) + /* value: { auto_pause: false, tags: ["clusterio"] @@ -351,89 +351,89 @@ class ObjectInput extends Component { id: "factorio.settings", onChange: f() */ - this.state = {} - } - onChange(e, key) { - if (e.target.type === "checkbox") { - // if (e.target.checked !== undefined) { - // Its a checkbox, set value to true/false - let value = { ...this.props.value } - value[key] = e.target.checked || false - this.props.onChange(value) - } else if (e.target.type === "text") { - // } else if (e.target.value !== undefined) { - // its probably a text input - let value = { ...this.props.value } - value[key] = e.target.value || "" - this.props.onChange(value) - } - } - render() { - let { value } = this.props - let ret = [] - for (let key in value) { - if (typeof value[key] === "boolean") { - ret.push( this.onChange(e, key)} - > - {key} - - ) - } else if (typeof value[key] === "string") { - ret.push(
{key} this.onChange(e, key)} - />
- ) - } - } - ret.push( - this.setState({ newInput: e.target.value })} /> - - } - trigger="click" - visible={this.state.addPopoverVisible} - handleVisibleChange={visible => this.setState({ addPopoverVisible: visible })} - > - - ) - return {ret} - } + this.state = {} + } + onChange(e, key) { + if (e.target.type === "checkbox") { + // if (e.target.checked !== undefined) { + // Its a checkbox, set value to true/false + let value = { ...this.props.value } + value[key] = e.target.checked || false + this.props.onChange(value) + } else if (e.target.type === "text") { + // } else if (e.target.value !== undefined) { + // its probably a text input + let value = { ...this.props.value } + value[key] = e.target.value || "" + this.props.onChange(value) + } + } + render() { + let { value } = this.props + let ret = [] + for (let key in value) { + if (typeof value[key] === "boolean") { + ret.push( this.onChange(e, key)} + > + {key} + + ) + } else if (typeof value[key] === "string") { + ret.push(
{key} this.onChange(e, key)} + />
+ ) + } + } + ret.push( + this.setState({ newInput: e.target.value })} /> + + } + trigger="click" + visible={this.state.addPopoverVisible} + handleVisibleChange={visible => this.setState({ addPopoverVisible: visible })} + > + + ) + return {ret} + } } class ConfigFormItem extends Component { - constructor(props) { - super(props) - } - render() { - let { field, group, editingConfig } = this.props - return - {editingConfig ? - renderFormField(group.fields[field]) - : - renderDisplayField(group.fields[field]) - } - - } + constructor(props) { + super(props) + } + render() { + let { field, group, editingConfig } = this.props + return + {editingConfig ? + renderFormField(group.fields[field]) + : + renderDisplayField(group.fields[field]) + } + + } } diff --git a/packages/master/web/pages/instances/instancesTable.jsx b/packages/master/web/pages/instances/instancesTable.jsx index 21a86e15..d73e4f88 100644 --- a/packages/master/web/pages/instances/instancesTable.jsx +++ b/packages/master/web/pages/instances/instancesTable.jsx @@ -5,42 +5,42 @@ import DataTable from "../../components/data-table" const config = require("@clusterio/lib/config") export class InstancesTable extends Component { - constructor(props) { - super(props) - } - navigate(url) { - this.props.history.push(url); - } - render() { - return -

Instances

- { - let instanceConfig = new config.InstanceConfig(); - await instanceConfig.init(); - console.log("Base config", instanceConfig) - instanceConfig.set("instance.name", args.name); - let serialized_config = instanceConfig.serialize(); - let response = await createInstance(serialized_config) - console.log("Created instance", response) - } - }} - DataFunction={listInstances} - TableProps={{ - onRow: (record, rowIndex) => { - return { - onClick: event => { - this.navigate(`/instances/${record.id}/view`) - } - } - } - }} - /> -
- } + constructor(props) { + super(props) + } + navigate(url) { + this.props.history.push(url); + } + render() { + return +

Instances

+ { + let instanceConfig = new config.InstanceConfig(); + await instanceConfig.init(); + console.log("Base config", instanceConfig) + instanceConfig.set("instance.name", args.name); + let serialized_config = instanceConfig.serialize(); + let response = await createInstance(serialized_config) + console.log("Created instance", response) + } + }} + DataFunction={listInstances} + TableProps={{ + onRow: (record, rowIndex) => { + return { + onClick: event => { + this.navigate(`/instances/${record.id}/view`) + } + } + } + }} + /> +
+ } } diff --git a/packages/master/web/pages/permissions/permissionsTable.jsx b/packages/master/web/pages/permissions/permissionsTable.jsx index eb63f893..8bcf995c 100644 --- a/packages/master/web/pages/permissions/permissionsTable.jsx +++ b/packages/master/web/pages/permissions/permissionsTable.jsx @@ -4,27 +4,27 @@ import { listSlaves, listInstances, listPermissions } from "../../util/wslink" import DataTable from "../../components/data-table" export class PermissionsTable extends Component { - constructor(props) { - super(props) - } - navigate(url) { - this.props.history.push(url); - } - render() { - return -

Permissions

- { - return { - onClick: event => { - this.navigate(`/permissions/${record.id}/view`) - } - } - } - }} - /> -
- } + constructor(props) { + super(props) + } + navigate(url) { + this.props.history.push(url); + } + render() { + return +

Permissions

+ { + return { + onClick: event => { + this.navigate(`/permissions/${record.id}/view`) + } + } + } + }} + /> +
+ } } diff --git a/packages/master/web/pages/roles/role.jsx b/packages/master/web/pages/roles/role.jsx index 7634e616..625a25e0 100644 --- a/packages/master/web/pages/roles/role.jsx +++ b/packages/master/web/pages/roles/role.jsx @@ -4,23 +4,23 @@ import { Card, Button, Popover, Select, Transfer } from "antd" import DeleteOutlined from "@ant-design/icons/DeleteOutlined" import { - listSlaves, - listInstances, - startInstance, - stopInstance, - setInstanceOutputSubscriptions, - deleteInstance, - assignInstance, - createSave, - getInstanceConfig, - setInstanceConfigField, - sendRcon, - deleteUser, - listUsers, - listRoles, - setRoles, - listPermissions, - updateRole, + listSlaves, + listInstances, + startInstance, + stopInstance, + setInstanceOutputSubscriptions, + deleteInstance, + assignInstance, + createSave, + getInstanceConfig, + setInstanceConfigField, + sendRcon, + deleteUser, + listUsers, + listRoles, + setRoles, + listPermissions, + updateRole, } from "../../util/wslink" import DataTable from "../../components/data-table" import notify from "../../util/notify" @@ -28,86 +28,86 @@ import notify from "../../util/notify" const { Option } = Select export class RoleView extends Component { - constructor(props) { - super(props) - this.state = { - role: {} - } - this.messagesEndRef = React.createRef() - } - navigate(url) { - this.props.history.push(url); - } - async componentDidMount() { - await this.getData() - } - async getData() { - let id = this.props.match.params.id + constructor(props) { + super(props) + this.state = { + role: {} + } + this.messagesEndRef = React.createRef() + } + navigate(url) { + this.props.history.push(url); + } + async componentDidMount() { + await this.getData() + } + async getData() { + let id = this.props.match.params.id - let roles = await listRoles() - let permissions = await listPermissions() + let roles = await listRoles() + let permissions = await listPermissions() - this.setState({ - role: roles.find(x => x.id === Number(id)), - permissions, - }) - } - async handleChange(targetKeys) { - this.setState({ - role: { - ...this.state.role, - permissions: targetKeys - } - }); - let response = await updateRole({ - ...this.state.role, - permissions: targetKeys, - }) - console.log("Updated user roles", response) - } - render() { - console.log(this.state) - let { role, permissions } = this.state - return - { - await deleteUser({ role: role.name }) - notify("Deleted role " + role.name, "success") - this.navigate("/roles") - }} - > + this.setState({ + role: roles.find(x => x.id === Number(id)), + permissions, + }) + } + async handleChange(targetKeys) { + this.setState({ + role: { + ...this.state.role, + permissions: targetKeys + } + }); + let response = await updateRole({ + ...this.state.role, + permissions: targetKeys, + }) + console.log("Updated user roles", response) + } + render() { + console.log(this.state) + let { role, permissions } = this.state + return + { + await deleteUser({ role: role.name }) + notify("Deleted role " + role.name, "success") + this.navigate("/roles") + }} + > Delete this role permanently - - } - trigger="click" - > - - -

{role.name}

-

Assign roles

- - option.name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1} - targetKeys={role.permissions} - onChange={this.handleChange.bind(this)} - render={item => item.name} - /> -
- } + + option.name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1} + targetKeys={role.permissions} + onChange={this.handleChange.bind(this)} + render={item => item.name} + /> +
+ } } diff --git a/packages/master/web/pages/roles/rolesTable.jsx b/packages/master/web/pages/roles/rolesTable.jsx index 4e0f0f2a..6dd3af92 100644 --- a/packages/master/web/pages/roles/rolesTable.jsx +++ b/packages/master/web/pages/roles/rolesTable.jsx @@ -4,40 +4,40 @@ import { listSlaves, listInstances, listRoles, createRole } from "../../util/wsl import DataTable from "../../components/data-table" export class RolesTable extends Component { - constructor(props) { - super(props) - } - navigate(url) { - this.props.history.push(url); - } - render() { - return -

Roles

- { - let response = await createRole({name: args.name, description: args.description}) - console.log("Created role",response) - } - }} - DataFunction={listRoles} - TableProps={{ - onRow: (record, rowIndex) => { - return { - onClick: event => { - this.navigate(`/roles/${record.id}/view`) - } - } - } - }} - /> -
- } + constructor(props) { + super(props) + } + navigate(url) { + this.props.history.push(url); + } + render() { + return +

Roles

+ { + let response = await createRole({name: args.name, description: args.description}) + console.log("Created role",response) + } + }} + DataFunction={listRoles} + TableProps={{ + onRow: (record, rowIndex) => { + return { + onClick: event => { + this.navigate(`/roles/${record.id}/view`) + } + } + } + }} + /> +
+ } } diff --git a/packages/master/web/pages/settings/settings.jsx b/packages/master/web/pages/settings/settings.jsx index d4fcf35d..e725d01b 100644 --- a/packages/master/web/pages/settings/settings.jsx +++ b/packages/master/web/pages/settings/settings.jsx @@ -2,80 +2,80 @@ import React, { Component } from "react" import { Card, Button, Input, Form } from "antd" const layout = { - labelCol: { - span: 4, - }, - wrapperCol: { - span: 16, - }, + labelCol: { + span: 4, + }, + wrapperCol: { + span: 16, + }, }; const tailLayout = { - wrapperCol: { - offset: 4, - span: 16, - }, + wrapperCol: { + offset: 4, + span: 16, + }, }; export class Settings extends Component { - constructor(props) { - super(props) - this.state = { - role: {} - } - } - navigate(url) { - this.props.history.push(url); - } - render() { - console.log(this.state) - return -

Web interface settings

-
{ - console.log("Saving settings",values) - for(let key of Object.keys(values)){ - localStorage.setItem(key, values[key].replace("https://", "wss://").replace("http://", "ws://")) - } - // Force refresh to apply changes - document.location = document.location - }} - > - - - - - - - - - - -
- } + + + + + } } diff --git a/packages/master/web/pages/slaves/slavesTable.jsx b/packages/master/web/pages/slaves/slavesTable.jsx index a2744e55..f0450be1 100644 --- a/packages/master/web/pages/slaves/slavesTable.jsx +++ b/packages/master/web/pages/slaves/slavesTable.jsx @@ -4,27 +4,27 @@ import { listSlaves, listInstances } from "../../util/wslink" import DataTable from "../../components/data-table" export class SlavesTable extends Component { - constructor(props) { - super(props) - } - navigate(url) { - this.props.history.push(url); - } - render() { - return -

Slaves

- { - return { - onClick: event => { - this.navigate(`/slaves/${record.id}/view`) - } - } - } - }} - /> -
- } + constructor(props) { + super(props) + } + navigate(url) { + this.props.history.push(url); + } + render() { + return +

Slaves

+ { + return { + onClick: event => { + this.navigate(`/slaves/${record.id}/view`) + } + } + } + }} + /> +
+ } } diff --git a/packages/master/web/pages/users/user.jsx b/packages/master/web/pages/users/user.jsx index 819ecec9..9989ab27 100644 --- a/packages/master/web/pages/users/user.jsx +++ b/packages/master/web/pages/users/user.jsx @@ -1,10 +1,10 @@ import React, { Component } from "react" import { Card, Button, Popover, Select, Transfer } from "antd"; import { - deleteUser, - listUsers, - listRoles, - setRoles, + deleteUser, + listUsers, + listRoles, + setRoles, } from "../../util/wslink" import DataTable from "../../components/data-table" import notify from "../../util/notify" @@ -13,78 +13,78 @@ import DeleteOutlined from "@ant-design/icons/DeleteOutlined" const { Option } = Select export class UserView extends Component { - constructor(props) { - super(props) - this.state = { - user: {} - } - this.messagesEndRef = React.createRef(); - } - navigate(url) { - this.props.history.push(url); - } - async componentDidMount() { - await this.getData() - } - async getData() { - let name = this.props.match.params.id + constructor(props) { + super(props) + this.state = { + user: {} + } + this.messagesEndRef = React.createRef(); + } + navigate(url) { + this.props.history.push(url); + } + async componentDidMount() { + await this.getData() + } + async getData() { + let name = this.props.match.params.id - let users = await listUsers() - let roles = await listRoles() + let users = await listUsers() + let roles = await listRoles() - this.setState({ - user: users.find(x => x.name === name), - roles, - }) - } - async handleChange(targetKeys) { - this.setState({ - user: { - ...this.state.user, - roles: targetKeys - } - }); - let response = await setRoles({ - name: this.state.user.name, - roles: targetKeys, - }) - console.log("Updated user roles",response) - }; - render() { - console.log(this.state) - let { user, roles } = this.state - return -

{user.name}

-

Assign roles

- option.name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1} - targetKeys={user.roles} - onChange={this.handleChange.bind(this)} - render={item => item.name} - /> - { - await deleteUser({ name: user.name }) - notify("Deleted user " + user.name, "success") - this.navigate("/users") - }} - > + this.setState({ + user: users.find(x => x.name === name), + roles, + }) + } + async handleChange(targetKeys) { + this.setState({ + user: { + ...this.state.user, + roles: targetKeys + } + }); + let response = await setRoles({ + name: this.state.user.name, + roles: targetKeys, + }) + console.log("Updated user roles",response) + }; + render() { + console.log(this.state) + let { user, roles } = this.state + return +

{user.name}

+

Assign roles

+ option.name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1} + targetKeys={user.roles} + onChange={this.handleChange.bind(this)} + render={item => item.name} + /> + { + await deleteUser({ name: user.name }) + notify("Deleted user " + user.name, "success") + this.navigate("/users") + }} + > Delete this user from the cluster - - } - trigger="click" - > - - -
- } + + } + trigger="click" + > + +
+
+ } } diff --git a/packages/master/web/pages/users/usersTable.jsx b/packages/master/web/pages/users/usersTable.jsx index 7a1a253c..7f22e4a1 100644 --- a/packages/master/web/pages/users/usersTable.jsx +++ b/packages/master/web/pages/users/usersTable.jsx @@ -4,37 +4,37 @@ import { listSlaves, listInstances, listUsers, createUser } from "../../util/wsl import DataTable from "../../components/data-table" export class UsersTable extends Component { - constructor(props) { - super(props) - } - navigate(url) { - this.props.history.push(url); - } - render() { - return -

Slaves

- { - let response = await createUser({name: args.name}) - console.log("Created user",response) - } - }} - DataFunction={listUsers} - TableProps={{ - onRow: (record, rowIndex) => { - return { - onClick: event => { - this.navigate(`/users/${record.name}/view`) - } - } - } - }} - /> -
- } + constructor(props) { + super(props) + } + navigate(url) { + this.props.history.push(url); + } + render() { + return +

Slaves

+ { + let response = await createUser({name: args.name}) + console.log("Created user",response) + } + }} + DataFunction={listUsers} + TableProps={{ + onRow: (record, rowIndex) => { + return { + onClick: event => { + this.navigate(`/users/${record.name}/view`) + } + } + } + }} + /> +
+ } } diff --git a/packages/master/web/util/notify.jsx b/packages/master/web/util/notify.jsx index 8df6b7c5..40801c98 100644 --- a/packages/master/web/util/notify.jsx +++ b/packages/master/web/util/notify.jsx @@ -6,10 +6,10 @@ import { notification } from "antd"; * @param {("info"|"error"|"success"|"warning"|"warn")} type */ export default function notify(message, type = "info", description) { - notification[type]({ - message: typeof message === "string" ? message : "ERROR: See console", - description, - placement: "bottomRight", - }); - if (typeof message !== "string") console.error(message) + notification[type]({ + message: typeof message === "string" ? message : "ERROR: See console", + description, + placement: "bottomRight", + }); + if (typeof message !== "string") console.error(message) } diff --git a/packages/master/web/util/websocket.jsx b/packages/master/web/util/websocket.jsx index a0a2e8e4..08fb435c 100644 --- a/packages/master/web/util/websocket.jsx +++ b/packages/master/web/util/websocket.jsx @@ -36,19 +36,19 @@ function formatOutput(output) { * @private */ export class ControlConnector extends link.WebSocketClientConnector { - constructor(url, reconnectDelay, token) { - super(url, reconnectDelay); - this._token = token; - } + constructor(url, reconnectDelay, token) { + super(url, reconnectDelay); + this._token = token; + } - register() { - console.log("SOCKET | registering control"); - this.sendHandshake("register_control", { - token: this._token, - agent: "web", - version: "2.0.0-alpha", - }); - } + register() { + console.log("SOCKET | registering control"); + this.sendHandshake("register_control", { + token: this._token, + agent: "web", + version: "2.0.0-alpha", + }); + } } /** @@ -58,41 +58,41 @@ export class ControlConnector extends link.WebSocketClientConnector { * @static */ export class Control extends link.Link { - constructor(connector, controlPlugins) { - super("control", "master", connector); - link.attachAllMessages(this); + constructor(connector, controlPlugins) { + super("control", "master", connector); + link.attachAllMessages(this); - /** + /** * Mapping of plugin names to their instance for loaded plugins. * @type {Map} */ - this.plugins = controlPlugins; - for (let controlPlugin of controlPlugins.values()) { - plugin.attachPluginMessages(this, controlPlugin.info, controlPlugin); - } - } + this.plugins = controlPlugins; + for (let controlPlugin of controlPlugins.values()) { + plugin.attachPluginMessages(this, controlPlugin.info, controlPlugin); + } + } - async instanceOutputEventHandler(message) { - let { instance_id, output } = message.data; - console.log(formatOutput(output)); - window.instanceOutputEventHandler && window.instanceOutputEventHandler({instance_id, output}) - } + async instanceOutputEventHandler(message) { + let { instance_id, output } = message.data; + console.log(formatOutput(output)); + window.instanceOutputEventHandler && window.instanceOutputEventHandler({instance_id, output}) + } - async debugWsMessageEventHandler(message) { - console.log("WS", message.data.direction, message.data.content); - } + async debugWsMessageEventHandler(message) { + console.log("WS", message.data.direction, message.data.content); + } - async shutdown() { - this.connector.setTimeout(30); + async shutdown() { + this.connector.setTimeout(30); - try { - await link.messages.prepareDisconnect.send(this); - } catch (err) { - if (!(err instanceof errors.SessionLost)) { - throw err; - } - } + try { + await link.messages.prepareDisconnect.send(this); + } catch (err) { + if (!(err instanceof errors.SessionLost)) { + throw err; + } + } - await this.connector.close(1001, "Control Quit"); - } + await this.connector.close(1001, "Control Quit"); + } } diff --git a/packages/master/web/util/wslink.jsx b/packages/master/web/util/wslink.jsx index 3ff8e297..68b6f820 100644 --- a/packages/master/web/util/wslink.jsx +++ b/packages/master/web/util/wslink.jsx @@ -7,18 +7,18 @@ let control, controlConnector // Create WS connection to master. Used by all components through the interface exported here. (async () => { - config.finalizeConfigs(); - controlConnector = new ControlConnector( - localStorage.getItem("master_url"), - 10, // Reconnect delay - localStorage.getItem("master_token"), - ); - control = new Control(controlConnector, []); - try { - await controlConnector.connect(); - } catch (err) { - console.log(err) - } + config.finalizeConfigs(); + controlConnector = new ControlConnector( + localStorage.getItem("master_url"), + 10, // Reconnect delay + localStorage.getItem("master_token"), + ); + control = new Control(controlConnector, []); + try { + await controlConnector.connect(); + } catch (err) { + console.log(err) + } })() let listSlaves = createListFunction("listSlaves") @@ -28,107 +28,107 @@ let listRoles = createListFunction("listRoles") let listPermissions = createListFunction("listPermissions", "name") let startInstance = async function ({ instance_id, save = null }) { - return await link.messages.startInstance.send(control, { instance_id, save }) + return await link.messages.startInstance.send(control, { instance_id, save }) } let stopInstance = async function ({ instance_id }) { - return await link.messages.stopInstance.send(control, { instance_id }) + return await link.messages.stopInstance.send(control, { instance_id }) } let createInstance = async function (serialized_config) { - return await link.messages.createInstance.send(control, { serialized_config }); + return await link.messages.createInstance.send(control, { serialized_config }); } let deleteInstance = async function ({ instance_id }) { - return await link.messages.deleteInstance.send(control, { instance_id }); + return await link.messages.deleteInstance.send(control, { instance_id }); } let assignInstance = async function ({ instance_id, slave_id }) { - return await link.messages.assignInstanceCommand.send(control, { - instance_id, - slave_id, - }); + return await link.messages.assignInstanceCommand.send(control, { + instance_id, + slave_id, + }); } let createSave = async function ({ instance_id }) { - return await link.messages.createSave.send(control, { instance_id }); + return await link.messages.createSave.send(control, { instance_id }); } let getInstanceConfig = async function ({ instance_id }) { - return await link.messages.getInstanceConfig.send(control, { instance_id }); + return await link.messages.getInstanceConfig.send(control, { instance_id }); } let setInstanceConfigField = async function ({ instance_id, field, value }) { - return await link.messages.setInstanceConfigField.send(control, { - instance_id, - field, - value: typeof value === "object" ? JSON.stringify(value) : value, - }); + return await link.messages.setInstanceConfigField.send(control, { + instance_id, + field, + value: typeof value === "object" ? JSON.stringify(value) : value, + }); } let setInstanceConfigProp = async function ({ instance_id, field, prop, value }) { - return await link.messages.setInstanceConfigProp.send(control, { - instance_id, - field, - prop, - value, // JSON Object - }); + return await link.messages.setInstanceConfigProp.send(control, { + instance_id, + field, + prop, + value, // JSON Object + }); } let sendRcon = async function ({ instance_id, command }) { - return await link.messages.sendRcon.send(control, { instance_id, command }) + return await link.messages.sendRcon.send(control, { instance_id, command }) } let setInstanceOutputSubscriptions = async function ({ instance_id }) { - return await link.messages.setInstanceOutputSubscriptions.send(control, { instance_ids: [instance_id] }) + return await link.messages.setInstanceOutputSubscriptions.send(control, { instance_ids: [instance_id] }) } let createUser = async function ({ name }) { - return await link.messages.createUser.send(control, { name }) + return await link.messages.createUser.send(control, { name }) } let deleteUser = async function ({ name }) { - return await link.messages.deleteUser.send(control, { name }) + return await link.messages.deleteUser.send(control, { name }) } let setRoles = async function ({ name, roles }) { - return await link.messages.updateUserRoles.send(control, { - name, - roles, - }) + return await link.messages.updateUserRoles.send(control, { + name, + roles, + }) } let createRole = async function ({ name, description, permissions = [] }) { - return await link.messages.createRole.send(control, { name, description, permissions }) + return await link.messages.createRole.send(control, { name, description, permissions }) } let updateRole = async function ({ id, name, description, permissions }) { - return await link.messages.updateRole.send(control, { - id, name, description, permissions - }) + return await link.messages.updateRole.send(control, { + id, name, description, permissions + }) } export { - listSlaves, - listInstances, - listUsers, - createUser, - deleteUser, - listRoles, - setRoles, - createRole, - updateRole, - listPermissions, - startInstance, - stopInstance, - createInstance, - deleteInstance, - assignInstance, - createSave, - getInstanceConfig, - setInstanceConfigField, - setInstanceConfigProp, - sendRcon, - setInstanceOutputSubscriptions, + listSlaves, + listInstances, + listUsers, + createUser, + deleteUser, + listRoles, + setRoles, + createRole, + updateRole, + listPermissions, + startInstance, + stopInstance, + createInstance, + deleteInstance, + assignInstance, + createSave, + getInstanceConfig, + setInstanceConfigField, + setInstanceConfigProp, + sendRcon, + setInstanceOutputSubscriptions, } function createListFunction(name, key) { - return async () => { - return (await link.messages[name].send(control)).list.map(addKey(key || "id")); - } + return async () => { + return (await link.messages[name].send(control)).list.map(addKey(key || "id")); + } } function addKey(key) { - return function (el) { - return { - ...el, - key: el[key] - } - } + return function (el) { + return { + ...el, + key: el[key] + } + } }