Add tableColumns to syncer.

This commit is contained in:
Yang Luo
2021-12-19 10:21:05 +08:00
parent 29d512d316
commit e7f395cfd4
4 changed files with 194 additions and 10 deletions

View File

@ -21,6 +21,13 @@ import (
"xorm.io/core"
)
type TableColumn struct {
Name string `json:"name"`
Type string `json:"type"`
CasdoorName string `json:"casdoorName"`
Values []string `json:"values"`
}
type Syncer struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
@ -29,16 +36,17 @@ type Syncer struct {
Organization string `xorm:"varchar(100)" json:"organization"`
Type string `xorm:"varchar(100)" json:"type"`
Host string `xorm:"varchar(100)" json:"host"`
Port int `json:"port"`
User string `xorm:"varchar(100)" json:"user"`
Password string `xorm:"varchar(100)" json:"password"`
Database string `xorm:"varchar(100)" json:"database"`
Table string `xorm:"varchar(100)" json:"table"`
AffiliationTable string `xorm:"varchar(100)" json:"affiliationTable"`
AvatarBaseUrl string `xorm:"varchar(100)" json:"avatarBaseUrl"`
SyncInterval int `json:"syncInterval"`
IsEnabled bool `json:"isEnabled"`
Host string `xorm:"varchar(100)" json:"host"`
Port int `json:"port"`
User string `xorm:"varchar(100)" json:"user"`
Password string `xorm:"varchar(100)" json:"password"`
Database string `xorm:"varchar(100)" json:"database"`
Table string `xorm:"varchar(100)" json:"table"`
TableColumns []*TableColumn `xorm:"mediumtext" json:"tableColumns"`
AffiliationTable string `xorm:"varchar(100)" json:"affiliationTable"`
AvatarBaseUrl string `xorm:"varchar(100)" json:"avatarBaseUrl"`
SyncInterval int `json:"syncInterval"`
IsEnabled bool `json:"isEnabled"`
Adapter *Adapter `xorm:"-" json:"-"`
}

View File

@ -19,6 +19,7 @@ import * as SyncerBackend from "./backend/SyncerBackend";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting";
import i18next from "i18next";
import SyncerTableColumnTable from "./SyncerTableColumnTable";
const { Option } = Select;
@ -177,6 +178,18 @@ class SyncerEditPage extends React.Component {
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("syncer:Table columns"), i18next.t("syncer:Table columns - Tooltip"))} :
</Col>
<Col span={22} >
<SyncerTableColumnTable
title={i18next.t("syncer:Table columns")}
table={this.state.syncer.tableColumns}
onUpdateTable={(value) => { this.updateSyncerField('tableColumns', value)}}
/>
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("syncer:Affiliation table"), i18next.t("syncer:Affiliation table - Tooltip"))} :

View File

@ -60,7 +60,11 @@ class SyncerListPage extends React.Component {
password: "123456",
database: "dbName",
table: "tableName",
tableColumns: [],
affiliationTable: "",
avatarBaseUrl: "",
syncInterval: 1,
isEnabled: true,
}
}

View File

@ -0,0 +1,159 @@
// Copyright 2021 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from "react";
import {DownOutlined, DeleteOutlined, UpOutlined} from '@ant-design/icons';
import {Button, Col, Input, Row, Select, Table, Tooltip} from 'antd';
import * as Setting from "./Setting";
import i18next from "i18next";
const { Option } = Select;
class SyncerTableColumnTable extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
};
}
updateTable(table) {
this.props.onUpdateTable(table);
}
updateField(table, index, key, value) {
table[index][key] = value;
this.updateTable(table);
}
addRow(table) {
let row = {name: `column${table.length}`, type: "string", values: []};
if (table === undefined) {
table = [];
}
table = Setting.addRow(table, row);
this.updateTable(table);
}
deleteRow(table, i) {
table = Setting.deleteRow(table, i);
this.updateTable(table);
}
upRow(table, i) {
table = Setting.swapRow(table, i - 1, i);
this.updateTable(table);
}
downRow(table, i) {
table = Setting.swapRow(table, i, i + 1);
this.updateTable(table);
}
renderTable(table) {
const columns = [
{
title: i18next.t("syncer:Column name"),
dataIndex: 'name',
key: 'name',
render: (text, record, index) => {
return (
<Input value={text} onChange={e => {
this.updateField(table, index, 'name', e.target.value);
}} />
)
}
},
{
title: i18next.t("syncer:Column type"),
dataIndex: 'type',
key: 'type',
render: (text, record, index) => {
return (
<Select virtual={false} style={{width: '100%'}} value={text} onChange={(value => {this.updateField(table, index, 'type', value);})}>
{
['string', 'integer', 'boolean']
.map((item, index) => <Option key={index} value={item}>{item}</Option>)
}
</Select>
)
}
},
{
title: i18next.t("syncer:Casdoor column"),
dataIndex: 'casdoorName',
key: 'casdoorName',
render: (text, record, index) => {
return (
<Select virtual={false} style={{width: '100%'}} value={text} onChange={(value => {this.updateField(table, index, 'casdoorName', value);})}>
{
['name', 'createdTime', 'updatedTime', 'id', 'type', 'password', 'passwordSalt', 'displayName', 'avatar', 'permanentAvatar', 'email', 'phone',
'location', 'address', 'affiliation', 'title', 'idCardType', 'idCard', 'homepage', 'bio', 'tag', 'region', 'language', 'gender', 'birthday',
'education', 'score', 'ranking', 'isDefaultAvatar', 'isOnline', 'isAdmin', 'isGlobalAdmin', 'isForbidden', 'isDeleted', 'CreatedIp']
.map((item, index) => <Option key={index} value={item}>{item}</Option>)
}
</Select>
)
}
},
{
title: i18next.t("general:Action"),
key: 'action',
width: '100px',
render: (text, record, index) => {
return (
<div>
<Tooltip placement="bottomLeft" title={i18next.t("general:Up")}>
<Button style={{marginRight: "5px"}} disabled={index === 0} icon={<UpOutlined />} size="small" onClick={() => this.upRow(table, index)} />
</Tooltip>
<Tooltip placement="topLeft" title={i18next.t("general:Down")}>
<Button style={{marginRight: "5px"}} disabled={index === table.length - 1} icon={<DownOutlined />} size="small" onClick={() => this.downRow(table, index)} />
</Tooltip>
<Tooltip placement="topLeft" title={i18next.t("general:Delete")}>
<Button icon={<DeleteOutlined />} size="small" onClick={() => this.deleteRow(table, index)} />
</Tooltip>
</div>
);
}
},
];
return (
<Table rowKey="index" columns={columns} dataSource={table} size="middle" bordered pagination={false}
title={() => (
<div>
{this.props.title}&nbsp;&nbsp;&nbsp;&nbsp;
<Button style={{marginRight: "5px"}} type="primary" size="small" onClick={() => this.addRow(table)}>{i18next.t("general:Add")}</Button>
</div>
)}
/>
);
}
render() {
return (
<div>
<Row style={{marginTop: '20px'}} >
<Col span={24}>
{
this.renderTable(this.props.table)
}
</Col>
</Row>
</div>
)
}
}
export default SyncerTableColumnTable;