Add accountTable.

This commit is contained in:
Gucheng Wang
2022-06-18 01:41:21 +08:00
parent 065b235dc5
commit ae4ab9902b
14 changed files with 566 additions and 130 deletions

View File

@ -47,6 +47,31 @@ func initBuiltInOrganization() bool {
PhonePrefix: "86", PhonePrefix: "86",
DefaultAvatar: "https://casbin.org/img/casbin.svg", DefaultAvatar: "https://casbin.org/img/casbin.svg",
Tags: []string{}, Tags: []string{},
AccountItems: []*AccountItem{
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
{Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
{Name: "Name", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
{Name: "Display name", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "Avatar", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "User type", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
{Name: "Password", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
{Name: "Email", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "Phone", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "Country/Region", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "Location", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "Affiliation", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "Title", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "Homepage", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "Bio", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
{Name: "Tag", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
{Name: "Is global admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
{Name: "Is forbidden", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
{Name: "Is deleted", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
},
} }
AddOrganization(organization) AddOrganization(organization)
return false return false

View File

@ -20,6 +20,13 @@ import (
"xorm.io/core" "xorm.io/core"
) )
type AccountItem struct {
Name string `json:"name"`
Visible bool `json:"visible"`
ViewRule string `json:"viewRule"`
ModifyRule string `json:"modifyRule"`
}
type Organization struct { type Organization struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"` Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"` Name string `xorm:"varchar(100) notnull pk" json:"name"`
@ -36,6 +43,8 @@ type Organization struct {
MasterPassword string `xorm:"varchar(100)" json:"masterPassword"` MasterPassword string `xorm:"varchar(100)" json:"masterPassword"`
EnableSoftDeletion bool `json:"enableSoftDeletion"` EnableSoftDeletion bool `json:"enableSoftDeletion"`
IsProfilePublic bool `json:"isProfilePublic"` IsProfilePublic bool `json:"isProfilePublic"`
AccountItems []*AccountItem `xorm:"varchar(2000)" json:"accountItems"`
} }
func GetOrganizationCount(owner, field, value string) int { func GetOrganizationCount(owner, field, value string) int {

242
web/src/AccountTable.js Normal file
View File

@ -0,0 +1,242 @@
// Copyright 2022 The Casdoor 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, Row, Select, Switch, Table, Tooltip} from 'antd';
import * as Setting from "./Setting";
import i18next from "i18next";
const { Option } = Select;
class AccountTable 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: Setting.getNewRowNameForTable(table, "Please select an account item"), visible: true};
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("provider:Name"),
dataIndex: 'name',
key: 'name',
render: (text, record, index) => {
const items = [
{name: "Organization", displayName: i18next.t("general:Organization")},
{name: "ID", displayName: i18next.t("general:ID")},
{name: "Name", displayName: i18next.t("general:Name")},
{name: "Display name", displayName: i18next.t("general:Display name")},
{name: "Avatar", displayName: i18next.t("general:Avatar")},
{name: "User type", displayName: i18next.t("general:User type")},
{name: "Password", displayName: i18next.t("general:Password")},
{name: "Email", displayName: i18next.t("general:Email")},
{name: "Phone", displayName: i18next.t("general:Phone")},
{name: "Country/Region", displayName: i18next.t("user:Country/Region")},
{name: "Location", displayName: i18next.t("user:Location")},
{name: "Affiliation", displayName: i18next.t("user:Affiliation")},
{name: "Title", displayName: i18next.t("user:Title")},
{name: "Homepage", displayName: i18next.t("user:Homepage")},
{name: "Bio", displayName: i18next.t("user:Bio")},
{name: "Tag", displayName: i18next.t("user:Tag")},
{name: "Signup application", displayName: i18next.t("general:Signup application")},
{name: "3rd-party logins", displayName: i18next.t("user:3rd-party logins")},
{name: "Properties", displayName: i18next.t("user:Properties")},
{name: "Is admin", displayName: i18next.t("user:Is admin")},
{name: "Is global admin", displayName: i18next.t("user:Is global admin")},
{name: "Is forbidden", displayName: i18next.t("user:Is forbidden")},
{name: "Is deleted", displayName: i18next.t("user:Is deleted")},
];
const getItemDisplayName = (text) => {
const item = items.filter(item => item.name === text);
if (item.length === 0) {
return "";
}
return item[0].displayName;
};
return (
<Select virtual={false} style={{width: '100%'}}
value={getItemDisplayName(text)}
onChange={value => {
this.updateField(table, index, 'name', value);
}} >
{
Setting.getDeduplicatedArray(items, table, "name").map((item, index) => <Option key={index} value={item.name}>{item.displayName}</Option>)
}
</Select>
)
}
},
{
title: i18next.t("provider:visible"),
dataIndex: 'visible',
key: 'visible',
width: '120px',
render: (text, record, index) => {
return (
<Switch checked={text} onChange={checked => {
this.updateField(table, index, 'visible', checked);
}} />
)
}
},
{
title: i18next.t("organization:viewRule"),
dataIndex: 'viewRule',
key: 'viewRule',
width: '155px',
render: (text, record, index) => {
if (!record.visible) {
return null;
}
let options = [
{id: 'Public', name: 'Public'},
{id: 'Self', name: 'Self'},
{id: 'Admin', name: 'Admin'},
];
return (
<Select virtual={false} style={{width: '100%'}} value={text} onChange={(value => {
this.updateField(table, index, 'viewRule', value);
})}>
{
options.map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
}
</Select>
)
}
},
{
title: i18next.t("organization:modifyRule"),
dataIndex: 'modifyRule',
key: 'modifyRule',
width: '155px',
render: (text, record, index) => {
if (!record.visible) {
return null;
}
let options;
if (record.viewRule === "Admin") {
options = [
{id: 'Admin', name: 'Admin'},
{id: 'Immutable', name: 'Immutable'},
];
} else {
options = [
{id: 'Self', name: 'Self'},
{id: 'Admin', name: 'Admin'},
{id: 'Immutable', name: 'Immutable'},
];
}
return (
<Select virtual={false} style={{width: '100%'}} value={text} onChange={(value => {
this.updateField(table, index, 'modifyRule', value);
})}>
{
options.map((item, index) => <Option key={index} value={item.id}>{item.name}</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 scroll={{x: 'max-content'}} rowKey="name" 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 AccountTable;

View File

@ -20,6 +20,7 @@ import * as Setting from "./Setting";
import i18next from "i18next"; import i18next from "i18next";
import {LinkOutlined} from "@ant-design/icons"; import {LinkOutlined} from "@ant-design/icons";
import LdapTable from "./LdapTable"; import LdapTable from "./LdapTable";
import AccountTable from "./AccountTable";
const { Option } = Select; const { Option } = Select;
@ -250,6 +251,18 @@ class OrganizationEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("organization:Account items"), i18next.t("organization:Account items - Tooltip"))} :
</Col>
<Col span={22} >
<AccountTable
title={i18next.t("organization:Account items")}
table={this.state.organization.accountItems}
onUpdateTable={(value) => { this.updateOrganizationField('accountItems', value)}}
/>
</Col>
</Row>
<Row style={{marginTop: '20px'}}> <Row style={{marginTop: '20px'}}>
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:LDAPs"), i18next.t("general:LDAPs - Tooltip"))} : {Setting.getLabel(i18next.t("general:LDAPs"), i18next.t("general:LDAPs - Tooltip"))} :

View File

@ -40,6 +40,31 @@ class OrganizationListPage extends BaseListPage {
masterPassword: "", masterPassword: "",
enableSoftDeletion: false, enableSoftDeletion: false,
isProfilePublic: true, isProfilePublic: true,
accountItems: [
{name: "Organization", visible: true, viewRule: "Public", modifyRule: "Admin"},
{name: "ID", visible: true, viewRule: "Public", modifyRule: "Immutable"},
{name: "Name", visible: true, viewRule: "Public", modifyRule: "Admin"},
{name: "Display name", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "Avatar", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "User type", visible: true, viewRule: "Public", modifyRule: "Admin"},
{name: "Password", visible: true, viewRule: "Self", modifyRule: "Self"},
{name: "Email", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "Phone", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "Country/Region", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "Location", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "Affiliation", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "Title", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "Homepage", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "Bio", visible: true, viewRule: "Public", modifyRule: "Self"},
{name: "Tag", visible: true, viewRule: "Public", modifyRule: "Admin"},
{name: "Signup application", visible: true, viewRule: "Public", modifyRule: "Admin"},
{name: "3rd-party logins", visible: true, viewRule: "Self", modifyRule: "Self"},
{name: "Properties", visible: false, viewRule: "Admin", modifyRule: "Admin"},
{name: "Is admin", visible: true, viewRule: "Admin", modifyRule: "Admin"},
{name: "Is global admin", visible: true, viewRule: "Admin", modifyRule: "Admin"},
{name: "Is forbidden", visible: true, viewRule: "Admin", modifyRule: "Admin"},
{name: "Is deleted", visible: true, viewRule: "Admin", modifyRule: "Admin"},
],
} }
} }

View File

@ -164,7 +164,7 @@ class SignupTable extends React.Component {
} }
}, },
{ {
title: i18next.t("provider:rule"), title: i18next.t("application:rule"),
dataIndex: 'rule', dataIndex: 'rule',
key: 'rule', key: 'rule',
width: '155px', width: '155px',

View File

@ -28,10 +28,10 @@ import OAuthWidget from "./common/OAuthWidget";
import SamlWidget from "./common/SamlWidget"; import SamlWidget from "./common/SamlWidget";
import SelectRegionBox from "./SelectRegionBox"; import SelectRegionBox from "./SelectRegionBox";
// import {Controlled as CodeMirror} from 'react-codemirror2'; import {Controlled as CodeMirror} from 'react-codemirror2';
// import "codemirror/lib/codemirror.css"; import "codemirror/lib/codemirror.css";
// require('codemirror/theme/material-darker.css'); require('codemirror/theme/material-darker.css');
// require("codemirror/mode/javascript/javascript"); require("codemirror/mode/javascript/javascript");
const { Option } = Select; const { Option } = Select;
@ -124,46 +124,78 @@ class UserEditPage extends React.Component {
return (this.state.user.id === this.props.account?.id) || Setting.isAdminUser(this.props.account); return (this.state.user.id === this.props.account?.id) || Setting.isAdminUser(this.props.account);
} }
renderUser() { renderAccountItem(accountItem) {
return ( if (!accountItem.visible) {
<Card size="small" title={ return null;
<div> }
{this.state.mode === "add" ? i18next.t("user:New User") : i18next.t("user:Edit User")}&nbsp;&nbsp;&nbsp;&nbsp;
<Button onClick={() => this.submitUserEdit(false)}>{i18next.t("general:Save")}</Button> const isSelf = this.state.user.id === this.props.account;
<Button style={{marginLeft: '20px'}} type="primary" onClick={() => this.submitUserEdit(true)}>{i18next.t("general:Save & Exit")}</Button> const isAdmin = Setting.isAdminUser(this.props.account);
{this.state.mode === "add" ? <Button style={{marginLeft: '20px'}} onClick={() => this.deleteUser()}>{i18next.t("general:Cancel")}</Button> : null}
</div> if (accountItem.viewRule === "Self") {
} style={(Setting.isMobile())? {margin: '5px'}:{}} type="inner"> if (!isSelf && !isAdmin) {
return null;
}
} else if (accountItem.viewRule === "Admin") {
if (!isAdmin) {
return null;
}
}
let disabled = false;
if (accountItem.modifyRule === "Self") {
if (!isSelf && !isAdmin) {
disabled = true;
}
} else if (accountItem.modifyRule === "Admin") {
if (!isAdmin) {
disabled = true;
}
} else if (accountItem.modifyRule === "Immutable") {
disabled = true;
}
if (accountItem.name === "Organization") {
return (
<Row style={{marginTop: '10px'}} > <Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} : {Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
</Col> </Col>
<Col span={22} > <Col span={22} >
<Select virtual={false} style={{width: '100%'}} disabled={!Setting.isAdminUser(this.props.account)} value={this.state.user.owner} onChange={(value => {this.updateUserField('owner', value);})}> <Select virtual={false} style={{width: '100%'}} disabled={disabled} 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>
)
} else if (accountItem.name === "ID") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel("ID", i18next.t("general:ID - Tooltip"))} : {Setting.getLabel("ID", i18next.t("general:ID - Tooltip"))} :
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.user.id} disabled={true} /> <Input value={this.state.user.id} disabled={disabled} />
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Name") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} : {Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
</Col> </Col>
<Col span={22} > <Col span={22} >
<Input value={this.state.user.name} disabled={!Setting.isAdminUser(this.props.account)} onChange={e => { <Input value={this.state.user.name} disabled={disabled} onChange={e => {
this.updateUserField('name', e.target.value); this.updateUserField('name', e.target.value);
}} /> }} />
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Display name") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} : {Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} :
@ -174,6 +206,9 @@ class UserEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Avatar") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Avatar"), i18next.t("general:Avatar - Tooltip"))} : {Setting.getLabel(i18next.t("general:Avatar"), i18next.t("general:Avatar - Tooltip"))} :
@ -204,6 +239,9 @@ class UserEditPage extends React.Component {
</Row> </Row>
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "User type") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:User type"), i18next.t("general:User type - Tooltip"))} : {Setting.getLabel(i18next.t("general:User type"), i18next.t("general:User type - Tooltip"))} :
@ -217,44 +255,56 @@ class UserEditPage extends React.Component {
</Select> </Select>
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Password") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Password"), i18next.t("general:Password - Tooltip"))} : {Setting.getLabel(i18next.t("general:Password"), i18next.t("general:Password - Tooltip"))} :
</Col> </Col>
<Col span={22} > <Col span={22} >
<PasswordModal user={this.state.user} account={this.props.account} disabled={this.state.userName !== this.state.user.name} /> <PasswordModal user={this.state.user} account={this.props.account} disabled={disabled} />
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Email") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Email"), i18next.t("general:Email - Tooltip"))} : {Setting.getLabel(i18next.t("general:Email"), i18next.t("general:Email - Tooltip"))} :
</Col> </Col>
<Col style={{paddingRight: '20px'}} span={11} > <Col style={{paddingRight: '20px'}} span={11} >
<Input value={this.state.user.email} <Input value={this.state.user.email}
disabled={this.state.user.id === this.props.account?.id ? true : !Setting.isAdminUser(this.props.account)} disabled={disabled}
onChange={e => { onChange={e => {
this.updateUserField('email', e.target.value); this.updateUserField('email', e.target.value);
}} /> }} />
</Col> </Col>
<Col span={11} > <Col span={11} >
{ this.state.user.id === this.props.account?.id ? (<ResetModal org={this.state.application?.organizationObj} buttonText={i18next.t("user:Reset Email...")} destType={"email"} />) : null} { this.state.user.id === this.props.account?.id ? (<ResetModal org={this.state.application?.organizationObj} buttonText={i18next.t("user:Reset Email...")} destType={"email"} />) : null}
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Phone") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Phone"), i18next.t("general:Phone - Tooltip"))} : {Setting.getLabel(i18next.t("general:Phone"), i18next.t("general:Phone - Tooltip"))} :
</Col> </Col>
<Col style={{paddingRight: '20px'}} span={11} > <Col style={{paddingRight: '20px'}} span={11} >
<Input value={this.state.user.phone} addonBefore={`+${this.state.application?.organizationObj.phonePrefix}`} <Input value={this.state.user.phone} addonBefore={`+${this.state.application?.organizationObj.phonePrefix}`}
disabled={this.state.user.id === this.props.account?.id ? true : !Setting.isAdminUser(this.props.account)} disabled={disabled}
onChange={e => { onChange={e => {
this.updateUserField('phone', e.target.value); this.updateUserField('phone', e.target.value);
}}/> }}/>
</Col> </Col>
<Col span={11} > <Col span={11} >
{ this.state.user.id === this.props.account?.id ? (<ResetModal org={this.state.application?.organizationObj} buttonText={i18next.t("user:Reset Phone...")} destType={"phone"} />) : null} { this.state.user.id === this.props.account?.id ? (<ResetModal org={this.state.application?.organizationObj} buttonText={i18next.t("user:Reset Phone...")} destType={"phone"} />) : null}
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Country/Region") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Country/Region"), i18next.t("user:Country/Region - Tooltip"))} : {Setting.getLabel(i18next.t("user:Country/Region"), i18next.t("user:Country/Region - Tooltip"))} :
@ -265,6 +315,9 @@ class UserEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Location") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Location"), i18next.t("user:Location - Tooltip"))} : {Setting.getLabel(i18next.t("user:Location"), i18next.t("user:Location - Tooltip"))} :
@ -275,11 +328,15 @@ class UserEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
{ )
(this.state.application === null || this.state.user === null) ? null : ( } else if (accountItem.name === "Affiliation") {
<AffiliationSelect labelSpan={(Setting.isMobile()) ? 22 : 2} application={this.state.application} user={this.state.user} onUpdateUserField={(key, value) => { return this.updateUserField(key, value)}} /> return (
) (this.state.application === null || this.state.user === null) ? null : (
} <AffiliationSelect labelSpan={(Setting.isMobile()) ? 22 : 2} application={this.state.application} user={this.state.user} onUpdateUserField={(key, value) => { return this.updateUserField(key, value)}} />
)
)
} else if (accountItem.name === "Title") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Title"), i18next.t("user:Title - Tooltip"))} : {Setting.getLabel(i18next.t("user:Title"), i18next.t("user:Title - Tooltip"))} :
@ -290,6 +347,9 @@ class UserEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Homepage") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Homepage"), i18next.t("user:Homepage - Tooltip"))} : {Setting.getLabel(i18next.t("user:Homepage"), i18next.t("user:Homepage - Tooltip"))} :
@ -300,6 +360,9 @@ class UserEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Bio") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Bio"), i18next.t("user:Bio - Tooltip"))} : {Setting.getLabel(i18next.t("user:Bio"), i18next.t("user:Bio - Tooltip"))} :
@ -310,6 +373,9 @@ class UserEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Tag") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Tag"), i18next.t("user:Tag - Tooltip"))} : {Setting.getLabel(i18next.t("user:Tag"), i18next.t("user:Tag - Tooltip"))} :
@ -335,102 +401,130 @@ class UserEditPage extends React.Component {
} }
</Col> </Col>
</Row> </Row>
)
} else if (accountItem.name === "Signup application") {
return (
<Row style={{marginTop: '20px'}} > <Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Signup application"), i18next.t("general:Signup application - Tooltip"))} : {Setting.getLabel(i18next.t("general:Signup application"), i18next.t("general:Signup application - Tooltip"))} :
</Col> </Col>
<Col span={22} > <Col span={22} >
<Select virtual={false} style={{width: '100%'}} disabled={!Setting.isAdminUser(this.props.account)} value={this.state.user.signupApplication} onChange={(value => {this.updateUserField('signupApplication', value);})}> <Select virtual={false} style={{width: '100%'}} disabled={disabled} value={this.state.user.signupApplication} onChange={(value => {this.updateUserField('signupApplication', value);})}>
{ {
this.state.applications.map((application, index) => <Option key={index} value={application.name}>{application.name}</Option>) this.state.applications.map((application, index) => <Option key={index} value={application.name}>{application.name}</Option>)
} }
</Select> </Select>
</Col> </Col>
</Row> </Row>
{ )
!this.isSelfOrAdmin() ? null : ( } else if (accountItem.name === "3rd-party logins") {
<Row style={{marginTop: '20px'}} > return (
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}> !this.isSelfOrAdmin() ? null : (
{Setting.getLabel(i18next.t("user:3rd-party logins"), i18next.t("user:3rd-party logins - Tooltip"))} : <Row style={{marginTop: '20px'}} >
</Col> <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
<Col span={22} > {Setting.getLabel(i18next.t("user:3rd-party logins"), i18next.t("user:3rd-party logins - Tooltip"))} :
<div style={{marginBottom: 20}}> </Col>
{ <Col span={22} >
(this.state.application === null || this.state.user === null) ? null : ( <div style={{marginBottom: 20}}>
this.state.application?.providers.filter(providerItem => Setting.isProviderVisible(providerItem)).map((providerItem, index) => {
(providerItem.provider.category === "OAuth") ? ( (this.state.application === null || this.state.user === null) ? null : (
<OAuthWidget key={providerItem.name} labelSpan={(Setting.isMobile()) ? 10 : 3} user={this.state.user} application={this.state.application} providerItem={providerItem} onUnlinked={() => { return this.unlinked()}} /> this.state.application?.providers.filter(providerItem => Setting.isProviderVisible(providerItem)).map((providerItem, index) =>
) : ( (providerItem.provider.category === "OAuth") ? (
<SamlWidget key={providerItem.name} labelSpan={(Setting.isMobile()) ? 10 : 3} user={this.state.user} application={this.state.application} providerItem={providerItem} onUnlinked={() => { return this.unlinked()}} /> <OAuthWidget key={providerItem.name} labelSpan={(Setting.isMobile()) ? 10 : 3} user={this.state.user} application={this.state.application} providerItem={providerItem} onUnlinked={() => { return this.unlinked()}} />
) ) : (
<SamlWidget key={providerItem.name} labelSpan={(Setting.isMobile()) ? 10 : 3} user={this.state.user} application={this.state.application} providerItem={providerItem} onUnlinked={() => { return this.unlinked()}} />
) )
) )
} )
</div> }
</Col> </div>
</Row> </Col>
) </Row>
} )
)
} else if (accountItem.name === "Properties") {
return (
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{i18next.t("user:Properties")}:
</Col>
<Col span={22} >
<CodeMirror
value={JSON.stringify(this.state.user.properties, null, 4)}
options={{mode: 'javascript', theme: "material-darker"}}
/>
</Col>
</Row>
)
} else if (accountItem.name === "Is admin") {
return (
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Is admin"), i18next.t("user:Is admin - Tooltip"))} :
</Col>
<Col span={(Setting.isMobile()) ? 22 : 2} >
<Switch checked={this.state.user.isAdmin} onChange={checked => {
this.updateUserField('isAdmin', checked);
}} />
</Col>
</Row>
)
} else if (accountItem.name === "Is global admin") {
return (
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Is global admin"), i18next.t("user:Is global admin - Tooltip"))} :
</Col>
<Col span={(Setting.isMobile()) ? 22 : 2} >
<Switch checked={this.state.user.isGlobalAdmin} onChange={checked => {
this.updateUserField('isGlobalAdmin', checked);
}} />
</Col>
</Row>
)
} else if (accountItem.name === "Is forbidden") {
return (
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Is forbidden"), i18next.t("user:Is forbidden - Tooltip"))} :
</Col>
<Col span={(Setting.isMobile()) ? 22 : 2} >
<Switch checked={this.state.user.isForbidden} onChange={checked => {
this.updateUserField('isForbidden', checked);
}} />
</Col>
</Row>
)
} else if (accountItem.name === "Is deleted") {
return (
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Is deleted"), i18next.t("user:Is deleted - Tooltip"))} :
</Col>
<Col span={(Setting.isMobile()) ? 22 : 2} >
<Switch checked={this.state.user.isDeleted} onChange={checked => {
this.updateUserField('isDeleted', checked);
}} />
</Col>
</Row>
)
}
}
renderUser() {
return (
<Card size="small" title={
<div>
{this.state.mode === "add" ? i18next.t("user:New User") : i18next.t("user:Edit User")}&nbsp;&nbsp;&nbsp;&nbsp;
<Button onClick={() => this.submitUserEdit(false)}>{i18next.t("general:Save")}</Button>
<Button style={{marginLeft: '20px'}} type="primary" onClick={() => this.submitUserEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
{this.state.mode === "add" ? <Button style={{marginLeft: '20px'}} onClick={() => this.deleteUser()}>{i18next.t("general:Cancel")}</Button> : null}
</div>
} style={(Setting.isMobile())? {margin: '5px'}:{}} type="inner">
{ {
!Setting.isAdminUser(this.props.account) ? null : ( this.state.application?.organizationObj.accountItems?.map(accountItem => this.renderAccountItem(accountItem))
<React.Fragment>
{/*<Row style={{marginTop: '20px'}} >*/}
{/* <Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>*/}
{/* {i18next.t("user:Properties")}:*/}
{/* </Col>*/}
{/* <Col span={22} >*/}
{/* <CodeMirror*/}
{/* value={JSON.stringify(this.state.user.properties, null, 4)}*/}
{/* options={{mode: 'javascript', theme: "material-darker"}}*/}
{/* />*/}
{/* </Col>*/}
{/*</Row>*/}
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Is admin"), i18next.t("user:Is admin - Tooltip"))} :
</Col>
<Col span={(Setting.isMobile()) ? 22 : 2} >
<Switch checked={this.state.user.isAdmin} onChange={checked => {
this.updateUserField('isAdmin', checked);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Is global admin"), i18next.t("user:Is global admin - Tooltip"))} :
</Col>
<Col span={(Setting.isMobile()) ? 22 : 2} >
<Switch checked={this.state.user.isGlobalAdmin} onChange={checked => {
this.updateUserField('isGlobalAdmin', checked);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Is forbidden"), i18next.t("user:Is forbidden - Tooltip"))} :
</Col>
<Col span={(Setting.isMobile()) ? 22 : 2} >
<Switch checked={this.state.user.isForbidden} onChange={checked => {
this.updateUserField('isForbidden', checked);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Is deleted"), i18next.t("user:Is deleted - Tooltip"))} :
</Col>
<Col span={(Setting.isMobile()) ? 22 : 2} >
<Switch checked={this.state.user.isDeleted} onChange={checked => {
this.updateUserField('isDeleted', checked);
}} />
</Col>
</Row>
</React.Fragment>
)
} }
</Card> </Card>
) )
} }

View File

@ -38,7 +38,8 @@
"Token expire": "Token läuft ab", "Token expire": "Token läuft ab",
"Token expire - Tooltip": "Token läuft ab - Tooltip", "Token expire - Tooltip": "Token läuft ab - Tooltip",
"Token format": "Token-Format", "Token format": "Token-Format",
"Token format - Tooltip": "Token-Format - Tooltip" "Token format - Tooltip": "Token-Format - Tooltip",
"rule": "rule"
}, },
"cert": { "cert": {
"Bit size": "Bitgröße", "Bit size": "Bitgröße",
@ -259,6 +260,8 @@
"New Model": "New Model" "New Model": "New Model"
}, },
"organization": { "organization": {
"Account items": "Account items",
"Account items - Tooltip": "Account items - Tooltip",
"Default avatar": "Standard Avatar", "Default avatar": "Standard Avatar",
"Edit Organization": "Organisation bearbeiten", "Edit Organization": "Organisation bearbeiten",
"Favicon": "Févicon", "Favicon": "Févicon",
@ -270,7 +273,9 @@
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"Website URL": "Website-URL", "Website URL": "Website-URL",
"Website URL - Tooltip": "Unique string-style identifier" "Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
}, },
"payment": { "payment": {
"Confirm your invoice information": "Confirm your invoice information", "Confirm your invoice information": "Confirm your invoice information",
@ -469,7 +474,6 @@
"canUnlink": "canUnlink", "canUnlink": "canUnlink",
"prompted": "gefragt", "prompted": "gefragt",
"required": "benötigt", "required": "benötigt",
"rule": "regel",
"visible": "sichtbar" "visible": "sichtbar"
}, },
"record": { "record": {

View File

@ -38,7 +38,8 @@
"Token expire": "Token expire", "Token expire": "Token expire",
"Token expire - Tooltip": "Token expire - Tooltip", "Token expire - Tooltip": "Token expire - Tooltip",
"Token format": "Token format", "Token format": "Token format",
"Token format - Tooltip": "Token format - Tooltip" "Token format - Tooltip": "Token format - Tooltip",
"rule": "rule"
}, },
"cert": { "cert": {
"Bit size": "Bit size", "Bit size": "Bit size",
@ -259,6 +260,8 @@
"New Model": "New Model" "New Model": "New Model"
}, },
"organization": { "organization": {
"Account items": "Account items",
"Account items - Tooltip": "Account items - Tooltip",
"Default avatar": "Default avatar", "Default avatar": "Default avatar",
"Edit Organization": "Edit Organization", "Edit Organization": "Edit Organization",
"Favicon": "Favicon", "Favicon": "Favicon",
@ -270,7 +273,9 @@
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"Website URL": "Website URL", "Website URL": "Website URL",
"Website URL - Tooltip": "Website URL - Tooltip" "Website URL - Tooltip": "Website URL - Tooltip",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
}, },
"payment": { "payment": {
"Confirm your invoice information": "Confirm your invoice information", "Confirm your invoice information": "Confirm your invoice information",
@ -469,7 +474,6 @@
"canUnlink": "canUnlink", "canUnlink": "canUnlink",
"prompted": "prompted", "prompted": "prompted",
"required": "required", "required": "required",
"rule": "rule",
"visible": "visible" "visible": "visible"
}, },
"record": { "record": {

View File

@ -38,7 +38,8 @@
"Token expire": "Expiration du jeton", "Token expire": "Expiration du jeton",
"Token expire - Tooltip": "Expiration du jeton - Info-bulle", "Token expire - Tooltip": "Expiration du jeton - Info-bulle",
"Token format": "Format du jeton", "Token format": "Format du jeton",
"Token format - Tooltip": "Format du jeton - infobulle" "Token format - Tooltip": "Format du jeton - infobulle",
"rule": "rule"
}, },
"cert": { "cert": {
"Bit size": "Taille du bit", "Bit size": "Taille du bit",
@ -259,6 +260,8 @@
"New Model": "New Model" "New Model": "New Model"
}, },
"organization": { "organization": {
"Account items": "Account items",
"Account items - Tooltip": "Account items - Tooltip",
"Default avatar": "Avatar par défaut", "Default avatar": "Avatar par défaut",
"Edit Organization": "Modifier l'organisation", "Edit Organization": "Modifier l'organisation",
"Favicon": "Favicon", "Favicon": "Favicon",
@ -270,7 +273,9 @@
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"Website URL": "URL du site web", "Website URL": "URL du site web",
"Website URL - Tooltip": "Unique string-style identifier" "Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
}, },
"payment": { "payment": {
"Confirm your invoice information": "Confirm your invoice information", "Confirm your invoice information": "Confirm your invoice information",
@ -469,7 +474,6 @@
"canUnlink": "canUnlink", "canUnlink": "canUnlink",
"prompted": "invitée", "prompted": "invitée",
"required": "Obligatoire", "required": "Obligatoire",
"rule": "règle",
"visible": "Visible" "visible": "Visible"
}, },
"record": { "record": {

View File

@ -38,7 +38,8 @@
"Token expire": "トークンの有効期限", "Token expire": "トークンの有効期限",
"Token expire - Tooltip": "トークンの有効期限 - ツールチップ", "Token expire - Tooltip": "トークンの有効期限 - ツールチップ",
"Token format": "トークンのフォーマット", "Token format": "トークンのフォーマット",
"Token format - Tooltip": "トークンフォーマット - ツールチップ" "Token format - Tooltip": "トークンフォーマット - ツールチップ",
"rule": "rule"
}, },
"cert": { "cert": {
"Bit size": "ビットサイズ", "Bit size": "ビットサイズ",
@ -259,6 +260,8 @@
"New Model": "New Model" "New Model": "New Model"
}, },
"organization": { "organization": {
"Account items": "Account items",
"Account items - Tooltip": "Account items - Tooltip",
"Default avatar": "デフォルトのアバター", "Default avatar": "デフォルトのアバター",
"Edit Organization": "組織を編集", "Edit Organization": "組織を編集",
"Favicon": "ファビコン", "Favicon": "ファビコン",
@ -270,7 +273,9 @@
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"Website URL": "Website URL", "Website URL": "Website URL",
"Website URL - Tooltip": "Unique string-style identifier" "Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
}, },
"payment": { "payment": {
"Confirm your invoice information": "Confirm your invoice information", "Confirm your invoice information": "Confirm your invoice information",
@ -469,7 +474,6 @@
"canUnlink": "canUnlink", "canUnlink": "canUnlink",
"prompted": "プロンプトされた", "prompted": "プロンプトされた",
"required": "必須", "required": "必須",
"rule": "ルール",
"visible": "表示" "visible": "表示"
}, },
"record": { "record": {

View File

@ -38,7 +38,8 @@
"Token expire": "Token expire", "Token expire": "Token expire",
"Token expire - Tooltip": "Token expire - Tooltip", "Token expire - Tooltip": "Token expire - Tooltip",
"Token format": "Token format", "Token format": "Token format",
"Token format - Tooltip": "Token format - Tooltip" "Token format - Tooltip": "Token format - Tooltip",
"rule": "rule"
}, },
"cert": { "cert": {
"Bit size": "Bit size", "Bit size": "Bit size",
@ -259,6 +260,8 @@
"New Model": "New Model" "New Model": "New Model"
}, },
"organization": { "organization": {
"Account items": "Account items",
"Account items - Tooltip": "Account items - Tooltip",
"Default avatar": "Default avatar", "Default avatar": "Default avatar",
"Edit Organization": "Edit Organization", "Edit Organization": "Edit Organization",
"Favicon": "Favicon", "Favicon": "Favicon",
@ -270,7 +273,9 @@
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"Website URL": "Website URL", "Website URL": "Website URL",
"Website URL - Tooltip": "Unique string-style identifier" "Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
}, },
"payment": { "payment": {
"Confirm your invoice information": "Confirm your invoice information", "Confirm your invoice information": "Confirm your invoice information",
@ -469,7 +474,6 @@
"canUnlink": "canUnlink", "canUnlink": "canUnlink",
"prompted": "prompted", "prompted": "prompted",
"required": "required", "required": "required",
"rule": "rule",
"visible": "visible" "visible": "visible"
}, },
"record": { "record": {

View File

@ -38,7 +38,8 @@
"Token expire": "Токен истекает", "Token expire": "Токен истекает",
"Token expire - Tooltip": "Истек токен - Подсказка", "Token expire - Tooltip": "Истек токен - Подсказка",
"Token format": "Формат токена", "Token format": "Формат токена",
"Token format - Tooltip": "Формат токена - Подсказка" "Token format - Tooltip": "Формат токена - Подсказка",
"rule": "rule"
}, },
"cert": { "cert": {
"Bit size": "Размер бита", "Bit size": "Размер бита",
@ -259,6 +260,8 @@
"New Model": "New Model" "New Model": "New Model"
}, },
"organization": { "organization": {
"Account items": "Account items",
"Account items - Tooltip": "Account items - Tooltip",
"Default avatar": "Аватар по умолчанию", "Default avatar": "Аватар по умолчанию",
"Edit Organization": "Изменить организацию", "Edit Organization": "Изменить организацию",
"Favicon": "Иконка", "Favicon": "Иконка",
@ -270,7 +273,9 @@
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"Website URL": "URL сайта", "Website URL": "URL сайта",
"Website URL - Tooltip": "Unique string-style identifier" "Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
}, },
"payment": { "payment": {
"Confirm your invoice information": "Confirm your invoice information", "Confirm your invoice information": "Confirm your invoice information",
@ -469,7 +474,6 @@
"canUnlink": "canUnlink", "canUnlink": "canUnlink",
"prompted": "запрошено", "prompted": "запрошено",
"required": "обязательный", "required": "обязательный",
"rule": "правило",
"visible": "видимый" "visible": "видимый"
}, },
"record": { "record": {

View File

@ -38,7 +38,8 @@
"Token expire": "Access Token过期", "Token expire": "Access Token过期",
"Token expire - Tooltip": "Access Token过期时间", "Token expire - Tooltip": "Access Token过期时间",
"Token format": "Access Token格式", "Token format": "Access Token格式",
"Token format - Tooltip": "Access Token格式" "Token format - Tooltip": "Access Token格式",
"rule": "规则"
}, },
"cert": { "cert": {
"Bit size": "位大小", "Bit size": "位大小",
@ -259,6 +260,8 @@
"New Model": "添加模型" "New Model": "添加模型"
}, },
"organization": { "organization": {
"Account items": "个人页设置项",
"Account items - Tooltip": "个人设置页面中的项目",
"Default avatar": "默认头像", "Default avatar": "默认头像",
"Edit Organization": "编辑组织", "Edit Organization": "编辑组织",
"Favicon": "图标", "Favicon": "图标",
@ -270,7 +273,9 @@
"Tags": "标签集合", "Tags": "标签集合",
"Tags - Tooltip": "可供用户选择的标签的集合", "Tags - Tooltip": "可供用户选择的标签的集合",
"Website URL": "网页地址", "Website URL": "网页地址",
"Website URL - Tooltip": "网页地址" "Website URL - Tooltip": "网页地址",
"modifyRule": "修改规则",
"viewRule": "查看规则"
}, },
"payment": { "payment": {
"Confirm your invoice information": "确认您的发票信息", "Confirm your invoice information": "确认您的发票信息",
@ -469,7 +474,6 @@
"canUnlink": "可解绑定", "canUnlink": "可解绑定",
"prompted": "注册后提醒绑定", "prompted": "注册后提醒绑定",
"required": "是否必填项", "required": "是否必填项",
"rule": "规则",
"visible": "是否可见" "visible": "是否可见"
}, },
"record": { "record": {