mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-22 18:25:47 +08:00
Change CRLF to LF.
This commit is contained in:
parent
7304e62f95
commit
09b39d69f6
@ -1,224 +1,224 @@
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select} from 'antd';
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import Face from "./Face";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
class ApplicationEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
applicationName: props.match.params.applicationName,
|
||||
application: null,
|
||||
organizations: [],
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getApplication();
|
||||
this.getOrganizations();
|
||||
this.getProviders();
|
||||
}
|
||||
|
||||
getApplication() {
|
||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||
.then((application) => {
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getProviders() {
|
||||
ProviderBackend.getProviders("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
providers: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseApplicationField(key, value) {
|
||||
// if ([].includes(key)) {
|
||||
// value = Setting.myParseInt(value);
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
updateApplicationField(key, value) {
|
||||
value = this.parseApplicationField(key, value);
|
||||
|
||||
let application = this.state.application;
|
||||
application[key] = value;
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
}
|
||||
|
||||
renderApplication() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
Edit Application
|
||||
<Button type="primary" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
|
||||
</div>
|
||||
} style={{marginLeft: '5px'}} type="inner">
|
||||
<Row style={{marginTop: '10px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.application.name} onChange={e => {
|
||||
this.updateApplicationField('name', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Display Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.application.displayName} onChange={e => {
|
||||
this.updateApplicationField('displayName', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Logo:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={1}>
|
||||
URL:
|
||||
</Col>
|
||||
<Col span={23} >
|
||||
<Input prefix={<LinkOutlined/>} value={this.state.application.logo} onChange={e => {
|
||||
this.updateApplicationField('logo', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={1}>
|
||||
Preview:
|
||||
</Col>
|
||||
<Col span={23} >
|
||||
<a target="_blank" href={this.state.application.logo}>
|
||||
<img src={this.state.application.logo} alt={this.state.application.logo} height={90} style={{marginBottom: '20px'}}/>
|
||||
</a>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Organization:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: '100%'}} value={this.state.application.organization} onChange={(value => {this.updateApplicationField('organization', value);})}>
|
||||
{
|
||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Providers:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select mode="tags" style={{width: '100%'}}
|
||||
value={this.state.application.providers}
|
||||
onChange={value => {
|
||||
this.updateApplicationField('providers', value);
|
||||
}} >
|
||||
{
|
||||
this.state.providers.map((provider, index) => <Option key={index} value={provider.name}>{provider.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Face Preview:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<a style={{marginBottom: '10px'}} target="_blank" href={`/doors/${this.state.application.name}`}>
|
||||
{
|
||||
`${window.location.host}/doors/${this.state.application.name}`
|
||||
}
|
||||
</a>
|
||||
<br/>
|
||||
<br/>
|
||||
<div style={{width: "500px", height: "600px", border: "1px solid rgb(217,217,217)"}}>
|
||||
<Face application={this.state.application} />
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
submitApplicationEdit() {
|
||||
let application = Setting.deepCopy(this.state.application);
|
||||
ApplicationBackend.updateApplication(this.state.application.owner, this.state.applicationName, application)
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
Setting.showMessage("success", `Successfully saved`);
|
||||
this.setState({
|
||||
applicationName: this.state.application.name,
|
||||
});
|
||||
this.props.history.push(`/applications/${this.state.application.name}`);
|
||||
} else {
|
||||
Setting.showMessage("error", `failed to save: server side failure`);
|
||||
this.updateApplicationField('name', this.state.applicationName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `failed to save: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.state.application !== null ? this.renderApplication() : null
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{margin: 10}}>
|
||||
<Col span={2}>
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Button type="primary" size="large" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ApplicationEditPage;
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select} from 'antd';
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import Face from "./Face";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
class ApplicationEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
applicationName: props.match.params.applicationName,
|
||||
application: null,
|
||||
organizations: [],
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getApplication();
|
||||
this.getOrganizations();
|
||||
this.getProviders();
|
||||
}
|
||||
|
||||
getApplication() {
|
||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||
.then((application) => {
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getProviders() {
|
||||
ProviderBackend.getProviders("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
providers: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseApplicationField(key, value) {
|
||||
// if ([].includes(key)) {
|
||||
// value = Setting.myParseInt(value);
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
updateApplicationField(key, value) {
|
||||
value = this.parseApplicationField(key, value);
|
||||
|
||||
let application = this.state.application;
|
||||
application[key] = value;
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
}
|
||||
|
||||
renderApplication() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
Edit Application
|
||||
<Button type="primary" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
|
||||
</div>
|
||||
} style={{marginLeft: '5px'}} type="inner">
|
||||
<Row style={{marginTop: '10px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.application.name} onChange={e => {
|
||||
this.updateApplicationField('name', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Display Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.application.displayName} onChange={e => {
|
||||
this.updateApplicationField('displayName', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Logo:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={1}>
|
||||
URL:
|
||||
</Col>
|
||||
<Col span={23} >
|
||||
<Input prefix={<LinkOutlined/>} value={this.state.application.logo} onChange={e => {
|
||||
this.updateApplicationField('logo', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={1}>
|
||||
Preview:
|
||||
</Col>
|
||||
<Col span={23} >
|
||||
<a target="_blank" href={this.state.application.logo}>
|
||||
<img src={this.state.application.logo} alt={this.state.application.logo} height={90} style={{marginBottom: '20px'}}/>
|
||||
</a>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Organization:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: '100%'}} value={this.state.application.organization} onChange={(value => {this.updateApplicationField('organization', value);})}>
|
||||
{
|
||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Providers:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select mode="tags" style={{width: '100%'}}
|
||||
value={this.state.application.providers}
|
||||
onChange={value => {
|
||||
this.updateApplicationField('providers', value);
|
||||
}} >
|
||||
{
|
||||
this.state.providers.map((provider, index) => <Option key={index} value={provider.name}>{provider.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Face Preview:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<a style={{marginBottom: '10px'}} target="_blank" href={`/doors/${this.state.application.name}`}>
|
||||
{
|
||||
`${window.location.host}/doors/${this.state.application.name}`
|
||||
}
|
||||
</a>
|
||||
<br/>
|
||||
<br/>
|
||||
<div style={{width: "500px", height: "600px", border: "1px solid rgb(217,217,217)"}}>
|
||||
<Face application={this.state.application} />
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
submitApplicationEdit() {
|
||||
let application = Setting.deepCopy(this.state.application);
|
||||
ApplicationBackend.updateApplication(this.state.application.owner, this.state.applicationName, application)
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
Setting.showMessage("success", `Successfully saved`);
|
||||
this.setState({
|
||||
applicationName: this.state.application.name,
|
||||
});
|
||||
this.props.history.push(`/applications/${this.state.application.name}`);
|
||||
} else {
|
||||
Setting.showMessage("error", `failed to save: server side failure`);
|
||||
this.updateApplicationField('name', this.state.applicationName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `failed to save: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.state.application !== null ? this.renderApplication() : null
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{margin: 10}}>
|
||||
<Col span={2}>
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Button type="primary" size="large" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ApplicationEditPage;
|
||||
|
@ -1,199 +1,199 @@
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Popconfirm, Row, Table} from 'antd';
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
|
||||
class ApplicationListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
applications: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getApplications();
|
||||
}
|
||||
|
||||
getApplications() {
|
||||
ApplicationBackend.getApplications("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
applications: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newApplication() {
|
||||
return {
|
||||
owner: "admin", // this.props.account.applicationname,
|
||||
name: `application_${this.state.applications.length}`,
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Application - ${this.state.applications.length}`,
|
||||
logo: "https://cdn.jsdelivr.net/gh/casbin/static/img/logo@2x.png",
|
||||
providers: [],
|
||||
}
|
||||
}
|
||||
|
||||
addApplication() {
|
||||
const newApplication = this.newApplication();
|
||||
ApplicationBackend.addApplication(newApplication)
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Application added successfully`);
|
||||
this.setState({
|
||||
applications: Setting.prependRow(this.state.applications, newApplication),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Application failed to add: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteApplication(i) {
|
||||
ApplicationBackend.deleteApplication(this.state.applications[i])
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Application deleted successfully`);
|
||||
this.setState({
|
||||
applications: Setting.deleteRow(this.state.applications, i),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Application failed to delete: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(applications) {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/applications/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Created Time',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Display Name',
|
||||
dataIndex: 'displayName',
|
||||
key: 'displayName',
|
||||
// width: '100px',
|
||||
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
||||
},
|
||||
{
|
||||
title: 'Logo',
|
||||
dataIndex: 'logo',
|
||||
key: 'logo',
|
||||
width: '250px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a target="_blank" href={text}>
|
||||
<img src={text} alt={text} width={150} />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Organization',
|
||||
dataIndex: 'organization',
|
||||
key: 'organization',
|
||||
width: '200px',
|
||||
sorter: (a, b) => a.organization.localeCompare(b.organization),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a href={`/organizations/${text}`}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Providers',
|
||||
dataIndex: 'providers',
|
||||
key: 'providers',
|
||||
width: '200px',
|
||||
sorter: (a, b) => a.providers.localeCompare(b.providers),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a href={`/providers/${text}`}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: '',
|
||||
key: 'op',
|
||||
width: '170px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/applications/${record.name}`)}>Edit</Button>
|
||||
<Popconfirm
|
||||
title={`Sure to delete application: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteApplication(index)}
|
||||
>
|
||||
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
Applications
|
||||
<Button type="primary" size="small" onClick={this.addApplication.bind(this)}>Add</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={applications === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.applications)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ApplicationListPage;
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Popconfirm, Row, Table} from 'antd';
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
|
||||
class ApplicationListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
applications: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getApplications();
|
||||
}
|
||||
|
||||
getApplications() {
|
||||
ApplicationBackend.getApplications("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
applications: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newApplication() {
|
||||
return {
|
||||
owner: "admin", // this.props.account.applicationname,
|
||||
name: `application_${this.state.applications.length}`,
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Application - ${this.state.applications.length}`,
|
||||
logo: "https://cdn.jsdelivr.net/gh/casbin/static/img/logo@2x.png",
|
||||
providers: [],
|
||||
}
|
||||
}
|
||||
|
||||
addApplication() {
|
||||
const newApplication = this.newApplication();
|
||||
ApplicationBackend.addApplication(newApplication)
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Application added successfully`);
|
||||
this.setState({
|
||||
applications: Setting.prependRow(this.state.applications, newApplication),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Application failed to add: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteApplication(i) {
|
||||
ApplicationBackend.deleteApplication(this.state.applications[i])
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Application deleted successfully`);
|
||||
this.setState({
|
||||
applications: Setting.deleteRow(this.state.applications, i),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Application failed to delete: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(applications) {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/applications/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Created Time',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Display Name',
|
||||
dataIndex: 'displayName',
|
||||
key: 'displayName',
|
||||
// width: '100px',
|
||||
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
||||
},
|
||||
{
|
||||
title: 'Logo',
|
||||
dataIndex: 'logo',
|
||||
key: 'logo',
|
||||
width: '250px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a target="_blank" href={text}>
|
||||
<img src={text} alt={text} width={150} />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Organization',
|
||||
dataIndex: 'organization',
|
||||
key: 'organization',
|
||||
width: '200px',
|
||||
sorter: (a, b) => a.organization.localeCompare(b.organization),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a href={`/organizations/${text}`}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Providers',
|
||||
dataIndex: 'providers',
|
||||
key: 'providers',
|
||||
width: '200px',
|
||||
sorter: (a, b) => a.providers.localeCompare(b.providers),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a href={`/providers/${text}`}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: '',
|
||||
key: 'op',
|
||||
width: '170px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/applications/${record.name}`)}>Edit</Button>
|
||||
<Popconfirm
|
||||
title={`Sure to delete application: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteApplication(index)}
|
||||
>
|
||||
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
Applications
|
||||
<Button type="primary" size="small" onClick={this.addApplication.bind(this)}>Add</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={applications === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.applications)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ApplicationListPage;
|
||||
|
258
web/src/Face.js
258
web/src/Face.js
@ -1,129 +1,129 @@
|
||||
import React from "react";
|
||||
import {Button, Checkbox, Col, Form, Input, Row} from "antd";
|
||||
import {LockOutlined, UserOutlined} from "@ant-design/icons";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
import * as AccountBackend from "./backend/AccountBackend";
|
||||
import * as Setting from "./Setting";
|
||||
|
||||
class Face extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
applicationName: props.applicationName !== undefined ? props.applicationName : (props.match === undefined ? null : props.match.params.applicationName),
|
||||
application: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getApplication();
|
||||
}
|
||||
|
||||
getApplication() {
|
||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||
.then((application) => {
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getApplicationObj() {
|
||||
if (this.props.application !== undefined) {
|
||||
return this.props.application;
|
||||
} else {
|
||||
return this.state.application;
|
||||
}
|
||||
}
|
||||
|
||||
onFinish(values) {
|
||||
AccountBackend.login(values)
|
||||
.then((res) => {
|
||||
if (res.status === 'ok') {
|
||||
this.props.onLoggedIn();
|
||||
Setting.showMessage("success", `Logged in successfully`);
|
||||
Setting.goToLink("/");
|
||||
} else {
|
||||
Setting.showMessage("error", `Log in failed:${res.msg}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
renderForm() {
|
||||
return (
|
||||
<Form
|
||||
name="normal_login"
|
||||
initialValues={{
|
||||
organization: this.getApplicationObj().organization,
|
||||
remember: true
|
||||
}}
|
||||
onFinish={this.onFinish.bind(this)}
|
||||
style={{width: "250px"}}
|
||||
size="large"
|
||||
>
|
||||
<Form.Item
|
||||
name="username"
|
||||
rules={[{ required: true, message: 'Please input your Username!' }]}
|
||||
>
|
||||
<Input
|
||||
prefix={<UserOutlined className="site-form-item-icon" />}
|
||||
placeholder="username"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password"
|
||||
rules={[{ required: true, message: 'Please input your Password!' }]}
|
||||
>
|
||||
<Input
|
||||
prefix={<LockOutlined className="site-form-item-icon" />}
|
||||
type="password"
|
||||
placeholder="password"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Form.Item name="remember" valuePropName="checked" noStyle>
|
||||
<Checkbox style={{float: "left"}}>Auto login</Checkbox>
|
||||
</Form.Item>
|
||||
<a style={{float: "right"}} href="">
|
||||
Forgot password?
|
||||
</a>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
style={{width: "100%"}}
|
||||
>
|
||||
Login
|
||||
</Button>
|
||||
<div style={{float: "right"}}>
|
||||
No account yet, <a href="/register">sign up now</a>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const application = this.getApplicationObj();
|
||||
if (application === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col span={24} style={{display: "flex", justifyContent: "center"}} >
|
||||
<div style={{marginTop: "80px", textAlign: "center"}}>
|
||||
<img src={application.logo} alt={application.displayName} style={{marginBottom: '50px'}}/>
|
||||
{
|
||||
this.renderForm(application)
|
||||
}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Face;
|
||||
import React from "react";
|
||||
import {Button, Checkbox, Col, Form, Input, Row} from "antd";
|
||||
import {LockOutlined, UserOutlined} from "@ant-design/icons";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
import * as AccountBackend from "./backend/AccountBackend";
|
||||
import * as Setting from "./Setting";
|
||||
|
||||
class Face extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
applicationName: props.applicationName !== undefined ? props.applicationName : (props.match === undefined ? null : props.match.params.applicationName),
|
||||
application: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getApplication();
|
||||
}
|
||||
|
||||
getApplication() {
|
||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||
.then((application) => {
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getApplicationObj() {
|
||||
if (this.props.application !== undefined) {
|
||||
return this.props.application;
|
||||
} else {
|
||||
return this.state.application;
|
||||
}
|
||||
}
|
||||
|
||||
onFinish(values) {
|
||||
AccountBackend.login(values)
|
||||
.then((res) => {
|
||||
if (res.status === 'ok') {
|
||||
this.props.onLoggedIn();
|
||||
Setting.showMessage("success", `Logged in successfully`);
|
||||
Setting.goToLink("/");
|
||||
} else {
|
||||
Setting.showMessage("error", `Log in failed:${res.msg}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
renderForm() {
|
||||
return (
|
||||
<Form
|
||||
name="normal_login"
|
||||
initialValues={{
|
||||
organization: this.getApplicationObj().organization,
|
||||
remember: true
|
||||
}}
|
||||
onFinish={this.onFinish.bind(this)}
|
||||
style={{width: "250px"}}
|
||||
size="large"
|
||||
>
|
||||
<Form.Item
|
||||
name="username"
|
||||
rules={[{ required: true, message: 'Please input your Username!' }]}
|
||||
>
|
||||
<Input
|
||||
prefix={<UserOutlined className="site-form-item-icon" />}
|
||||
placeholder="username"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password"
|
||||
rules={[{ required: true, message: 'Please input your Password!' }]}
|
||||
>
|
||||
<Input
|
||||
prefix={<LockOutlined className="site-form-item-icon" />}
|
||||
type="password"
|
||||
placeholder="password"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Form.Item name="remember" valuePropName="checked" noStyle>
|
||||
<Checkbox style={{float: "left"}}>Auto login</Checkbox>
|
||||
</Form.Item>
|
||||
<a style={{float: "right"}} href="">
|
||||
Forgot password?
|
||||
</a>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
style={{width: "100%"}}
|
||||
>
|
||||
Login
|
||||
</Button>
|
||||
<div style={{float: "right"}}>
|
||||
No account yet, <a href="/register">sign up now</a>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const application = this.getApplicationObj();
|
||||
if (application === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col span={24} style={{display: "flex", justifyContent: "center"}} >
|
||||
<div style={{marginTop: "80px", textAlign: "center"}}>
|
||||
<img src={application.logo} alt={application.displayName} style={{marginBottom: '50px'}}/>
|
||||
{
|
||||
this.renderForm(application)
|
||||
}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Face;
|
||||
|
@ -1,18 +1,18 @@
|
||||
import React from "react";
|
||||
|
||||
class HomePage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
"home"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default HomePage;
|
||||
import React from "react";
|
||||
|
||||
class HomePage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
"home"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default HomePage;
|
||||
|
@ -1,135 +1,135 @@
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row} from 'antd';
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
|
||||
class OrganizationEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizationName: props.match.params.organizationName,
|
||||
organization: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getOrganization();
|
||||
}
|
||||
|
||||
getOrganization() {
|
||||
OrganizationBackend.getOrganization("admin", this.state.organizationName)
|
||||
.then((organization) => {
|
||||
this.setState({
|
||||
organization: organization,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseOrganizationField(key, value) {
|
||||
// if ([].includes(key)) {
|
||||
// value = Setting.myParseInt(value);
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
updateOrganizationField(key, value) {
|
||||
value = this.parseOrganizationField(key, value);
|
||||
|
||||
let organization = this.state.organization;
|
||||
organization[key] = value;
|
||||
this.setState({
|
||||
organization: organization,
|
||||
});
|
||||
}
|
||||
|
||||
renderOrganization() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
Edit Organization
|
||||
<Button type="primary" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
|
||||
</div>
|
||||
} style={{marginLeft: '5px'}} type="inner">
|
||||
<Row style={{marginTop: '10px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.organization.name} onChange={e => {
|
||||
this.updateOrganizationField('name', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Display Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.organization.displayName} onChange={e => {
|
||||
this.updateOrganizationField('displayName', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Website Url:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.organization.websiteUrl} onChange={e => {
|
||||
this.updateOrganizationField('websiteUrl', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
submitOrganizationEdit() {
|
||||
let organization = Setting.deepCopy(this.state.organization);
|
||||
OrganizationBackend.updateOrganization(this.state.organization.owner, this.state.organizationName, organization)
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
Setting.showMessage("success", `Successfully saved`);
|
||||
this.setState({
|
||||
organizationName: this.state.organization.name,
|
||||
});
|
||||
this.props.history.push(`/organizations/${this.state.organization.name}`);
|
||||
} else {
|
||||
Setting.showMessage("error", `failed to save: server side failure`);
|
||||
this.updateOrganizationField('name', this.state.organizationName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `failed to save: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.state.organization !== null ? this.renderOrganization() : null
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{margin: 10}}>
|
||||
<Col span={2}>
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Button type="primary" size="large" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default OrganizationEditPage;
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row} from 'antd';
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
|
||||
class OrganizationEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizationName: props.match.params.organizationName,
|
||||
organization: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getOrganization();
|
||||
}
|
||||
|
||||
getOrganization() {
|
||||
OrganizationBackend.getOrganization("admin", this.state.organizationName)
|
||||
.then((organization) => {
|
||||
this.setState({
|
||||
organization: organization,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseOrganizationField(key, value) {
|
||||
// if ([].includes(key)) {
|
||||
// value = Setting.myParseInt(value);
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
updateOrganizationField(key, value) {
|
||||
value = this.parseOrganizationField(key, value);
|
||||
|
||||
let organization = this.state.organization;
|
||||
organization[key] = value;
|
||||
this.setState({
|
||||
organization: organization,
|
||||
});
|
||||
}
|
||||
|
||||
renderOrganization() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
Edit Organization
|
||||
<Button type="primary" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
|
||||
</div>
|
||||
} style={{marginLeft: '5px'}} type="inner">
|
||||
<Row style={{marginTop: '10px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.organization.name} onChange={e => {
|
||||
this.updateOrganizationField('name', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Display Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.organization.displayName} onChange={e => {
|
||||
this.updateOrganizationField('displayName', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Website Url:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.organization.websiteUrl} onChange={e => {
|
||||
this.updateOrganizationField('websiteUrl', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
submitOrganizationEdit() {
|
||||
let organization = Setting.deepCopy(this.state.organization);
|
||||
OrganizationBackend.updateOrganization(this.state.organization.owner, this.state.organizationName, organization)
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
Setting.showMessage("success", `Successfully saved`);
|
||||
this.setState({
|
||||
organizationName: this.state.organization.name,
|
||||
});
|
||||
this.props.history.push(`/organizations/${this.state.organization.name}`);
|
||||
} else {
|
||||
Setting.showMessage("error", `failed to save: server side failure`);
|
||||
this.updateOrganizationField('name', this.state.organizationName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `failed to save: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.state.organization !== null ? this.renderOrganization() : null
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{margin: 10}}>
|
||||
<Col span={2}>
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Button type="primary" size="large" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default OrganizationEditPage;
|
||||
|
@ -1,171 +1,171 @@
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Popconfirm, Row, Table} from 'antd';
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
|
||||
class OrganizationListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizations: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getOrganizations();
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newOrganization() {
|
||||
return {
|
||||
owner: "admin", // this.props.account.organizationname,
|
||||
name: `organization_${this.state.organizations.length}`,
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Organization - ${this.state.organizations.length}`,
|
||||
websiteUrl: "https://example.com",
|
||||
}
|
||||
}
|
||||
|
||||
addOrganization() {
|
||||
const newOrganization = this.newOrganization();
|
||||
OrganizationBackend.addOrganization(newOrganization)
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Organization added successfully`);
|
||||
this.setState({
|
||||
organizations: Setting.prependRow(this.state.organizations, newOrganization),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Organization failed to add: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteOrganization(i) {
|
||||
OrganizationBackend.deleteOrganization(this.state.organizations[i])
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Organization deleted successfully`);
|
||||
this.setState({
|
||||
organizations: Setting.deleteRow(this.state.organizations, i),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Organization failed to delete: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(organizations) {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/organizations/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Created Time',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Display Name',
|
||||
dataIndex: 'displayName',
|
||||
key: 'displayName',
|
||||
// width: '100px',
|
||||
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
||||
},
|
||||
{
|
||||
title: 'Website Url',
|
||||
dataIndex: 'websiteUrl',
|
||||
key: 'websiteUrl',
|
||||
width: '300px',
|
||||
sorter: (a, b) => a.websiteUrl.localeCompare(b.websiteUrl),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a target="_blank" href={text}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: '',
|
||||
key: 'op',
|
||||
width: '170px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/organizations/${record.name}`)}>Edit</Button>
|
||||
<Popconfirm
|
||||
title={`Sure to delete organization: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteOrganization(index)}
|
||||
>
|
||||
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
Organizations
|
||||
<Button type="primary" size="small" onClick={this.addOrganization.bind(this)}>Add</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={organizations === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.organizations)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default OrganizationListPage;
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Popconfirm, Row, Table} from 'antd';
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
|
||||
class OrganizationListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizations: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getOrganizations();
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newOrganization() {
|
||||
return {
|
||||
owner: "admin", // this.props.account.organizationname,
|
||||
name: `organization_${this.state.organizations.length}`,
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Organization - ${this.state.organizations.length}`,
|
||||
websiteUrl: "https://example.com",
|
||||
}
|
||||
}
|
||||
|
||||
addOrganization() {
|
||||
const newOrganization = this.newOrganization();
|
||||
OrganizationBackend.addOrganization(newOrganization)
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Organization added successfully`);
|
||||
this.setState({
|
||||
organizations: Setting.prependRow(this.state.organizations, newOrganization),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Organization failed to add: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteOrganization(i) {
|
||||
OrganizationBackend.deleteOrganization(this.state.organizations[i])
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Organization deleted successfully`);
|
||||
this.setState({
|
||||
organizations: Setting.deleteRow(this.state.organizations, i),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Organization failed to delete: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(organizations) {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/organizations/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Created Time',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Display Name',
|
||||
dataIndex: 'displayName',
|
||||
key: 'displayName',
|
||||
// width: '100px',
|
||||
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
||||
},
|
||||
{
|
||||
title: 'Website Url',
|
||||
dataIndex: 'websiteUrl',
|
||||
key: 'websiteUrl',
|
||||
width: '300px',
|
||||
sorter: (a, b) => a.websiteUrl.localeCompare(b.websiteUrl),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a target="_blank" href={text}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: '',
|
||||
key: 'op',
|
||||
width: '170px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/organizations/${record.name}`)}>Edit</Button>
|
||||
<Popconfirm
|
||||
title={`Sure to delete organization: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteOrganization(index)}
|
||||
>
|
||||
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
Organizations
|
||||
<Button type="primary" size="small" onClick={this.addOrganization.bind(this)}>Add</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={organizations === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.organizations)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default OrganizationListPage;
|
||||
|
@ -1,165 +1,165 @@
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row} from 'antd';
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as Setting from "./Setting";
|
||||
|
||||
class ProviderEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
providerName: props.match.params.providerName,
|
||||
provider: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getProvider();
|
||||
}
|
||||
|
||||
getProvider() {
|
||||
ProviderBackend.getProvider("admin", this.state.providerName)
|
||||
.then((provider) => {
|
||||
this.setState({
|
||||
provider: provider,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseProviderField(key, value) {
|
||||
// if ([].includes(key)) {
|
||||
// value = Setting.myParseInt(value);
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
updateProviderField(key, value) {
|
||||
value = this.parseProviderField(key, value);
|
||||
|
||||
let provider = this.state.provider;
|
||||
provider[key] = value;
|
||||
this.setState({
|
||||
provider: provider,
|
||||
});
|
||||
}
|
||||
|
||||
renderProvider() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
Edit Provider
|
||||
<Button type="primary" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
|
||||
</div>
|
||||
} style={{marginLeft: '5px'}} type="inner">
|
||||
<Row style={{marginTop: '10px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.name} onChange={e => {
|
||||
this.updateProviderField('name', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Display Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.displayName} onChange={e => {
|
||||
this.updateProviderField('displayName', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
type:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.type} onChange={e => {
|
||||
this.updateProviderField('type', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Client Id:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.clientId} onChange={e => {
|
||||
this.updateProviderField('clientId', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Client Secret:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.clientSecret} onChange={e => {
|
||||
this.updateProviderField('clientSecret', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Provider Url:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.providerUrl} onChange={e => {
|
||||
this.updateProviderField('providerUrl', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
submitProviderEdit() {
|
||||
let provider = Setting.deepCopy(this.state.provider);
|
||||
ProviderBackend.updateProvider(this.state.provider.owner, this.state.providerName, provider)
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
Setting.showMessage("success", `Successfully saved`);
|
||||
this.setState({
|
||||
providerName: this.state.provider.name,
|
||||
});
|
||||
this.props.history.push(`/providers/${this.state.provider.name}`);
|
||||
} else {
|
||||
Setting.showMessage("error", `failed to save: server side failure`);
|
||||
this.updateProviderField('name', this.state.providerName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `failed to save: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.state.provider !== null ? this.renderProvider() : null
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{margin: 10}}>
|
||||
<Col span={2}>
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Button type="primary" size="large" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ProviderEditPage;
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row} from 'antd';
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as Setting from "./Setting";
|
||||
|
||||
class ProviderEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
providerName: props.match.params.providerName,
|
||||
provider: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getProvider();
|
||||
}
|
||||
|
||||
getProvider() {
|
||||
ProviderBackend.getProvider("admin", this.state.providerName)
|
||||
.then((provider) => {
|
||||
this.setState({
|
||||
provider: provider,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseProviderField(key, value) {
|
||||
// if ([].includes(key)) {
|
||||
// value = Setting.myParseInt(value);
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
updateProviderField(key, value) {
|
||||
value = this.parseProviderField(key, value);
|
||||
|
||||
let provider = this.state.provider;
|
||||
provider[key] = value;
|
||||
this.setState({
|
||||
provider: provider,
|
||||
});
|
||||
}
|
||||
|
||||
renderProvider() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
Edit Provider
|
||||
<Button type="primary" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
|
||||
</div>
|
||||
} style={{marginLeft: '5px'}} type="inner">
|
||||
<Row style={{marginTop: '10px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.name} onChange={e => {
|
||||
this.updateProviderField('name', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Display Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.displayName} onChange={e => {
|
||||
this.updateProviderField('displayName', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
type:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.type} onChange={e => {
|
||||
this.updateProviderField('type', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Client Id:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.clientId} onChange={e => {
|
||||
this.updateProviderField('clientId', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Client Secret:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.clientSecret} onChange={e => {
|
||||
this.updateProviderField('clientSecret', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Provider Url:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.providerUrl} onChange={e => {
|
||||
this.updateProviderField('providerUrl', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
submitProviderEdit() {
|
||||
let provider = Setting.deepCopy(this.state.provider);
|
||||
ProviderBackend.updateProvider(this.state.provider.owner, this.state.providerName, provider)
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
Setting.showMessage("success", `Successfully saved`);
|
||||
this.setState({
|
||||
providerName: this.state.provider.name,
|
||||
});
|
||||
this.props.history.push(`/providers/${this.state.provider.name}`);
|
||||
} else {
|
||||
Setting.showMessage("error", `failed to save: server side failure`);
|
||||
this.updateProviderField('name', this.state.providerName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `failed to save: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.state.provider !== null ? this.renderProvider() : null
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{margin: 10}}>
|
||||
<Col span={2}>
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Button type="primary" size="large" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ProviderEditPage;
|
||||
|
@ -1,195 +1,195 @@
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Popconfirm, Row, Table} from 'antd';
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
|
||||
class ProviderListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
providers: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getProviders();
|
||||
}
|
||||
|
||||
getProviders() {
|
||||
ProviderBackend.getProviders("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
providers: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newProvider() {
|
||||
return {
|
||||
owner: "admin", // this.props.account.providername,
|
||||
name: `provider_${this.state.providers.length}`,
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Provider - ${this.state.providers.length}`,
|
||||
type: "github",
|
||||
clientId: "",
|
||||
clientSecret: "",
|
||||
providerUrl: "https://github.com/organizations/xxx/settings/applications/1234567",
|
||||
}
|
||||
}
|
||||
|
||||
addProvider() {
|
||||
const newProvider = this.newProvider();
|
||||
ProviderBackend.addProvider(newProvider)
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Provider added successfully`);
|
||||
this.setState({
|
||||
providers: Setting.prependRow(this.state.providers, newProvider),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Provider failed to add: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteProvider(i) {
|
||||
ProviderBackend.deleteProvider(this.state.providers[i])
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Provider deleted successfully`);
|
||||
this.setState({
|
||||
providers: Setting.deleteRow(this.state.providers, i),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Provider failed to delete: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(providers) {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/providers/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Created Time',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Display Name',
|
||||
dataIndex: 'displayName',
|
||||
key: 'displayName',
|
||||
// width: '100px',
|
||||
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
||||
},
|
||||
{
|
||||
title: 'Type',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.type.localeCompare(b.type),
|
||||
},
|
||||
{
|
||||
title: 'Client Id',
|
||||
dataIndex: 'clientId',
|
||||
key: 'clientId',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.clientId.localeCompare(b.clientId),
|
||||
},
|
||||
{
|
||||
title: 'Client Secret',
|
||||
dataIndex: 'clientSecret',
|
||||
key: 'clientSecret',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.clientSecret.localeCompare(b.clientSecret),
|
||||
},
|
||||
{
|
||||
title: 'Provider Url',
|
||||
dataIndex: 'providerUrl',
|
||||
key: 'providerUrl',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.providerUrl.localeCompare(b.providerUrl),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a target="_blank" href={text}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: '',
|
||||
key: 'op',
|
||||
width: '170px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/providers/${record.name}`)}>Edit</Button>
|
||||
<Popconfirm
|
||||
title={`Sure to delete provider: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteProvider(index)}
|
||||
>
|
||||
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
Providers
|
||||
<Button type="primary" size="small" onClick={this.addProvider.bind(this)}>Add</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={providers === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.providers)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ProviderListPage;
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Popconfirm, Row, Table} from 'antd';
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
|
||||
class ProviderListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
providers: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getProviders();
|
||||
}
|
||||
|
||||
getProviders() {
|
||||
ProviderBackend.getProviders("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
providers: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newProvider() {
|
||||
return {
|
||||
owner: "admin", // this.props.account.providername,
|
||||
name: `provider_${this.state.providers.length}`,
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Provider - ${this.state.providers.length}`,
|
||||
type: "github",
|
||||
clientId: "",
|
||||
clientSecret: "",
|
||||
providerUrl: "https://github.com/organizations/xxx/settings/applications/1234567",
|
||||
}
|
||||
}
|
||||
|
||||
addProvider() {
|
||||
const newProvider = this.newProvider();
|
||||
ProviderBackend.addProvider(newProvider)
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Provider added successfully`);
|
||||
this.setState({
|
||||
providers: Setting.prependRow(this.state.providers, newProvider),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Provider failed to add: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteProvider(i) {
|
||||
ProviderBackend.deleteProvider(this.state.providers[i])
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `Provider deleted successfully`);
|
||||
this.setState({
|
||||
providers: Setting.deleteRow(this.state.providers, i),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Provider failed to delete: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(providers) {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/providers/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Created Time',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Display Name',
|
||||
dataIndex: 'displayName',
|
||||
key: 'displayName',
|
||||
// width: '100px',
|
||||
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
||||
},
|
||||
{
|
||||
title: 'Type',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.type.localeCompare(b.type),
|
||||
},
|
||||
{
|
||||
title: 'Client Id',
|
||||
dataIndex: 'clientId',
|
||||
key: 'clientId',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.clientId.localeCompare(b.clientId),
|
||||
},
|
||||
{
|
||||
title: 'Client Secret',
|
||||
dataIndex: 'clientSecret',
|
||||
key: 'clientSecret',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.clientSecret.localeCompare(b.clientSecret),
|
||||
},
|
||||
{
|
||||
title: 'Provider Url',
|
||||
dataIndex: 'providerUrl',
|
||||
key: 'providerUrl',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.providerUrl.localeCompare(b.providerUrl),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a target="_blank" href={text}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: '',
|
||||
key: 'op',
|
||||
width: '170px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/providers/${record.name}`)}>Edit</Button>
|
||||
<Popconfirm
|
||||
title={`Sure to delete provider: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteProvider(index)}
|
||||
>
|
||||
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
Providers
|
||||
<Button type="primary" size="small" onClick={this.addProvider.bind(this)}>Add</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={providers === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.providers)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ProviderListPage;
|
||||
|
@ -1,125 +1,125 @@
|
||||
// Copyright 2020 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import {message} from "antd";
|
||||
import React from "react";
|
||||
import {isMobile as isMobileDevice} from "react-device-detect";
|
||||
|
||||
export let ServerUrl = '';
|
||||
|
||||
export function initServerUrl() {
|
||||
const hostname = window.location.hostname;
|
||||
if (hostname === 'localhost') {
|
||||
ServerUrl = `http://${hostname}:8000`;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseJson(s) {
|
||||
if (s === "") {
|
||||
return null;
|
||||
} else {
|
||||
return JSON.parse(s);
|
||||
}
|
||||
}
|
||||
|
||||
export function myParseInt(i) {
|
||||
const res = parseInt(i);
|
||||
return isNaN(res) ? 0 : res;
|
||||
}
|
||||
|
||||
export function openLink(link) {
|
||||
// this.props.history.push(link);
|
||||
const w = window.open('about:blank');
|
||||
w.location.href = link;
|
||||
}
|
||||
|
||||
export function goToLink(link) {
|
||||
window.location.href = link;
|
||||
}
|
||||
|
||||
export function showMessage(type, text) {
|
||||
if (type === "") {
|
||||
return;
|
||||
} else if (type === "success") {
|
||||
message.success(text);
|
||||
} else if (type === "error") {
|
||||
message.error(text);
|
||||
}
|
||||
}
|
||||
|
||||
export function deepCopy(obj) {
|
||||
return Object.assign({}, obj);
|
||||
}
|
||||
|
||||
export function addRow(array, row) {
|
||||
return [...array, row];
|
||||
}
|
||||
|
||||
export function prependRow(array, row) {
|
||||
return [row, ...array];
|
||||
}
|
||||
|
||||
export function deleteRow(array, i) {
|
||||
// return array = array.slice(0, i).concat(array.slice(i + 1));
|
||||
return [...array.slice(0, i), ...array.slice(i + 1)];
|
||||
}
|
||||
|
||||
export function swapRow(array, i, j) {
|
||||
return [...array.slice(0, i), array[j], ...array.slice(i + 1, j), array[i], ...array.slice(j + 1)];
|
||||
}
|
||||
|
||||
export function isMobile() {
|
||||
// return getIsMobileView();
|
||||
return isMobileDevice;
|
||||
}
|
||||
|
||||
export function getFormattedDate(date) {
|
||||
if (date === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
date = date.replace('T', ' ');
|
||||
date = date.replace('+08:00', ' ');
|
||||
return date;
|
||||
}
|
||||
|
||||
export function getFormattedDateShort(date) {
|
||||
return date.slice(0, 10);
|
||||
}
|
||||
|
||||
export function getShortName(s) {
|
||||
return s.split('/').slice(-1)[0];
|
||||
}
|
||||
|
||||
function getRandomInt(s) {
|
||||
let hash = 0;
|
||||
if (s.length !== 0) {
|
||||
for (let i = 0; i < s.length; i ++) {
|
||||
let char = s.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + char;
|
||||
hash = hash & hash;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
export function getAvatarColor(s) {
|
||||
const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
|
||||
let random = getRandomInt(s);
|
||||
if (random < 0) {
|
||||
random = -random;
|
||||
}
|
||||
return colorList[random % 4];
|
||||
}
|
||||
// Copyright 2020 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import {message} from "antd";
|
||||
import React from "react";
|
||||
import {isMobile as isMobileDevice} from "react-device-detect";
|
||||
|
||||
export let ServerUrl = '';
|
||||
|
||||
export function initServerUrl() {
|
||||
const hostname = window.location.hostname;
|
||||
if (hostname === 'localhost') {
|
||||
ServerUrl = `http://${hostname}:8000`;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseJson(s) {
|
||||
if (s === "") {
|
||||
return null;
|
||||
} else {
|
||||
return JSON.parse(s);
|
||||
}
|
||||
}
|
||||
|
||||
export function myParseInt(i) {
|
||||
const res = parseInt(i);
|
||||
return isNaN(res) ? 0 : res;
|
||||
}
|
||||
|
||||
export function openLink(link) {
|
||||
// this.props.history.push(link);
|
||||
const w = window.open('about:blank');
|
||||
w.location.href = link;
|
||||
}
|
||||
|
||||
export function goToLink(link) {
|
||||
window.location.href = link;
|
||||
}
|
||||
|
||||
export function showMessage(type, text) {
|
||||
if (type === "") {
|
||||
return;
|
||||
} else if (type === "success") {
|
||||
message.success(text);
|
||||
} else if (type === "error") {
|
||||
message.error(text);
|
||||
}
|
||||
}
|
||||
|
||||
export function deepCopy(obj) {
|
||||
return Object.assign({}, obj);
|
||||
}
|
||||
|
||||
export function addRow(array, row) {
|
||||
return [...array, row];
|
||||
}
|
||||
|
||||
export function prependRow(array, row) {
|
||||
return [row, ...array];
|
||||
}
|
||||
|
||||
export function deleteRow(array, i) {
|
||||
// return array = array.slice(0, i).concat(array.slice(i + 1));
|
||||
return [...array.slice(0, i), ...array.slice(i + 1)];
|
||||
}
|
||||
|
||||
export function swapRow(array, i, j) {
|
||||
return [...array.slice(0, i), array[j], ...array.slice(i + 1, j), array[i], ...array.slice(j + 1)];
|
||||
}
|
||||
|
||||
export function isMobile() {
|
||||
// return getIsMobileView();
|
||||
return isMobileDevice;
|
||||
}
|
||||
|
||||
export function getFormattedDate(date) {
|
||||
if (date === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
date = date.replace('T', ' ');
|
||||
date = date.replace('+08:00', ' ');
|
||||
return date;
|
||||
}
|
||||
|
||||
export function getFormattedDateShort(date) {
|
||||
return date.slice(0, 10);
|
||||
}
|
||||
|
||||
export function getShortName(s) {
|
||||
return s.split('/').slice(-1)[0];
|
||||
}
|
||||
|
||||
function getRandomInt(s) {
|
||||
let hash = 0;
|
||||
if (s.length !== 0) {
|
||||
for (let i = 0; i < s.length; i ++) {
|
||||
let char = s.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + char;
|
||||
hash = hash & hash;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
export function getAvatarColor(s) {
|
||||
const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
|
||||
let random = getRandomInt(s);
|
||||
if (random < 0) {
|
||||
random = -random;
|
||||
}
|
||||
return colorList[random % 4];
|
||||
}
|
||||
|
@ -1,193 +1,193 @@
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select} from 'antd';
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
class UserEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizationName: props.match.params.organizationName,
|
||||
userName: props.match.params.userName,
|
||||
user: null,
|
||||
organizations: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getUser();
|
||||
this.getOrganizations();
|
||||
}
|
||||
|
||||
getUser() {
|
||||
UserBackend.getUser(this.state.organizationName, this.state.userName)
|
||||
.then((user) => {
|
||||
this.setState({
|
||||
user: user,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseUserField(key, value) {
|
||||
// if ([].includes(key)) {
|
||||
// value = Setting.myParseInt(value);
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
updateUserField(key, value) {
|
||||
value = this.parseUserField(key, value);
|
||||
|
||||
let user = this.state.user;
|
||||
user[key] = value;
|
||||
this.setState({
|
||||
user: user,
|
||||
});
|
||||
}
|
||||
|
||||
renderUser() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
Edit User
|
||||
<Button type="primary" onClick={this.submitUserEdit.bind(this)}>Save</Button>
|
||||
</div>
|
||||
} style={{marginLeft: '5px'}} type="inner">
|
||||
<Row style={{marginTop: '10px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Organization:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: '100%'}} value={this.state.user.owner} onChange={(value => {this.updateUserField('owner', value);})}>
|
||||
{
|
||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.name} onChange={e => {
|
||||
this.updateUserField('name', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Password Type:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.passwordType} onChange={e => {
|
||||
this.updateUserField('passwordType', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Password:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.password} onChange={e => {
|
||||
this.updateUserField('password', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Display Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.displayName} onChange={e => {
|
||||
this.updateUserField('displayName', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Email:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.email} onChange={e => {
|
||||
this.updateUserField('email', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Phone:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.phone} onChange={e => {
|
||||
this.updateUserField('phone', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
submitUserEdit() {
|
||||
let user = Setting.deepCopy(this.state.user);
|
||||
UserBackend.updateUser(this.state.organizationName, this.state.userName, user)
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
Setting.showMessage("success", `Successfully saved`);
|
||||
this.setState({
|
||||
organizationName: this.state.user.owner,
|
||||
userName: this.state.user.name,
|
||||
});
|
||||
this.props.history.push(`/users/${this.state.user.owner}/${this.state.user.name}`);
|
||||
} else {
|
||||
Setting.showMessage("error", `failed to save: server side failure`);
|
||||
this.updateUserField('owner', this.state.organizationName);
|
||||
this.updateUserField('name', this.state.userName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `failed to save: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.state.user !== null ? this.renderUser() : null
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{margin: 10}}>
|
||||
<Col span={2}>
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Button type="primary" size="large" onClick={this.submitUserEdit.bind(this)}>Save</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default UserEditPage;
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select} from 'antd';
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
class UserEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizationName: props.match.params.organizationName,
|
||||
userName: props.match.params.userName,
|
||||
user: null,
|
||||
organizations: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getUser();
|
||||
this.getOrganizations();
|
||||
}
|
||||
|
||||
getUser() {
|
||||
UserBackend.getUser(this.state.organizationName, this.state.userName)
|
||||
.then((user) => {
|
||||
this.setState({
|
||||
user: user,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseUserField(key, value) {
|
||||
// if ([].includes(key)) {
|
||||
// value = Setting.myParseInt(value);
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
updateUserField(key, value) {
|
||||
value = this.parseUserField(key, value);
|
||||
|
||||
let user = this.state.user;
|
||||
user[key] = value;
|
||||
this.setState({
|
||||
user: user,
|
||||
});
|
||||
}
|
||||
|
||||
renderUser() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
Edit User
|
||||
<Button type="primary" onClick={this.submitUserEdit.bind(this)}>Save</Button>
|
||||
</div>
|
||||
} style={{marginLeft: '5px'}} type="inner">
|
||||
<Row style={{marginTop: '10px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Organization:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: '100%'}} value={this.state.user.owner} onChange={(value => {this.updateUserField('owner', value);})}>
|
||||
{
|
||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.name} onChange={e => {
|
||||
this.updateUserField('name', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Password Type:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.passwordType} onChange={e => {
|
||||
this.updateUserField('passwordType', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Password:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.password} onChange={e => {
|
||||
this.updateUserField('password', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Display Name:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.displayName} onChange={e => {
|
||||
this.updateUserField('displayName', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Email:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.email} onChange={e => {
|
||||
this.updateUserField('email', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={2}>
|
||||
Phone:
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.user.phone} onChange={e => {
|
||||
this.updateUserField('phone', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
submitUserEdit() {
|
||||
let user = Setting.deepCopy(this.state.user);
|
||||
UserBackend.updateUser(this.state.organizationName, this.state.userName, user)
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
Setting.showMessage("success", `Successfully saved`);
|
||||
this.setState({
|
||||
organizationName: this.state.user.owner,
|
||||
userName: this.state.user.name,
|
||||
});
|
||||
this.props.history.push(`/users/${this.state.user.owner}/${this.state.user.name}`);
|
||||
} else {
|
||||
Setting.showMessage("error", `failed to save: server side failure`);
|
||||
this.updateUserField('owner', this.state.organizationName);
|
||||
this.updateUserField('name', this.state.userName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `failed to save: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.state.user !== null ? this.renderUser() : null
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{margin: 10}}>
|
||||
<Col span={2}>
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Button type="primary" size="large" onClick={this.submitUserEdit.bind(this)}>Save</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default UserEditPage;
|
||||
|
@ -1,202 +1,202 @@
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Popconfirm, Row, Table} from 'antd';
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
|
||||
class UserListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
users: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getUsers();
|
||||
}
|
||||
|
||||
getUsers() {
|
||||
UserBackend.getGlobalUsers()
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
users: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newUser() {
|
||||
return {
|
||||
owner: "admin", // this.props.account.username,
|
||||
name: `user_${this.state.users.length}`,
|
||||
createdTime: moment().format(),
|
||||
password: "123456",
|
||||
passwordType: "plain",
|
||||
displayName: `New User - ${this.state.users.length}`,
|
||||
email: "user@example.com",
|
||||
phone: "1-12345678",
|
||||
}
|
||||
}
|
||||
|
||||
addUser() {
|
||||
const newUser = this.newUser();
|
||||
UserBackend.addUser(newUser)
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `User added successfully`);
|
||||
this.setState({
|
||||
users: Setting.prependRow(this.state.users, newUser),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `User failed to add: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteUser(i) {
|
||||
UserBackend.deleteUser(this.state.users[i])
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `User deleted successfully`);
|
||||
this.setState({
|
||||
users: Setting.deleteRow(this.state.users, i),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `User failed to delete: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(users) {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Organization',
|
||||
dataIndex: 'owner',
|
||||
key: 'owner',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.owner.localeCompare(b.owner),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a href={`/organizations/${text}`}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/users/${record.owner}/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Created Time',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'PasswordType',
|
||||
dataIndex: 'passwordType',
|
||||
key: 'passwordType',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.passwordType.localeCompare(b.passwordType),
|
||||
},
|
||||
{
|
||||
title: 'Password',
|
||||
dataIndex: 'password',
|
||||
key: 'password',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.password.localeCompare(b.password),
|
||||
},
|
||||
{
|
||||
title: 'Display Name',
|
||||
dataIndex: 'displayName',
|
||||
key: 'displayName',
|
||||
// width: '100px',
|
||||
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
||||
},
|
||||
{
|
||||
title: 'Email',
|
||||
dataIndex: 'email',
|
||||
key: 'email',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.email.localeCompare(b.email),
|
||||
},
|
||||
{
|
||||
title: 'Phone',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.phone.localeCompare(b.phone),
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: '',
|
||||
key: 'op',
|
||||
width: '170px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/users/${record.owner}/${record.name}`)}>Edit</Button>
|
||||
<Popconfirm
|
||||
title={`Sure to delete user: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteUser(index)}
|
||||
>
|
||||
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={users} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
Users
|
||||
<Button type="primary" size="small" onClick={this.addUser.bind(this)}>Add</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={users === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.users)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default UserListPage;
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Popconfirm, Row, Table} from 'antd';
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
|
||||
class UserListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
users: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getUsers();
|
||||
}
|
||||
|
||||
getUsers() {
|
||||
UserBackend.getGlobalUsers()
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
users: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newUser() {
|
||||
return {
|
||||
owner: "admin", // this.props.account.username,
|
||||
name: `user_${this.state.users.length}`,
|
||||
createdTime: moment().format(),
|
||||
password: "123456",
|
||||
passwordType: "plain",
|
||||
displayName: `New User - ${this.state.users.length}`,
|
||||
email: "user@example.com",
|
||||
phone: "1-12345678",
|
||||
}
|
||||
}
|
||||
|
||||
addUser() {
|
||||
const newUser = this.newUser();
|
||||
UserBackend.addUser(newUser)
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `User added successfully`);
|
||||
this.setState({
|
||||
users: Setting.prependRow(this.state.users, newUser),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `User failed to add: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteUser(i) {
|
||||
UserBackend.deleteUser(this.state.users[i])
|
||||
.then((res) => {
|
||||
Setting.showMessage("success", `User deleted successfully`);
|
||||
this.setState({
|
||||
users: Setting.deleteRow(this.state.users, i),
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `User failed to delete: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(users) {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Organization',
|
||||
dataIndex: 'owner',
|
||||
key: 'owner',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.owner.localeCompare(b.owner),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<a href={`/organizations/${text}`}>
|
||||
{text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/users/${record.owner}/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Created Time',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'PasswordType',
|
||||
dataIndex: 'passwordType',
|
||||
key: 'passwordType',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.passwordType.localeCompare(b.passwordType),
|
||||
},
|
||||
{
|
||||
title: 'Password',
|
||||
dataIndex: 'password',
|
||||
key: 'password',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.password.localeCompare(b.password),
|
||||
},
|
||||
{
|
||||
title: 'Display Name',
|
||||
dataIndex: 'displayName',
|
||||
key: 'displayName',
|
||||
// width: '100px',
|
||||
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
||||
},
|
||||
{
|
||||
title: 'Email',
|
||||
dataIndex: 'email',
|
||||
key: 'email',
|
||||
width: '150px',
|
||||
sorter: (a, b) => a.email.localeCompare(b.email),
|
||||
},
|
||||
{
|
||||
title: 'Phone',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.phone.localeCompare(b.phone),
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: '',
|
||||
key: 'op',
|
||||
width: '170px',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/users/${record.owner}/${record.name}`)}>Edit</Button>
|
||||
<Popconfirm
|
||||
title={`Sure to delete user: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteUser(index)}
|
||||
>
|
||||
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={users} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
Users
|
||||
<Button type="primary" size="small" onClick={this.addUser.bind(this)}>Add</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={users === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.users)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default UserListPage;
|
||||
|
@ -1,77 +1,77 @@
|
||||
import React from "react";
|
||||
import {Col, Descriptions, Row} from 'antd';
|
||||
import * as AccountBackend from "../backend/AccountBackend";
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
class AccountPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
username: props.match.params.username,
|
||||
user: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getUser();
|
||||
}
|
||||
|
||||
getUser() {
|
||||
if (this.state.username !== undefined) {
|
||||
AccountBackend.getUser(this.state.username)
|
||||
.then((user) => {
|
||||
this.setState({
|
||||
user: user,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderValue(key) {
|
||||
if (this.props.account === null || this.props.account === undefined) {
|
||||
return <a href={"/login"}>Please sign in first</a>
|
||||
} else if (this.state.user !== null) {
|
||||
return this.state.user[key];
|
||||
} else {
|
||||
return this.props.account[key];
|
||||
}
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
return (
|
||||
<div>
|
||||
|
||||
<Descriptions title="My Account" bordered>
|
||||
<Descriptions.Item label="Username">{this.renderValue("name")}</Descriptions.Item>
|
||||
<Descriptions.Item label="Organization">{this.renderValue("owner")}</Descriptions.Item>
|
||||
<Descriptions.Item label="Created At">{Setting.getFormattedDate(this.renderValue("createdTime"))}</Descriptions.Item>
|
||||
<Descriptions.Item label="Password Type">{this.renderValue("passwordType")}</Descriptions.Item>
|
||||
<Descriptions.Item label="Display Name">{this.renderValue("displayName")}</Descriptions.Item>
|
||||
<Descriptions.Item label="E-mail">{this.renderValue("email")}</Descriptions.Item>
|
||||
<Descriptions.Item label="Phone">{this.renderValue("phone")}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderContent()
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default AccountPage;
|
||||
import React from "react";
|
||||
import {Col, Descriptions, Row} from 'antd';
|
||||
import * as AccountBackend from "../backend/AccountBackend";
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
class AccountPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
username: props.match.params.username,
|
||||
user: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.getUser();
|
||||
}
|
||||
|
||||
getUser() {
|
||||
if (this.state.username !== undefined) {
|
||||
AccountBackend.getUser(this.state.username)
|
||||
.then((user) => {
|
||||
this.setState({
|
||||
user: user,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderValue(key) {
|
||||
if (this.props.account === null || this.props.account === undefined) {
|
||||
return <a href={"/login"}>Please sign in first</a>
|
||||
} else if (this.state.user !== null) {
|
||||
return this.state.user[key];
|
||||
} else {
|
||||
return this.props.account[key];
|
||||
}
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
return (
|
||||
<div>
|
||||
|
||||
<Descriptions title="My Account" bordered>
|
||||
<Descriptions.Item label="Username">{this.renderValue("name")}</Descriptions.Item>
|
||||
<Descriptions.Item label="Organization">{this.renderValue("owner")}</Descriptions.Item>
|
||||
<Descriptions.Item label="Created At">{Setting.getFormattedDate(this.renderValue("createdTime"))}</Descriptions.Item>
|
||||
<Descriptions.Item label="Password Type">{this.renderValue("passwordType")}</Descriptions.Item>
|
||||
<Descriptions.Item label="Display Name">{this.renderValue("displayName")}</Descriptions.Item>
|
||||
<Descriptions.Item label="E-mail">{this.renderValue("email")}</Descriptions.Item>
|
||||
<Descriptions.Item label="Phone">{this.renderValue("phone")}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderContent()
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default AccountPage;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import Face from "../Face";
|
||||
|
||||
class LoginPage extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Face applicationName={"app-built-in"} account={this.props.account} onLoggedIn={this.props.onLoggedIn.bind(this)} {...this.props} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default LoginPage;
|
||||
import React from 'react';
|
||||
import Face from "../Face";
|
||||
|
||||
class LoginPage extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Face applicationName={"app-built-in"} account={this.props.account} onLoggedIn={this.props.onLoggedIn.bind(this)} {...this.props} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default LoginPage;
|
||||
|
@ -1,52 +1,52 @@
|
||||
// Copyright 2020 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getUser(username) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-user?username=${username}`, {
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getAccount() {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-account`, {
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function register(values) {
|
||||
return fetch(`${Setting.ServerUrl}/api/register`, {
|
||||
method: 'POST',
|
||||
credentials: "include",
|
||||
body: JSON.stringify(values),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function login(values) {
|
||||
return fetch(`${Setting.ServerUrl}/api/login`, {
|
||||
method: 'POST',
|
||||
credentials: "include",
|
||||
body: JSON.stringify(values),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return fetch(`${Setting.ServerUrl}/api/logout`, {
|
||||
method: 'POST',
|
||||
credentials: "include",
|
||||
}).then(res => res.json());
|
||||
}
|
||||
// Copyright 2020 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getUser(username) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-user?username=${username}`, {
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getAccount() {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-account`, {
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function register(values) {
|
||||
return fetch(`${Setting.ServerUrl}/api/register`, {
|
||||
method: 'POST',
|
||||
credentials: "include",
|
||||
body: JSON.stringify(values),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function login(values) {
|
||||
return fetch(`${Setting.ServerUrl}/api/login`, {
|
||||
method: 'POST',
|
||||
credentials: "include",
|
||||
body: JSON.stringify(values),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return fetch(`${Setting.ServerUrl}/api/logout`, {
|
||||
method: 'POST',
|
||||
credentials: "include",
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getApplications(owner) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-applications?owner=${owner}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getApplication(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-application?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function updateApplication(owner, name, application) {
|
||||
let newApplication = Setting.deepCopy(application);
|
||||
return fetch(`${Setting.ServerUrl}/api/update-application?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newApplication),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function addApplication(application) {
|
||||
let newApplication = Setting.deepCopy(application);
|
||||
return fetch(`${Setting.ServerUrl}/api/add-application`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newApplication),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function deleteApplication(application) {
|
||||
let newApplication = Setting.deepCopy(application);
|
||||
return fetch(`${Setting.ServerUrl}/api/delete-application`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newApplication),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getApplications(owner) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-applications?owner=${owner}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getApplication(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-application?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function updateApplication(owner, name, application) {
|
||||
let newApplication = Setting.deepCopy(application);
|
||||
return fetch(`${Setting.ServerUrl}/api/update-application?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newApplication),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function addApplication(application) {
|
||||
let newApplication = Setting.deepCopy(application);
|
||||
return fetch(`${Setting.ServerUrl}/api/add-application`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newApplication),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function deleteApplication(application) {
|
||||
let newApplication = Setting.deepCopy(application);
|
||||
return fetch(`${Setting.ServerUrl}/api/delete-application`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newApplication),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getOrganizations(owner) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-organizations?owner=${owner}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getOrganization(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-organization?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function updateOrganization(owner, name, organization) {
|
||||
let newOrganization = Setting.deepCopy(organization);
|
||||
return fetch(`${Setting.ServerUrl}/api/update-organization?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newOrganization),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function addOrganization(organization) {
|
||||
let newOrganization = Setting.deepCopy(organization);
|
||||
return fetch(`${Setting.ServerUrl}/api/add-organization`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newOrganization),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function deleteOrganization(organization) {
|
||||
let newOrganization = Setting.deepCopy(organization);
|
||||
return fetch(`${Setting.ServerUrl}/api/delete-organization`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newOrganization),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getOrganizations(owner) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-organizations?owner=${owner}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getOrganization(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-organization?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function updateOrganization(owner, name, organization) {
|
||||
let newOrganization = Setting.deepCopy(organization);
|
||||
return fetch(`${Setting.ServerUrl}/api/update-organization?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newOrganization),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function addOrganization(organization) {
|
||||
let newOrganization = Setting.deepCopy(organization);
|
||||
return fetch(`${Setting.ServerUrl}/api/add-organization`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newOrganization),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function deleteOrganization(organization) {
|
||||
let newOrganization = Setting.deepCopy(organization);
|
||||
return fetch(`${Setting.ServerUrl}/api/delete-organization`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newOrganization),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getProviders(owner) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-providers?owner=${owner}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getProvider(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-provider?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function updateProvider(owner, name, provider) {
|
||||
let newProvider = Setting.deepCopy(provider);
|
||||
return fetch(`${Setting.ServerUrl}/api/update-provider?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newProvider),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function addProvider(provider) {
|
||||
let newProvider = Setting.deepCopy(provider);
|
||||
return fetch(`${Setting.ServerUrl}/api/add-provider`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newProvider),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function deleteProvider(provider) {
|
||||
let newProvider = Setting.deepCopy(provider);
|
||||
return fetch(`${Setting.ServerUrl}/api/delete-provider`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newProvider),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getProviders(owner) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-providers?owner=${owner}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getProvider(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-provider?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function updateProvider(owner, name, provider) {
|
||||
let newProvider = Setting.deepCopy(provider);
|
||||
return fetch(`${Setting.ServerUrl}/api/update-provider?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newProvider),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function addProvider(provider) {
|
||||
let newProvider = Setting.deepCopy(provider);
|
||||
return fetch(`${Setting.ServerUrl}/api/add-provider`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newProvider),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function deleteProvider(provider) {
|
||||
let newProvider = Setting.deepCopy(provider);
|
||||
return fetch(`${Setting.ServerUrl}/api/delete-provider`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newProvider),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
@ -1,49 +1,49 @@
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getGlobalUsers() {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-global-users`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getUsers(owner) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-users?owner=${owner}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getUser(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-user?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function updateUser(owner, name, user) {
|
||||
let newUser = Setting.deepCopy(user);
|
||||
return fetch(`${Setting.ServerUrl}/api/update-user?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newUser),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function addUser(user) {
|
||||
let newUser = Setting.deepCopy(user);
|
||||
return fetch(`${Setting.ServerUrl}/api/add-user`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newUser),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function deleteUser(user) {
|
||||
let newUser = Setting.deepCopy(user);
|
||||
return fetch(`${Setting.ServerUrl}/api/delete-user`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newUser),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getGlobalUsers() {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-global-users`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getUsers(owner) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-users?owner=${owner}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getUser(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-user?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function updateUser(owner, name, user) {
|
||||
let newUser = Setting.deepCopy(user);
|
||||
return fetch(`${Setting.ServerUrl}/api/update-user?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newUser),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function addUser(user) {
|
||||
let newUser = Setting.deepCopy(user);
|
||||
return fetch(`${Setting.ServerUrl}/api/add-user`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newUser),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function deleteUser(user) {
|
||||
let newUser = Setting.deepCopy(user);
|
||||
return fetch(`${Setting.ServerUrl}/api/delete-user`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newUser),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
23244
web/yarn.lock
23244
web/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user