Change CRLF to LF.

This commit is contained in:
Yang Luo 2021-02-13 12:15:19 +08:00
parent 7304e62f95
commit 09b39d69f6
19 changed files with 13694 additions and 13694 deletions

View File

@ -1,224 +1,224 @@
import React from "react"; import React from "react";
import {Button, Card, Col, Input, Row, Select} from 'antd'; import {Button, Card, Col, Input, Row, Select} from 'antd';
import {LinkOutlined} from "@ant-design/icons"; import {LinkOutlined} from "@ant-design/icons";
import * as ApplicationBackend from "./backend/ApplicationBackend"; import * as ApplicationBackend from "./backend/ApplicationBackend";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
import * as ProviderBackend from "./backend/ProviderBackend"; import * as ProviderBackend from "./backend/ProviderBackend";
import * as OrganizationBackend from "./backend/OrganizationBackend"; import * as OrganizationBackend from "./backend/OrganizationBackend";
import Face from "./Face"; import Face from "./Face";
const { Option } = Select; const { Option } = Select;
class ApplicationEditPage extends React.Component { class ApplicationEditPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
applicationName: props.match.params.applicationName, applicationName: props.match.params.applicationName,
application: null, application: null,
organizations: [], organizations: [],
providers: [], providers: [],
}; };
} }
componentWillMount() { componentWillMount() {
this.getApplication(); this.getApplication();
this.getOrganizations(); this.getOrganizations();
this.getProviders(); this.getProviders();
} }
getApplication() { getApplication() {
ApplicationBackend.getApplication("admin", this.state.applicationName) ApplicationBackend.getApplication("admin", this.state.applicationName)
.then((application) => { .then((application) => {
this.setState({ this.setState({
application: application, application: application,
}); });
}); });
} }
getOrganizations() { getOrganizations() {
OrganizationBackend.getOrganizations("admin") OrganizationBackend.getOrganizations("admin")
.then((res) => { .then((res) => {
this.setState({ this.setState({
organizations: res, organizations: res,
}); });
}); });
} }
getProviders() { getProviders() {
ProviderBackend.getProviders("admin") ProviderBackend.getProviders("admin")
.then((res) => { .then((res) => {
this.setState({ this.setState({
providers: res, providers: res,
}); });
}); });
} }
parseApplicationField(key, value) { parseApplicationField(key, value) {
// if ([].includes(key)) { // if ([].includes(key)) {
// value = Setting.myParseInt(value); // value = Setting.myParseInt(value);
// } // }
return value; return value;
} }
updateApplicationField(key, value) { updateApplicationField(key, value) {
value = this.parseApplicationField(key, value); value = this.parseApplicationField(key, value);
let application = this.state.application; let application = this.state.application;
application[key] = value; application[key] = value;
this.setState({ this.setState({
application: application, application: application,
}); });
} }
renderApplication() { renderApplication() {
return ( return (
<Card size="small" title={ <Card size="small" title={
<div> <div>
Edit Application&nbsp;&nbsp;&nbsp;&nbsp; Edit Application&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitApplicationEdit.bind(this)}>Save</Button> <Button type="primary" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
</div> </div>
} style={{marginLeft: '5px'}} type="inner"> } style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} > <Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Name: Name:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.application.name} onChange={e => { <Input value={this.state.application.name} onChange={e => {
this.updateApplicationField('name', e.target.value); this.updateApplicationField('name', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Display Name: Display Name:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.application.displayName} onChange={e => { <Input value={this.state.application.displayName} onChange={e => {
this.updateApplicationField('displayName', e.target.value); this.updateApplicationField('displayName', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Logo: Logo:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={1}> <Col style={{marginTop: '5px'}} span={1}>
URL: URL:
</Col> </Col>
<Col span={23} > <Col span={23} >
<Input prefix={<LinkOutlined/>} value={this.state.application.logo} onChange={e => { <Input prefix={<LinkOutlined/>} value={this.state.application.logo} onChange={e => {
this.updateApplicationField('logo', e.target.value); this.updateApplicationField('logo', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={1}> <Col style={{marginTop: '5px'}} span={1}>
Preview: Preview:
</Col> </Col>
<Col span={23} > <Col span={23} >
<a target="_blank" href={this.state.application.logo}> <a target="_blank" href={this.state.application.logo}>
<img src={this.state.application.logo} alt={this.state.application.logo} height={90} style={{marginBottom: '20px'}}/> <img src={this.state.application.logo} alt={this.state.application.logo} height={90} style={{marginBottom: '20px'}}/>
</a> </a>
</Col> </Col>
</Row> </Row>
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Organization: Organization:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Select virtual={false} style={{width: '100%'}} value={this.state.application.organization} onChange={(value => {this.updateApplicationField('organization', value);})}> <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>) this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
} }
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Providers: Providers:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Select mode="tags" style={{width: '100%'}} <Select mode="tags" style={{width: '100%'}}
value={this.state.application.providers} value={this.state.application.providers}
onChange={value => { onChange={value => {
this.updateApplicationField('providers', value); this.updateApplicationField('providers', value);
}} > }} >
{ {
this.state.providers.map((provider, index) => <Option key={index} value={provider.name}>{provider.name}</Option>) this.state.providers.map((provider, index) => <Option key={index} value={provider.name}>{provider.name}</Option>)
} }
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Face Preview: Face Preview:
</Col> </Col>
<Col span={22} > <Col span={22} >
<a style={{marginBottom: '10px'}} target="_blank" href={`/doors/${this.state.application.name}`}> <a style={{marginBottom: '10px'}} target="_blank" href={`/doors/${this.state.application.name}`}>
{ {
`${window.location.host}/doors/${this.state.application.name}` `${window.location.host}/doors/${this.state.application.name}`
} }
</a> </a>
<br/> <br/>
<br/> <br/>
<div style={{width: "500px", height: "600px", border: "1px solid rgb(217,217,217)"}}> <div style={{width: "500px", height: "600px", border: "1px solid rgb(217,217,217)"}}>
<Face application={this.state.application} /> <Face application={this.state.application} />
</div> </div>
</Col> </Col>
</Row> </Row>
</Card> </Card>
) )
} }
submitApplicationEdit() { submitApplicationEdit() {
let application = Setting.deepCopy(this.state.application); let application = Setting.deepCopy(this.state.application);
ApplicationBackend.updateApplication(this.state.application.owner, this.state.applicationName, application) ApplicationBackend.updateApplication(this.state.application.owner, this.state.applicationName, application)
.then((res) => { .then((res) => {
if (res) { if (res) {
Setting.showMessage("success", `Successfully saved`); Setting.showMessage("success", `Successfully saved`);
this.setState({ this.setState({
applicationName: this.state.application.name, applicationName: this.state.application.name,
}); });
this.props.history.push(`/applications/${this.state.application.name}`); this.props.history.push(`/applications/${this.state.application.name}`);
} else { } else {
Setting.showMessage("error", `failed to save: server side failure`); Setting.showMessage("error", `failed to save: server side failure`);
this.updateApplicationField('name', this.state.applicationName); this.updateApplicationField('name', this.state.applicationName);
} }
}) })
.catch(error => { .catch(error => {
Setting.showMessage("error", `failed to save: ${error}`); Setting.showMessage("error", `failed to save: ${error}`);
}); });
} }
render() { render() {
return ( return (
<div> <div>
<Row style={{width: "100%"}}> <Row style={{width: "100%"}}>
<Col span={1}> <Col span={1}>
</Col> </Col>
<Col span={22}> <Col span={22}>
{ {
this.state.application !== null ? this.renderApplication() : null this.state.application !== null ? this.renderApplication() : null
} }
</Col> </Col>
<Col span={1}> <Col span={1}>
</Col> </Col>
</Row> </Row>
<Row style={{margin: 10}}> <Row style={{margin: 10}}>
<Col span={2}> <Col span={2}>
</Col> </Col>
<Col span={18}> <Col span={18}>
<Button type="primary" size="large" onClick={this.submitApplicationEdit.bind(this)}>Save</Button> <Button type="primary" size="large" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
); );
} }
} }
export default ApplicationEditPage; export default ApplicationEditPage;

View File

@ -1,199 +1,199 @@
import React from "react"; import React from "react";
import {Link} from "react-router-dom"; import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd'; import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment"; import moment from "moment";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
import * as ApplicationBackend from "./backend/ApplicationBackend"; import * as ApplicationBackend from "./backend/ApplicationBackend";
class ApplicationListPage extends React.Component { class ApplicationListPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
applications: null, applications: null,
}; };
} }
componentWillMount() { componentWillMount() {
this.getApplications(); this.getApplications();
} }
getApplications() { getApplications() {
ApplicationBackend.getApplications("admin") ApplicationBackend.getApplications("admin")
.then((res) => { .then((res) => {
this.setState({ this.setState({
applications: res, applications: res,
}); });
}); });
} }
newApplication() { newApplication() {
return { return {
owner: "admin", // this.props.account.applicationname, owner: "admin", // this.props.account.applicationname,
name: `application_${this.state.applications.length}`, name: `application_${this.state.applications.length}`,
createdTime: moment().format(), createdTime: moment().format(),
displayName: `New Application - ${this.state.applications.length}`, displayName: `New Application - ${this.state.applications.length}`,
logo: "https://cdn.jsdelivr.net/gh/casbin/static/img/logo@2x.png", logo: "https://cdn.jsdelivr.net/gh/casbin/static/img/logo@2x.png",
providers: [], providers: [],
} }
} }
addApplication() { addApplication() {
const newApplication = this.newApplication(); const newApplication = this.newApplication();
ApplicationBackend.addApplication(newApplication) ApplicationBackend.addApplication(newApplication)
.then((res) => { .then((res) => {
Setting.showMessage("success", `Application added successfully`); Setting.showMessage("success", `Application added successfully`);
this.setState({ this.setState({
applications: Setting.prependRow(this.state.applications, newApplication), applications: Setting.prependRow(this.state.applications, newApplication),
}); });
} }
) )
.catch(error => { .catch(error => {
Setting.showMessage("error", `Application failed to add: ${error}`); Setting.showMessage("error", `Application failed to add: ${error}`);
}); });
} }
deleteApplication(i) { deleteApplication(i) {
ApplicationBackend.deleteApplication(this.state.applications[i]) ApplicationBackend.deleteApplication(this.state.applications[i])
.then((res) => { .then((res) => {
Setting.showMessage("success", `Application deleted successfully`); Setting.showMessage("success", `Application deleted successfully`);
this.setState({ this.setState({
applications: Setting.deleteRow(this.state.applications, i), applications: Setting.deleteRow(this.state.applications, i),
}); });
} }
) )
.catch(error => { .catch(error => {
Setting.showMessage("error", `Application failed to delete: ${error}`); Setting.showMessage("error", `Application failed to delete: ${error}`);
}); });
} }
renderTable(applications) { renderTable(applications) {
const columns = [ const columns = [
{ {
title: 'Name', title: 'Name',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
width: '150px', width: '150px',
sorter: (a, b) => a.name.localeCompare(b.name), sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<Link to={`/applications/${text}`}> <Link to={`/applications/${text}`}>
{text} {text}
</Link> </Link>
) )
} }
}, },
{ {
title: 'Created Time', title: 'Created Time',
dataIndex: 'createdTime', dataIndex: 'createdTime',
key: 'createdTime', key: 'createdTime',
width: '160px', width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime), sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => { render: (text, record, index) => {
return Setting.getFormattedDate(text); return Setting.getFormattedDate(text);
} }
}, },
{ {
title: 'Display Name', title: 'Display Name',
dataIndex: 'displayName', dataIndex: 'displayName',
key: 'displayName', key: 'displayName',
// width: '100px', // width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName), sorter: (a, b) => a.displayName.localeCompare(b.displayName),
}, },
{ {
title: 'Logo', title: 'Logo',
dataIndex: 'logo', dataIndex: 'logo',
key: 'logo', key: 'logo',
width: '250px', width: '250px',
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<a target="_blank" href={text}> <a target="_blank" href={text}>
<img src={text} alt={text} width={150} /> <img src={text} alt={text} width={150} />
</a> </a>
) )
} }
}, },
{ {
title: 'Organization', title: 'Organization',
dataIndex: 'organization', dataIndex: 'organization',
key: 'organization', key: 'organization',
width: '200px', width: '200px',
sorter: (a, b) => a.organization.localeCompare(b.organization), sorter: (a, b) => a.organization.localeCompare(b.organization),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<a href={`/organizations/${text}`}> <a href={`/organizations/${text}`}>
{text} {text}
</a> </a>
) )
} }
}, },
{ {
title: 'Providers', title: 'Providers',
dataIndex: 'providers', dataIndex: 'providers',
key: 'providers', key: 'providers',
width: '200px', width: '200px',
sorter: (a, b) => a.providers.localeCompare(b.providers), sorter: (a, b) => a.providers.localeCompare(b.providers),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<a href={`/providers/${text}`}> <a href={`/providers/${text}`}>
{text} {text}
</a> </a>
) )
} }
}, },
{ {
title: 'Action', title: 'Action',
dataIndex: '', dataIndex: '',
key: 'op', key: 'op',
width: '170px', width: '170px',
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<div> <div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/applications/${record.name}`)}>Edit</Button> <Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/applications/${record.name}`)}>Edit</Button>
<Popconfirm <Popconfirm
title={`Sure to delete application: ${record.name} ?`} title={`Sure to delete application: ${record.name} ?`}
onConfirm={() => this.deleteApplication(index)} onConfirm={() => this.deleteApplication(index)}
> >
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button> <Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm> </Popconfirm>
</div> </div>
) )
} }
}, },
]; ];
return ( return (
<div> <div>
<Table columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => ( title={() => (
<div> <div>
Applications&nbsp;&nbsp;&nbsp;&nbsp; Applications&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addApplication.bind(this)}>Add</Button> <Button type="primary" size="small" onClick={this.addApplication.bind(this)}>Add</Button>
</div> </div>
)} )}
loading={applications === null} loading={applications === null}
/> />
</div> </div>
); );
} }
render() { render() {
return ( return (
<div> <div>
<Row style={{width: "100%"}}> <Row style={{width: "100%"}}>
<Col span={1}> <Col span={1}>
</Col> </Col>
<Col span={22}> <Col span={22}>
{ {
this.renderTable(this.state.applications) this.renderTable(this.state.applications)
} }
</Col> </Col>
<Col span={1}> <Col span={1}>
</Col> </Col>
</Row> </Row>
</div> </div>
); );
} }
} }
export default ApplicationListPage; export default ApplicationListPage;

View File

@ -1,129 +1,129 @@
import React from "react"; import React from "react";
import {Button, Checkbox, Col, Form, Input, Row} from "antd"; import {Button, Checkbox, Col, Form, Input, Row} from "antd";
import {LockOutlined, UserOutlined} from "@ant-design/icons"; import {LockOutlined, UserOutlined} from "@ant-design/icons";
import * as ApplicationBackend from "./backend/ApplicationBackend"; import * as ApplicationBackend from "./backend/ApplicationBackend";
import * as AccountBackend from "./backend/AccountBackend"; import * as AccountBackend from "./backend/AccountBackend";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
class Face extends React.Component { class Face extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
applicationName: props.applicationName !== undefined ? props.applicationName : (props.match === undefined ? null : props.match.params.applicationName), applicationName: props.applicationName !== undefined ? props.applicationName : (props.match === undefined ? null : props.match.params.applicationName),
application: null, application: null,
}; };
} }
componentWillMount() { componentWillMount() {
this.getApplication(); this.getApplication();
} }
getApplication() { getApplication() {
ApplicationBackend.getApplication("admin", this.state.applicationName) ApplicationBackend.getApplication("admin", this.state.applicationName)
.then((application) => { .then((application) => {
this.setState({ this.setState({
application: application, application: application,
}); });
}); });
} }
getApplicationObj() { getApplicationObj() {
if (this.props.application !== undefined) { if (this.props.application !== undefined) {
return this.props.application; return this.props.application;
} else { } else {
return this.state.application; return this.state.application;
} }
} }
onFinish(values) { onFinish(values) {
AccountBackend.login(values) AccountBackend.login(values)
.then((res) => { .then((res) => {
if (res.status === 'ok') { if (res.status === 'ok') {
this.props.onLoggedIn(); this.props.onLoggedIn();
Setting.showMessage("success", `Logged in successfully`); Setting.showMessage("success", `Logged in successfully`);
Setting.goToLink("/"); Setting.goToLink("/");
} else { } else {
Setting.showMessage("error", `Log in failed${res.msg}`); Setting.showMessage("error", `Log in failed${res.msg}`);
} }
}); });
}; };
renderForm() { renderForm() {
return ( return (
<Form <Form
name="normal_login" name="normal_login"
initialValues={{ initialValues={{
organization: this.getApplicationObj().organization, organization: this.getApplicationObj().organization,
remember: true remember: true
}} }}
onFinish={this.onFinish.bind(this)} onFinish={this.onFinish.bind(this)}
style={{width: "250px"}} style={{width: "250px"}}
size="large" size="large"
> >
<Form.Item <Form.Item
name="username" name="username"
rules={[{ required: true, message: 'Please input your Username!' }]} rules={[{ required: true, message: 'Please input your Username!' }]}
> >
<Input <Input
prefix={<UserOutlined className="site-form-item-icon" />} prefix={<UserOutlined className="site-form-item-icon" />}
placeholder="username" placeholder="username"
/> />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="password" name="password"
rules={[{ required: true, message: 'Please input your Password!' }]} rules={[{ required: true, message: 'Please input your Password!' }]}
> >
<Input <Input
prefix={<LockOutlined className="site-form-item-icon" />} prefix={<LockOutlined className="site-form-item-icon" />}
type="password" type="password"
placeholder="password" placeholder="password"
/> />
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Form.Item name="remember" valuePropName="checked" noStyle> <Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox style={{float: "left"}}>Auto login</Checkbox> <Checkbox style={{float: "left"}}>Auto login</Checkbox>
</Form.Item> </Form.Item>
<a style={{float: "right"}} href=""> <a style={{float: "right"}} href="">
Forgot password? Forgot password?
</a> </a>
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Button <Button
type="primary" type="primary"
htmlType="submit" htmlType="submit"
style={{width: "100%"}} style={{width: "100%"}}
> >
Login Login
</Button> </Button>
<div style={{float: "right"}}> <div style={{float: "right"}}>
No account yet, <a href="/register">sign up now</a> No account yet, <a href="/register">sign up now</a>
</div> </div>
</Form.Item> </Form.Item>
</Form> </Form>
); );
} }
render() { render() {
const application = this.getApplicationObj(); const application = this.getApplicationObj();
if (application === null) { if (application === null) {
return null; return null;
} }
return ( return (
<Row> <Row>
<Col span={24} style={{display: "flex", justifyContent: "center"}} > <Col span={24} style={{display: "flex", justifyContent: "center"}} >
<div style={{marginTop: "80px", textAlign: "center"}}> <div style={{marginTop: "80px", textAlign: "center"}}>
<img src={application.logo} alt={application.displayName} style={{marginBottom: '50px'}}/> <img src={application.logo} alt={application.displayName} style={{marginBottom: '50px'}}/>
{ {
this.renderForm(application) this.renderForm(application)
} }
</div> </div>
</Col> </Col>
</Row> </Row>
) )
} }
} }
export default Face; export default Face;

View File

@ -1,18 +1,18 @@
import React from "react"; import React from "react";
class HomePage extends React.Component { class HomePage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
}; };
} }
render() { render() {
return ( return (
"home" "home"
) )
} }
} }
export default HomePage; export default HomePage;

View File

@ -1,135 +1,135 @@
import React from "react"; import React from "react";
import {Button, Card, Col, Input, Row} from 'antd'; import {Button, Card, Col, Input, Row} from 'antd';
import {LinkOutlined} from "@ant-design/icons"; import {LinkOutlined} from "@ant-design/icons";
import * as OrganizationBackend from "./backend/OrganizationBackend"; import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
class OrganizationEditPage extends React.Component { class OrganizationEditPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
organizationName: props.match.params.organizationName, organizationName: props.match.params.organizationName,
organization: null, organization: null,
}; };
} }
componentWillMount() { componentWillMount() {
this.getOrganization(); this.getOrganization();
} }
getOrganization() { getOrganization() {
OrganizationBackend.getOrganization("admin", this.state.organizationName) OrganizationBackend.getOrganization("admin", this.state.organizationName)
.then((organization) => { .then((organization) => {
this.setState({ this.setState({
organization: organization, organization: organization,
}); });
}); });
} }
parseOrganizationField(key, value) { parseOrganizationField(key, value) {
// if ([].includes(key)) { // if ([].includes(key)) {
// value = Setting.myParseInt(value); // value = Setting.myParseInt(value);
// } // }
return value; return value;
} }
updateOrganizationField(key, value) { updateOrganizationField(key, value) {
value = this.parseOrganizationField(key, value); value = this.parseOrganizationField(key, value);
let organization = this.state.organization; let organization = this.state.organization;
organization[key] = value; organization[key] = value;
this.setState({ this.setState({
organization: organization, organization: organization,
}); });
} }
renderOrganization() { renderOrganization() {
return ( return (
<Card size="small" title={ <Card size="small" title={
<div> <div>
Edit Organization&nbsp;&nbsp;&nbsp;&nbsp; Edit Organization&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button> <Button type="primary" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
</div> </div>
} style={{marginLeft: '5px'}} type="inner"> } style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} > <Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Name: Name:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.organization.name} onChange={e => { <Input value={this.state.organization.name} onChange={e => {
this.updateOrganizationField('name', e.target.value); this.updateOrganizationField('name', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Display Name: Display Name:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.organization.displayName} onChange={e => { <Input value={this.state.organization.displayName} onChange={e => {
this.updateOrganizationField('displayName', e.target.value); this.updateOrganizationField('displayName', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Website Url: Website Url:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.organization.websiteUrl} onChange={e => { <Input value={this.state.organization.websiteUrl} onChange={e => {
this.updateOrganizationField('websiteUrl', e.target.value); this.updateOrganizationField('websiteUrl', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
</Card> </Card>
) )
} }
submitOrganizationEdit() { submitOrganizationEdit() {
let organization = Setting.deepCopy(this.state.organization); let organization = Setting.deepCopy(this.state.organization);
OrganizationBackend.updateOrganization(this.state.organization.owner, this.state.organizationName, organization) OrganizationBackend.updateOrganization(this.state.organization.owner, this.state.organizationName, organization)
.then((res) => { .then((res) => {
if (res) { if (res) {
Setting.showMessage("success", `Successfully saved`); Setting.showMessage("success", `Successfully saved`);
this.setState({ this.setState({
organizationName: this.state.organization.name, organizationName: this.state.organization.name,
}); });
this.props.history.push(`/organizations/${this.state.organization.name}`); this.props.history.push(`/organizations/${this.state.organization.name}`);
} else { } else {
Setting.showMessage("error", `failed to save: server side failure`); Setting.showMessage("error", `failed to save: server side failure`);
this.updateOrganizationField('name', this.state.organizationName); this.updateOrganizationField('name', this.state.organizationName);
} }
}) })
.catch(error => { .catch(error => {
Setting.showMessage("error", `failed to save: ${error}`); Setting.showMessage("error", `failed to save: ${error}`);
}); });
} }
render() { render() {
return ( return (
<div> <div>
<Row style={{width: "100%"}}> <Row style={{width: "100%"}}>
<Col span={1}> <Col span={1}>
</Col> </Col>
<Col span={22}> <Col span={22}>
{ {
this.state.organization !== null ? this.renderOrganization() : null this.state.organization !== null ? this.renderOrganization() : null
} }
</Col> </Col>
<Col span={1}> <Col span={1}>
</Col> </Col>
</Row> </Row>
<Row style={{margin: 10}}> <Row style={{margin: 10}}>
<Col span={2}> <Col span={2}>
</Col> </Col>
<Col span={18}> <Col span={18}>
<Button type="primary" size="large" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button> <Button type="primary" size="large" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
); );
} }
} }
export default OrganizationEditPage; export default OrganizationEditPage;

View File

@ -1,171 +1,171 @@
import React from "react"; import React from "react";
import {Link} from "react-router-dom"; import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd'; import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment"; import moment from "moment";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
import * as OrganizationBackend from "./backend/OrganizationBackend"; import * as OrganizationBackend from "./backend/OrganizationBackend";
class OrganizationListPage extends React.Component { class OrganizationListPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
organizations: null, organizations: null,
}; };
} }
componentWillMount() { componentWillMount() {
this.getOrganizations(); this.getOrganizations();
} }
getOrganizations() { getOrganizations() {
OrganizationBackend.getOrganizations("admin") OrganizationBackend.getOrganizations("admin")
.then((res) => { .then((res) => {
this.setState({ this.setState({
organizations: res, organizations: res,
}); });
}); });
} }
newOrganization() { newOrganization() {
return { return {
owner: "admin", // this.props.account.organizationname, owner: "admin", // this.props.account.organizationname,
name: `organization_${this.state.organizations.length}`, name: `organization_${this.state.organizations.length}`,
createdTime: moment().format(), createdTime: moment().format(),
displayName: `New Organization - ${this.state.organizations.length}`, displayName: `New Organization - ${this.state.organizations.length}`,
websiteUrl: "https://example.com", websiteUrl: "https://example.com",
} }
} }
addOrganization() { addOrganization() {
const newOrganization = this.newOrganization(); const newOrganization = this.newOrganization();
OrganizationBackend.addOrganization(newOrganization) OrganizationBackend.addOrganization(newOrganization)
.then((res) => { .then((res) => {
Setting.showMessage("success", `Organization added successfully`); Setting.showMessage("success", `Organization added successfully`);
this.setState({ this.setState({
organizations: Setting.prependRow(this.state.organizations, newOrganization), organizations: Setting.prependRow(this.state.organizations, newOrganization),
}); });
} }
) )
.catch(error => { .catch(error => {
Setting.showMessage("error", `Organization failed to add: ${error}`); Setting.showMessage("error", `Organization failed to add: ${error}`);
}); });
} }
deleteOrganization(i) { deleteOrganization(i) {
OrganizationBackend.deleteOrganization(this.state.organizations[i]) OrganizationBackend.deleteOrganization(this.state.organizations[i])
.then((res) => { .then((res) => {
Setting.showMessage("success", `Organization deleted successfully`); Setting.showMessage("success", `Organization deleted successfully`);
this.setState({ this.setState({
organizations: Setting.deleteRow(this.state.organizations, i), organizations: Setting.deleteRow(this.state.organizations, i),
}); });
} }
) )
.catch(error => { .catch(error => {
Setting.showMessage("error", `Organization failed to delete: ${error}`); Setting.showMessage("error", `Organization failed to delete: ${error}`);
}); });
} }
renderTable(organizations) { renderTable(organizations) {
const columns = [ const columns = [
{ {
title: 'Name', title: 'Name',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
width: '120px', width: '120px',
sorter: (a, b) => a.name.localeCompare(b.name), sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<Link to={`/organizations/${text}`}> <Link to={`/organizations/${text}`}>
{text} {text}
</Link> </Link>
) )
} }
}, },
{ {
title: 'Created Time', title: 'Created Time',
dataIndex: 'createdTime', dataIndex: 'createdTime',
key: 'createdTime', key: 'createdTime',
width: '160px', width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime), sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => { render: (text, record, index) => {
return Setting.getFormattedDate(text); return Setting.getFormattedDate(text);
} }
}, },
{ {
title: 'Display Name', title: 'Display Name',
dataIndex: 'displayName', dataIndex: 'displayName',
key: 'displayName', key: 'displayName',
// width: '100px', // width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName), sorter: (a, b) => a.displayName.localeCompare(b.displayName),
}, },
{ {
title: 'Website Url', title: 'Website Url',
dataIndex: 'websiteUrl', dataIndex: 'websiteUrl',
key: 'websiteUrl', key: 'websiteUrl',
width: '300px', width: '300px',
sorter: (a, b) => a.websiteUrl.localeCompare(b.websiteUrl), sorter: (a, b) => a.websiteUrl.localeCompare(b.websiteUrl),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<a target="_blank" href={text}> <a target="_blank" href={text}>
{text} {text}
</a> </a>
) )
} }
}, },
{ {
title: 'Action', title: 'Action',
dataIndex: '', dataIndex: '',
key: 'op', key: 'op',
width: '170px', width: '170px',
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<div> <div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/organizations/${record.name}`)}>Edit</Button> <Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/organizations/${record.name}`)}>Edit</Button>
<Popconfirm <Popconfirm
title={`Sure to delete organization: ${record.name} ?`} title={`Sure to delete organization: ${record.name} ?`}
onConfirm={() => this.deleteOrganization(index)} onConfirm={() => this.deleteOrganization(index)}
> >
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button> <Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm> </Popconfirm>
</div> </div>
) )
} }
}, },
]; ];
return ( return (
<div> <div>
<Table columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => ( title={() => (
<div> <div>
Organizations&nbsp;&nbsp;&nbsp;&nbsp; Organizations&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addOrganization.bind(this)}>Add</Button> <Button type="primary" size="small" onClick={this.addOrganization.bind(this)}>Add</Button>
</div> </div>
)} )}
loading={organizations === null} loading={organizations === null}
/> />
</div> </div>
); );
} }
render() { render() {
return ( return (
<div> <div>
<Row style={{width: "100%"}}> <Row style={{width: "100%"}}>
<Col span={1}> <Col span={1}>
</Col> </Col>
<Col span={22}> <Col span={22}>
{ {
this.renderTable(this.state.organizations) this.renderTable(this.state.organizations)
} }
</Col> </Col>
<Col span={1}> <Col span={1}>
</Col> </Col>
</Row> </Row>
</div> </div>
); );
} }
} }
export default OrganizationListPage; export default OrganizationListPage;

View File

@ -1,165 +1,165 @@
import React from "react"; import React from "react";
import {Button, Card, Col, Input, Row} from 'antd'; import {Button, Card, Col, Input, Row} from 'antd';
import {LinkOutlined} from "@ant-design/icons"; import {LinkOutlined} from "@ant-design/icons";
import * as ProviderBackend from "./backend/ProviderBackend"; import * as ProviderBackend from "./backend/ProviderBackend";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
class ProviderEditPage extends React.Component { class ProviderEditPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
providerName: props.match.params.providerName, providerName: props.match.params.providerName,
provider: null, provider: null,
}; };
} }
componentWillMount() { componentWillMount() {
this.getProvider(); this.getProvider();
} }
getProvider() { getProvider() {
ProviderBackend.getProvider("admin", this.state.providerName) ProviderBackend.getProvider("admin", this.state.providerName)
.then((provider) => { .then((provider) => {
this.setState({ this.setState({
provider: provider, provider: provider,
}); });
}); });
} }
parseProviderField(key, value) { parseProviderField(key, value) {
// if ([].includes(key)) { // if ([].includes(key)) {
// value = Setting.myParseInt(value); // value = Setting.myParseInt(value);
// } // }
return value; return value;
} }
updateProviderField(key, value) { updateProviderField(key, value) {
value = this.parseProviderField(key, value); value = this.parseProviderField(key, value);
let provider = this.state.provider; let provider = this.state.provider;
provider[key] = value; provider[key] = value;
this.setState({ this.setState({
provider: provider, provider: provider,
}); });
} }
renderProvider() { renderProvider() {
return ( return (
<Card size="small" title={ <Card size="small" title={
<div> <div>
Edit Provider&nbsp;&nbsp;&nbsp;&nbsp; Edit Provider&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitProviderEdit.bind(this)}>Save</Button> <Button type="primary" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
</div> </div>
} style={{marginLeft: '5px'}} type="inner"> } style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} > <Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Name: Name:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.provider.name} onChange={e => { <Input value={this.state.provider.name} onChange={e => {
this.updateProviderField('name', e.target.value); this.updateProviderField('name', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Display Name: Display Name:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.provider.displayName} onChange={e => { <Input value={this.state.provider.displayName} onChange={e => {
this.updateProviderField('displayName', e.target.value); this.updateProviderField('displayName', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
type: type:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.provider.type} onChange={e => { <Input value={this.state.provider.type} onChange={e => {
this.updateProviderField('type', e.target.value); this.updateProviderField('type', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Client Id: Client Id:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.provider.clientId} onChange={e => { <Input value={this.state.provider.clientId} onChange={e => {
this.updateProviderField('clientId', e.target.value); this.updateProviderField('clientId', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Client Secret: Client Secret:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.provider.clientSecret} onChange={e => { <Input value={this.state.provider.clientSecret} onChange={e => {
this.updateProviderField('clientSecret', e.target.value); this.updateProviderField('clientSecret', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Provider Url: Provider Url:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.provider.providerUrl} onChange={e => { <Input value={this.state.provider.providerUrl} onChange={e => {
this.updateProviderField('providerUrl', e.target.value); this.updateProviderField('providerUrl', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
</Card> </Card>
) )
} }
submitProviderEdit() { submitProviderEdit() {
let provider = Setting.deepCopy(this.state.provider); let provider = Setting.deepCopy(this.state.provider);
ProviderBackend.updateProvider(this.state.provider.owner, this.state.providerName, provider) ProviderBackend.updateProvider(this.state.provider.owner, this.state.providerName, provider)
.then((res) => { .then((res) => {
if (res) { if (res) {
Setting.showMessage("success", `Successfully saved`); Setting.showMessage("success", `Successfully saved`);
this.setState({ this.setState({
providerName: this.state.provider.name, providerName: this.state.provider.name,
}); });
this.props.history.push(`/providers/${this.state.provider.name}`); this.props.history.push(`/providers/${this.state.provider.name}`);
} else { } else {
Setting.showMessage("error", `failed to save: server side failure`); Setting.showMessage("error", `failed to save: server side failure`);
this.updateProviderField('name', this.state.providerName); this.updateProviderField('name', this.state.providerName);
} }
}) })
.catch(error => { .catch(error => {
Setting.showMessage("error", `failed to save: ${error}`); Setting.showMessage("error", `failed to save: ${error}`);
}); });
} }
render() { render() {
return ( return (
<div> <div>
<Row style={{width: "100%"}}> <Row style={{width: "100%"}}>
<Col span={1}> <Col span={1}>
</Col> </Col>
<Col span={22}> <Col span={22}>
{ {
this.state.provider !== null ? this.renderProvider() : null this.state.provider !== null ? this.renderProvider() : null
} }
</Col> </Col>
<Col span={1}> <Col span={1}>
</Col> </Col>
</Row> </Row>
<Row style={{margin: 10}}> <Row style={{margin: 10}}>
<Col span={2}> <Col span={2}>
</Col> </Col>
<Col span={18}> <Col span={18}>
<Button type="primary" size="large" onClick={this.submitProviderEdit.bind(this)}>Save</Button> <Button type="primary" size="large" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
); );
} }
} }
export default ProviderEditPage; export default ProviderEditPage;

View File

@ -1,195 +1,195 @@
import React from "react"; import React from "react";
import {Link} from "react-router-dom"; import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd'; import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment"; import moment from "moment";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
import * as ProviderBackend from "./backend/ProviderBackend"; import * as ProviderBackend from "./backend/ProviderBackend";
class ProviderListPage extends React.Component { class ProviderListPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
providers: null, providers: null,
}; };
} }
componentWillMount() { componentWillMount() {
this.getProviders(); this.getProviders();
} }
getProviders() { getProviders() {
ProviderBackend.getProviders("admin") ProviderBackend.getProviders("admin")
.then((res) => { .then((res) => {
this.setState({ this.setState({
providers: res, providers: res,
}); });
}); });
} }
newProvider() { newProvider() {
return { return {
owner: "admin", // this.props.account.providername, owner: "admin", // this.props.account.providername,
name: `provider_${this.state.providers.length}`, name: `provider_${this.state.providers.length}`,
createdTime: moment().format(), createdTime: moment().format(),
displayName: `New Provider - ${this.state.providers.length}`, displayName: `New Provider - ${this.state.providers.length}`,
type: "github", type: "github",
clientId: "", clientId: "",
clientSecret: "", clientSecret: "",
providerUrl: "https://github.com/organizations/xxx/settings/applications/1234567", providerUrl: "https://github.com/organizations/xxx/settings/applications/1234567",
} }
} }
addProvider() { addProvider() {
const newProvider = this.newProvider(); const newProvider = this.newProvider();
ProviderBackend.addProvider(newProvider) ProviderBackend.addProvider(newProvider)
.then((res) => { .then((res) => {
Setting.showMessage("success", `Provider added successfully`); Setting.showMessage("success", `Provider added successfully`);
this.setState({ this.setState({
providers: Setting.prependRow(this.state.providers, newProvider), providers: Setting.prependRow(this.state.providers, newProvider),
}); });
} }
) )
.catch(error => { .catch(error => {
Setting.showMessage("error", `Provider failed to add: ${error}`); Setting.showMessage("error", `Provider failed to add: ${error}`);
}); });
} }
deleteProvider(i) { deleteProvider(i) {
ProviderBackend.deleteProvider(this.state.providers[i]) ProviderBackend.deleteProvider(this.state.providers[i])
.then((res) => { .then((res) => {
Setting.showMessage("success", `Provider deleted successfully`); Setting.showMessage("success", `Provider deleted successfully`);
this.setState({ this.setState({
providers: Setting.deleteRow(this.state.providers, i), providers: Setting.deleteRow(this.state.providers, i),
}); });
} }
) )
.catch(error => { .catch(error => {
Setting.showMessage("error", `Provider failed to delete: ${error}`); Setting.showMessage("error", `Provider failed to delete: ${error}`);
}); });
} }
renderTable(providers) { renderTable(providers) {
const columns = [ const columns = [
{ {
title: 'Name', title: 'Name',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
width: '120px', width: '120px',
sorter: (a, b) => a.name.localeCompare(b.name), sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<Link to={`/providers/${text}`}> <Link to={`/providers/${text}`}>
{text} {text}
</Link> </Link>
) )
} }
}, },
{ {
title: 'Created Time', title: 'Created Time',
dataIndex: 'createdTime', dataIndex: 'createdTime',
key: 'createdTime', key: 'createdTime',
width: '160px', width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime), sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => { render: (text, record, index) => {
return Setting.getFormattedDate(text); return Setting.getFormattedDate(text);
} }
}, },
{ {
title: 'Display Name', title: 'Display Name',
dataIndex: 'displayName', dataIndex: 'displayName',
key: 'displayName', key: 'displayName',
// width: '100px', // width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName), sorter: (a, b) => a.displayName.localeCompare(b.displayName),
}, },
{ {
title: 'Type', title: 'Type',
dataIndex: 'type', dataIndex: 'type',
key: 'type', key: 'type',
width: '150px', width: '150px',
sorter: (a, b) => a.type.localeCompare(b.type), sorter: (a, b) => a.type.localeCompare(b.type),
}, },
{ {
title: 'Client Id', title: 'Client Id',
dataIndex: 'clientId', dataIndex: 'clientId',
key: 'clientId', key: 'clientId',
width: '150px', width: '150px',
sorter: (a, b) => a.clientId.localeCompare(b.clientId), sorter: (a, b) => a.clientId.localeCompare(b.clientId),
}, },
{ {
title: 'Client Secret', title: 'Client Secret',
dataIndex: 'clientSecret', dataIndex: 'clientSecret',
key: 'clientSecret', key: 'clientSecret',
width: '150px', width: '150px',
sorter: (a, b) => a.clientSecret.localeCompare(b.clientSecret), sorter: (a, b) => a.clientSecret.localeCompare(b.clientSecret),
}, },
{ {
title: 'Provider Url', title: 'Provider Url',
dataIndex: 'providerUrl', dataIndex: 'providerUrl',
key: 'providerUrl', key: 'providerUrl',
width: '150px', width: '150px',
sorter: (a, b) => a.providerUrl.localeCompare(b.providerUrl), sorter: (a, b) => a.providerUrl.localeCompare(b.providerUrl),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<a target="_blank" href={text}> <a target="_blank" href={text}>
{text} {text}
</a> </a>
) )
} }
}, },
{ {
title: 'Action', title: 'Action',
dataIndex: '', dataIndex: '',
key: 'op', key: 'op',
width: '170px', width: '170px',
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<div> <div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/providers/${record.name}`)}>Edit</Button> <Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/providers/${record.name}`)}>Edit</Button>
<Popconfirm <Popconfirm
title={`Sure to delete provider: ${record.name} ?`} title={`Sure to delete provider: ${record.name} ?`}
onConfirm={() => this.deleteProvider(index)} onConfirm={() => this.deleteProvider(index)}
> >
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button> <Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm> </Popconfirm>
</div> </div>
) )
} }
}, },
]; ];
return ( return (
<div> <div>
<Table columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => ( title={() => (
<div> <div>
Providers&nbsp;&nbsp;&nbsp;&nbsp; Providers&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addProvider.bind(this)}>Add</Button> <Button type="primary" size="small" onClick={this.addProvider.bind(this)}>Add</Button>
</div> </div>
)} )}
loading={providers === null} loading={providers === null}
/> />
</div> </div>
); );
} }
render() { render() {
return ( return (
<div> <div>
<Row style={{width: "100%"}}> <Row style={{width: "100%"}}>
<Col span={1}> <Col span={1}>
</Col> </Col>
<Col span={22}> <Col span={22}>
{ {
this.renderTable(this.state.providers) this.renderTable(this.state.providers)
} }
</Col> </Col>
<Col span={1}> <Col span={1}>
</Col> </Col>
</Row> </Row>
</div> </div>
); );
} }
} }
export default ProviderListPage; export default ProviderListPage;

View File

@ -1,125 +1,125 @@
// Copyright 2020 The casbin Authors. All Rights Reserved. // Copyright 2020 The casbin Authors. All Rights Reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import {message} from "antd"; import {message} from "antd";
import React from "react"; import React from "react";
import {isMobile as isMobileDevice} from "react-device-detect"; import {isMobile as isMobileDevice} from "react-device-detect";
export let ServerUrl = ''; export let ServerUrl = '';
export function initServerUrl() { export function initServerUrl() {
const hostname = window.location.hostname; const hostname = window.location.hostname;
if (hostname === 'localhost') { if (hostname === 'localhost') {
ServerUrl = `http://${hostname}:8000`; ServerUrl = `http://${hostname}:8000`;
} }
} }
export function parseJson(s) { export function parseJson(s) {
if (s === "") { if (s === "") {
return null; return null;
} else { } else {
return JSON.parse(s); return JSON.parse(s);
} }
} }
export function myParseInt(i) { export function myParseInt(i) {
const res = parseInt(i); const res = parseInt(i);
return isNaN(res) ? 0 : res; return isNaN(res) ? 0 : res;
} }
export function openLink(link) { export function openLink(link) {
// this.props.history.push(link); // this.props.history.push(link);
const w = window.open('about:blank'); const w = window.open('about:blank');
w.location.href = link; w.location.href = link;
} }
export function goToLink(link) { export function goToLink(link) {
window.location.href = link; window.location.href = link;
} }
export function showMessage(type, text) { export function showMessage(type, text) {
if (type === "") { if (type === "") {
return; return;
} else if (type === "success") { } else if (type === "success") {
message.success(text); message.success(text);
} else if (type === "error") { } else if (type === "error") {
message.error(text); message.error(text);
} }
} }
export function deepCopy(obj) { export function deepCopy(obj) {
return Object.assign({}, obj); return Object.assign({}, obj);
} }
export function addRow(array, row) { export function addRow(array, row) {
return [...array, row]; return [...array, row];
} }
export function prependRow(array, row) { export function prependRow(array, row) {
return [row, ...array]; return [row, ...array];
} }
export function deleteRow(array, i) { export function deleteRow(array, i) {
// return array = array.slice(0, i).concat(array.slice(i + 1)); // return array = array.slice(0, i).concat(array.slice(i + 1));
return [...array.slice(0, i), ...array.slice(i + 1)]; return [...array.slice(0, i), ...array.slice(i + 1)];
} }
export function swapRow(array, i, j) { export function swapRow(array, i, j) {
return [...array.slice(0, i), array[j], ...array.slice(i + 1, j), array[i], ...array.slice(j + 1)]; return [...array.slice(0, i), array[j], ...array.slice(i + 1, j), array[i], ...array.slice(j + 1)];
} }
export function isMobile() { export function isMobile() {
// return getIsMobileView(); // return getIsMobileView();
return isMobileDevice; return isMobileDevice;
} }
export function getFormattedDate(date) { export function getFormattedDate(date) {
if (date === undefined) { if (date === undefined) {
return null; return null;
} }
date = date.replace('T', ' '); date = date.replace('T', ' ');
date = date.replace('+08:00', ' '); date = date.replace('+08:00', ' ');
return date; return date;
} }
export function getFormattedDateShort(date) { export function getFormattedDateShort(date) {
return date.slice(0, 10); return date.slice(0, 10);
} }
export function getShortName(s) { export function getShortName(s) {
return s.split('/').slice(-1)[0]; return s.split('/').slice(-1)[0];
} }
function getRandomInt(s) { function getRandomInt(s) {
let hash = 0; let hash = 0;
if (s.length !== 0) { if (s.length !== 0) {
for (let i = 0; i < s.length; i ++) { for (let i = 0; i < s.length; i ++) {
let char = s.charCodeAt(i); let char = s.charCodeAt(i);
hash = ((hash << 5) - hash) + char; hash = ((hash << 5) - hash) + char;
hash = hash & hash; hash = hash & hash;
} }
} }
return hash; return hash;
} }
export function getAvatarColor(s) { export function getAvatarColor(s) {
const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae']; const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
let random = getRandomInt(s); let random = getRandomInt(s);
if (random < 0) { if (random < 0) {
random = -random; random = -random;
} }
return colorList[random % 4]; return colorList[random % 4];
} }

View File

@ -1,193 +1,193 @@
import React from "react"; import React from "react";
import {Button, Card, Col, Input, Row, Select} from 'antd'; import {Button, Card, Col, Input, Row, Select} from 'antd';
import * as UserBackend from "./backend/UserBackend"; import * as UserBackend from "./backend/UserBackend";
import * as OrganizationBackend from "./backend/OrganizationBackend"; import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
const { Option } = Select; const { Option } = Select;
class UserEditPage extends React.Component { class UserEditPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
organizationName: props.match.params.organizationName, organizationName: props.match.params.organizationName,
userName: props.match.params.userName, userName: props.match.params.userName,
user: null, user: null,
organizations: [], organizations: [],
}; };
} }
componentWillMount() { componentWillMount() {
this.getUser(); this.getUser();
this.getOrganizations(); this.getOrganizations();
} }
getUser() { getUser() {
UserBackend.getUser(this.state.organizationName, this.state.userName) UserBackend.getUser(this.state.organizationName, this.state.userName)
.then((user) => { .then((user) => {
this.setState({ this.setState({
user: user, user: user,
}); });
}); });
} }
getOrganizations() { getOrganizations() {
OrganizationBackend.getOrganizations("admin") OrganizationBackend.getOrganizations("admin")
.then((res) => { .then((res) => {
this.setState({ this.setState({
organizations: res, organizations: res,
}); });
}); });
} }
parseUserField(key, value) { parseUserField(key, value) {
// if ([].includes(key)) { // if ([].includes(key)) {
// value = Setting.myParseInt(value); // value = Setting.myParseInt(value);
// } // }
return value; return value;
} }
updateUserField(key, value) { updateUserField(key, value) {
value = this.parseUserField(key, value); value = this.parseUserField(key, value);
let user = this.state.user; let user = this.state.user;
user[key] = value; user[key] = value;
this.setState({ this.setState({
user: user, user: user,
}); });
} }
renderUser() { renderUser() {
return ( return (
<Card size="small" title={ <Card size="small" title={
<div> <div>
Edit User&nbsp;&nbsp;&nbsp;&nbsp; Edit User&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitUserEdit.bind(this)}>Save</Button> <Button type="primary" onClick={this.submitUserEdit.bind(this)}>Save</Button>
</div> </div>
} style={{marginLeft: '5px'}} type="inner"> } style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} > <Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Organization: Organization:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Select virtual={false} style={{width: '100%'}} value={this.state.user.owner} onChange={(value => {this.updateUserField('owner', value);})}> <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>) this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
} }
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Name: Name:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.user.name} onChange={e => { <Input value={this.state.user.name} onChange={e => {
this.updateUserField('name', e.target.value); this.updateUserField('name', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Password Type: Password Type:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.user.passwordType} onChange={e => { <Input value={this.state.user.passwordType} onChange={e => {
this.updateUserField('passwordType', e.target.value); this.updateUserField('passwordType', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Password: Password:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.user.password} onChange={e => { <Input value={this.state.user.password} onChange={e => {
this.updateUserField('password', e.target.value); this.updateUserField('password', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Display Name: Display Name:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.user.displayName} onChange={e => { <Input value={this.state.user.displayName} onChange={e => {
this.updateUserField('displayName', e.target.value); this.updateUserField('displayName', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Email: Email:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.user.email} onChange={e => { <Input value={this.state.user.email} onChange={e => {
this.updateUserField('email', e.target.value); this.updateUserField('email', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}> <Col style={{marginTop: '5px'}} span={2}>
Phone: Phone:
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.user.phone} onChange={e => { <Input value={this.state.user.phone} onChange={e => {
this.updateUserField('phone', e.target.value); this.updateUserField('phone', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
</Card> </Card>
) )
} }
submitUserEdit() { submitUserEdit() {
let user = Setting.deepCopy(this.state.user); let user = Setting.deepCopy(this.state.user);
UserBackend.updateUser(this.state.organizationName, this.state.userName, user) UserBackend.updateUser(this.state.organizationName, this.state.userName, user)
.then((res) => { .then((res) => {
if (res) { if (res) {
Setting.showMessage("success", `Successfully saved`); Setting.showMessage("success", `Successfully saved`);
this.setState({ this.setState({
organizationName: this.state.user.owner, organizationName: this.state.user.owner,
userName: this.state.user.name, userName: this.state.user.name,
}); });
this.props.history.push(`/users/${this.state.user.owner}/${this.state.user.name}`); this.props.history.push(`/users/${this.state.user.owner}/${this.state.user.name}`);
} else { } else {
Setting.showMessage("error", `failed to save: server side failure`); Setting.showMessage("error", `failed to save: server side failure`);
this.updateUserField('owner', this.state.organizationName); this.updateUserField('owner', this.state.organizationName);
this.updateUserField('name', this.state.userName); this.updateUserField('name', this.state.userName);
} }
}) })
.catch(error => { .catch(error => {
Setting.showMessage("error", `failed to save: ${error}`); Setting.showMessage("error", `failed to save: ${error}`);
}); });
} }
render() { render() {
return ( return (
<div> <div>
<Row style={{width: "100%"}}> <Row style={{width: "100%"}}>
<Col span={1}> <Col span={1}>
</Col> </Col>
<Col span={22}> <Col span={22}>
{ {
this.state.user !== null ? this.renderUser() : null this.state.user !== null ? this.renderUser() : null
} }
</Col> </Col>
<Col span={1}> <Col span={1}>
</Col> </Col>
</Row> </Row>
<Row style={{margin: 10}}> <Row style={{margin: 10}}>
<Col span={2}> <Col span={2}>
</Col> </Col>
<Col span={18}> <Col span={18}>
<Button type="primary" size="large" onClick={this.submitUserEdit.bind(this)}>Save</Button> <Button type="primary" size="large" onClick={this.submitUserEdit.bind(this)}>Save</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
); );
} }
} }
export default UserEditPage; export default UserEditPage;

View File

@ -1,202 +1,202 @@
import React from "react"; import React from "react";
import {Link} from "react-router-dom"; import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd'; import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment"; import moment from "moment";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
import * as UserBackend from "./backend/UserBackend"; import * as UserBackend from "./backend/UserBackend";
class UserListPage extends React.Component { class UserListPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
users: null, users: null,
}; };
} }
componentWillMount() { componentWillMount() {
this.getUsers(); this.getUsers();
} }
getUsers() { getUsers() {
UserBackend.getGlobalUsers() UserBackend.getGlobalUsers()
.then((res) => { .then((res) => {
this.setState({ this.setState({
users: res, users: res,
}); });
}); });
} }
newUser() { newUser() {
return { return {
owner: "admin", // this.props.account.username, owner: "admin", // this.props.account.username,
name: `user_${this.state.users.length}`, name: `user_${this.state.users.length}`,
createdTime: moment().format(), createdTime: moment().format(),
password: "123456", password: "123456",
passwordType: "plain", passwordType: "plain",
displayName: `New User - ${this.state.users.length}`, displayName: `New User - ${this.state.users.length}`,
email: "user@example.com", email: "user@example.com",
phone: "1-12345678", phone: "1-12345678",
} }
} }
addUser() { addUser() {
const newUser = this.newUser(); const newUser = this.newUser();
UserBackend.addUser(newUser) UserBackend.addUser(newUser)
.then((res) => { .then((res) => {
Setting.showMessage("success", `User added successfully`); Setting.showMessage("success", `User added successfully`);
this.setState({ this.setState({
users: Setting.prependRow(this.state.users, newUser), users: Setting.prependRow(this.state.users, newUser),
}); });
} }
) )
.catch(error => { .catch(error => {
Setting.showMessage("error", `User failed to add: ${error}`); Setting.showMessage("error", `User failed to add: ${error}`);
}); });
} }
deleteUser(i) { deleteUser(i) {
UserBackend.deleteUser(this.state.users[i]) UserBackend.deleteUser(this.state.users[i])
.then((res) => { .then((res) => {
Setting.showMessage("success", `User deleted successfully`); Setting.showMessage("success", `User deleted successfully`);
this.setState({ this.setState({
users: Setting.deleteRow(this.state.users, i), users: Setting.deleteRow(this.state.users, i),
}); });
} }
) )
.catch(error => { .catch(error => {
Setting.showMessage("error", `User failed to delete: ${error}`); Setting.showMessage("error", `User failed to delete: ${error}`);
}); });
} }
renderTable(users) { renderTable(users) {
const columns = [ const columns = [
{ {
title: 'Organization', title: 'Organization',
dataIndex: 'owner', dataIndex: 'owner',
key: 'owner', key: 'owner',
width: '120px', width: '120px',
sorter: (a, b) => a.owner.localeCompare(b.owner), sorter: (a, b) => a.owner.localeCompare(b.owner),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<a href={`/organizations/${text}`}> <a href={`/organizations/${text}`}>
{text} {text}
</a> </a>
) )
} }
}, },
{ {
title: 'Name', title: 'Name',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
width: '120px', width: '120px',
sorter: (a, b) => a.name.localeCompare(b.name), sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<Link to={`/users/${record.owner}/${text}`}> <Link to={`/users/${record.owner}/${text}`}>
{text} {text}
</Link> </Link>
) )
} }
}, },
{ {
title: 'Created Time', title: 'Created Time',
dataIndex: 'createdTime', dataIndex: 'createdTime',
key: 'createdTime', key: 'createdTime',
width: '160px', width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime), sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => { render: (text, record, index) => {
return Setting.getFormattedDate(text); return Setting.getFormattedDate(text);
} }
}, },
{ {
title: 'PasswordType', title: 'PasswordType',
dataIndex: 'passwordType', dataIndex: 'passwordType',
key: 'passwordType', key: 'passwordType',
width: '150px', width: '150px',
sorter: (a, b) => a.passwordType.localeCompare(b.passwordType), sorter: (a, b) => a.passwordType.localeCompare(b.passwordType),
}, },
{ {
title: 'Password', title: 'Password',
dataIndex: 'password', dataIndex: 'password',
key: 'password', key: 'password',
width: '150px', width: '150px',
sorter: (a, b) => a.password.localeCompare(b.password), sorter: (a, b) => a.password.localeCompare(b.password),
}, },
{ {
title: 'Display Name', title: 'Display Name',
dataIndex: 'displayName', dataIndex: 'displayName',
key: 'displayName', key: 'displayName',
// width: '100px', // width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName), sorter: (a, b) => a.displayName.localeCompare(b.displayName),
}, },
{ {
title: 'Email', title: 'Email',
dataIndex: 'email', dataIndex: 'email',
key: 'email', key: 'email',
width: '150px', width: '150px',
sorter: (a, b) => a.email.localeCompare(b.email), sorter: (a, b) => a.email.localeCompare(b.email),
}, },
{ {
title: 'Phone', title: 'Phone',
dataIndex: 'phone', dataIndex: 'phone',
key: 'phone', key: 'phone',
width: '120px', width: '120px',
sorter: (a, b) => a.phone.localeCompare(b.phone), sorter: (a, b) => a.phone.localeCompare(b.phone),
}, },
{ {
title: 'Action', title: 'Action',
dataIndex: '', dataIndex: '',
key: 'op', key: 'op',
width: '170px', width: '170px',
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<div> <div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/users/${record.owner}/${record.name}`)}>Edit</Button> <Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/users/${record.owner}/${record.name}`)}>Edit</Button>
<Popconfirm <Popconfirm
title={`Sure to delete user: ${record.name} ?`} title={`Sure to delete user: ${record.name} ?`}
onConfirm={() => this.deleteUser(index)} onConfirm={() => this.deleteUser(index)}
> >
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button> <Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm> </Popconfirm>
</div> </div>
) )
} }
}, },
]; ];
return ( return (
<div> <div>
<Table columns={columns} dataSource={users} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table columns={columns} dataSource={users} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => ( title={() => (
<div> <div>
Users&nbsp;&nbsp;&nbsp;&nbsp; Users&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addUser.bind(this)}>Add</Button> <Button type="primary" size="small" onClick={this.addUser.bind(this)}>Add</Button>
</div> </div>
)} )}
loading={users === null} loading={users === null}
/> />
</div> </div>
); );
} }
render() { render() {
return ( return (
<div> <div>
<Row style={{width: "100%"}}> <Row style={{width: "100%"}}>
<Col span={1}> <Col span={1}>
</Col> </Col>
<Col span={22}> <Col span={22}>
{ {
this.renderTable(this.state.users) this.renderTable(this.state.users)
} }
</Col> </Col>
<Col span={1}> <Col span={1}>
</Col> </Col>
</Row> </Row>
</div> </div>
); );
} }
} }
export default UserListPage; export default UserListPage;

View File

@ -1,77 +1,77 @@
import React from "react"; import React from "react";
import {Col, Descriptions, Row} from 'antd'; import {Col, Descriptions, Row} from 'antd';
import * as AccountBackend from "../backend/AccountBackend"; import * as AccountBackend from "../backend/AccountBackend";
import * as Setting from "../Setting"; import * as Setting from "../Setting";
class AccountPage extends React.Component { class AccountPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
classes: props, classes: props,
username: props.match.params.username, username: props.match.params.username,
user: null, user: null,
}; };
} }
componentWillMount() { componentWillMount() {
this.getUser(); this.getUser();
} }
getUser() { getUser() {
if (this.state.username !== undefined) { if (this.state.username !== undefined) {
AccountBackend.getUser(this.state.username) AccountBackend.getUser(this.state.username)
.then((user) => { .then((user) => {
this.setState({ this.setState({
user: user, user: user,
}); });
}); });
} }
} }
renderValue(key) { renderValue(key) {
if (this.props.account === null || this.props.account === undefined) { if (this.props.account === null || this.props.account === undefined) {
return <a href={"/login"}>Please sign in first</a> return <a href={"/login"}>Please sign in first</a>
} else if (this.state.user !== null) { } else if (this.state.user !== null) {
return this.state.user[key]; return this.state.user[key];
} else { } else {
return this.props.account[key]; return this.props.account[key];
} }
} }
renderContent() { renderContent() {
return ( return (
<div> <div>
&nbsp; &nbsp;
<Descriptions title="My Account" bordered> <Descriptions title="My Account" bordered>
<Descriptions.Item label="Username">{this.renderValue("name")}</Descriptions.Item> <Descriptions.Item label="Username">{this.renderValue("name")}</Descriptions.Item>
<Descriptions.Item label="Organization">{this.renderValue("owner")}</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="Created At">{Setting.getFormattedDate(this.renderValue("createdTime"))}</Descriptions.Item>
<Descriptions.Item label="Password Type">{this.renderValue("passwordType")}</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="Display Name">{this.renderValue("displayName")}</Descriptions.Item>
<Descriptions.Item label="E-mail">{this.renderValue("email")}</Descriptions.Item> <Descriptions.Item label="E-mail">{this.renderValue("email")}</Descriptions.Item>
<Descriptions.Item label="Phone">{this.renderValue("phone")}</Descriptions.Item> <Descriptions.Item label="Phone">{this.renderValue("phone")}</Descriptions.Item>
</Descriptions> </Descriptions>
</div> </div>
); );
} }
render() { render() {
return ( return (
<div> <div>
<Row style={{width: "100%"}}> <Row style={{width: "100%"}}>
<Col span={1}> <Col span={1}>
</Col> </Col>
<Col span={22}> <Col span={22}>
{ {
this.renderContent() this.renderContent()
} }
</Col> </Col>
<Col span={1}> <Col span={1}>
</Col> </Col>
</Row> </Row>
</div> </div>
) )
} }
} }
export default AccountPage; export default AccountPage;

View File

@ -1,12 +1,12 @@
import React from 'react'; import React from 'react';
import Face from "../Face"; import Face from "../Face";
class LoginPage extends React.Component { class LoginPage extends React.Component {
render() { render() {
return ( return (
<Face applicationName={"app-built-in"} account={this.props.account} onLoggedIn={this.props.onLoggedIn.bind(this)} {...this.props} /> <Face applicationName={"app-built-in"} account={this.props.account} onLoggedIn={this.props.onLoggedIn.bind(this)} {...this.props} />
) )
} }
} }
export default LoginPage; export default LoginPage;

View File

@ -1,52 +1,52 @@
// Copyright 2020 The casbin Authors. All Rights Reserved. // Copyright 2020 The casbin Authors. All Rights Reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getUser(username) { export function getUser(username) {
return fetch(`${Setting.ServerUrl}/api/get-user?username=${username}`, { return fetch(`${Setting.ServerUrl}/api/get-user?username=${username}`, {
method: 'GET', method: 'GET',
credentials: 'include' credentials: 'include'
}).then(res => res.json()); }).then(res => res.json());
} }
export function getAccount() { export function getAccount() {
return fetch(`${Setting.ServerUrl}/api/get-account`, { return fetch(`${Setting.ServerUrl}/api/get-account`, {
method: 'GET', method: 'GET',
credentials: 'include' credentials: 'include'
}).then(res => res.json()); }).then(res => res.json());
} }
export function register(values) { export function register(values) {
return fetch(`${Setting.ServerUrl}/api/register`, { return fetch(`${Setting.ServerUrl}/api/register`, {
method: 'POST', method: 'POST',
credentials: "include", credentials: "include",
body: JSON.stringify(values), body: JSON.stringify(values),
}).then(res => res.json()); }).then(res => res.json());
} }
export function login(values) { export function login(values) {
return fetch(`${Setting.ServerUrl}/api/login`, { return fetch(`${Setting.ServerUrl}/api/login`, {
method: 'POST', method: 'POST',
credentials: "include", credentials: "include",
body: JSON.stringify(values), body: JSON.stringify(values),
}).then(res => res.json()); }).then(res => res.json());
} }
export function logout() { export function logout() {
return fetch(`${Setting.ServerUrl}/api/logout`, { return fetch(`${Setting.ServerUrl}/api/logout`, {
method: 'POST', method: 'POST',
credentials: "include", credentials: "include",
}).then(res => res.json()); }).then(res => res.json());
} }

View File

@ -1,42 +1,42 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getApplications(owner) { export function getApplications(owner) {
return fetch(`${Setting.ServerUrl}/api/get-applications?owner=${owner}`, { return fetch(`${Setting.ServerUrl}/api/get-applications?owner=${owner}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function getApplication(owner, name) { export function getApplication(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-application?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/get-application?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function updateApplication(owner, name, application) { export function updateApplication(owner, name, application) {
let newApplication = Setting.deepCopy(application); let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/update-application?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/update-application?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newApplication), body: JSON.stringify(newApplication),
}).then(res => res.json()); }).then(res => res.json());
} }
export function addApplication(application) { export function addApplication(application) {
let newApplication = Setting.deepCopy(application); let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/add-application`, { return fetch(`${Setting.ServerUrl}/api/add-application`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newApplication), body: JSON.stringify(newApplication),
}).then(res => res.json()); }).then(res => res.json());
} }
export function deleteApplication(application) { export function deleteApplication(application) {
let newApplication = Setting.deepCopy(application); let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/delete-application`, { return fetch(`${Setting.ServerUrl}/api/delete-application`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newApplication), body: JSON.stringify(newApplication),
}).then(res => res.json()); }).then(res => res.json());
} }

View File

@ -1,42 +1,42 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getOrganizations(owner) { export function getOrganizations(owner) {
return fetch(`${Setting.ServerUrl}/api/get-organizations?owner=${owner}`, { return fetch(`${Setting.ServerUrl}/api/get-organizations?owner=${owner}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function getOrganization(owner, name) { export function getOrganization(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-organization?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/get-organization?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function updateOrganization(owner, name, organization) { export function updateOrganization(owner, name, organization) {
let newOrganization = Setting.deepCopy(organization); let newOrganization = Setting.deepCopy(organization);
return fetch(`${Setting.ServerUrl}/api/update-organization?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/update-organization?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newOrganization), body: JSON.stringify(newOrganization),
}).then(res => res.json()); }).then(res => res.json());
} }
export function addOrganization(organization) { export function addOrganization(organization) {
let newOrganization = Setting.deepCopy(organization); let newOrganization = Setting.deepCopy(organization);
return fetch(`${Setting.ServerUrl}/api/add-organization`, { return fetch(`${Setting.ServerUrl}/api/add-organization`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newOrganization), body: JSON.stringify(newOrganization),
}).then(res => res.json()); }).then(res => res.json());
} }
export function deleteOrganization(organization) { export function deleteOrganization(organization) {
let newOrganization = Setting.deepCopy(organization); let newOrganization = Setting.deepCopy(organization);
return fetch(`${Setting.ServerUrl}/api/delete-organization`, { return fetch(`${Setting.ServerUrl}/api/delete-organization`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newOrganization), body: JSON.stringify(newOrganization),
}).then(res => res.json()); }).then(res => res.json());
} }

View File

@ -1,42 +1,42 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getProviders(owner) { export function getProviders(owner) {
return fetch(`${Setting.ServerUrl}/api/get-providers?owner=${owner}`, { return fetch(`${Setting.ServerUrl}/api/get-providers?owner=${owner}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function getProvider(owner, name) { export function getProvider(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-provider?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/get-provider?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function updateProvider(owner, name, provider) { export function updateProvider(owner, name, provider) {
let newProvider = Setting.deepCopy(provider); let newProvider = Setting.deepCopy(provider);
return fetch(`${Setting.ServerUrl}/api/update-provider?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/update-provider?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newProvider), body: JSON.stringify(newProvider),
}).then(res => res.json()); }).then(res => res.json());
} }
export function addProvider(provider) { export function addProvider(provider) {
let newProvider = Setting.deepCopy(provider); let newProvider = Setting.deepCopy(provider);
return fetch(`${Setting.ServerUrl}/api/add-provider`, { return fetch(`${Setting.ServerUrl}/api/add-provider`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newProvider), body: JSON.stringify(newProvider),
}).then(res => res.json()); }).then(res => res.json());
} }
export function deleteProvider(provider) { export function deleteProvider(provider) {
let newProvider = Setting.deepCopy(provider); let newProvider = Setting.deepCopy(provider);
return fetch(`${Setting.ServerUrl}/api/delete-provider`, { return fetch(`${Setting.ServerUrl}/api/delete-provider`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newProvider), body: JSON.stringify(newProvider),
}).then(res => res.json()); }).then(res => res.json());
} }

View File

@ -1,49 +1,49 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getGlobalUsers() { export function getGlobalUsers() {
return fetch(`${Setting.ServerUrl}/api/get-global-users`, { return fetch(`${Setting.ServerUrl}/api/get-global-users`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function getUsers(owner) { export function getUsers(owner) {
return fetch(`${Setting.ServerUrl}/api/get-users?owner=${owner}`, { return fetch(`${Setting.ServerUrl}/api/get-users?owner=${owner}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function getUser(owner, name) { export function getUser(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-user?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/get-user?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function updateUser(owner, name, user) { export function updateUser(owner, name, user) {
let newUser = Setting.deepCopy(user); let newUser = Setting.deepCopy(user);
return fetch(`${Setting.ServerUrl}/api/update-user?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/update-user?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newUser), body: JSON.stringify(newUser),
}).then(res => res.json()); }).then(res => res.json());
} }
export function addUser(user) { export function addUser(user) {
let newUser = Setting.deepCopy(user); let newUser = Setting.deepCopy(user);
return fetch(`${Setting.ServerUrl}/api/add-user`, { return fetch(`${Setting.ServerUrl}/api/add-user`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newUser), body: JSON.stringify(newUser),
}).then(res => res.json()); }).then(res => res.json());
} }
export function deleteUser(user) { export function deleteUser(user) {
let newUser = Setting.deepCopy(user); let newUser = Setting.deepCopy(user);
return fetch(`${Setting.ServerUrl}/api/delete-user`, { return fetch(`${Setting.ServerUrl}/api/delete-user`, {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
body: JSON.stringify(newUser), body: JSON.stringify(newUser),
}).then(res => res.json()); }).then(res => res.json());
} }

File diff suppressed because it is too large Load Diff