Compare commits

..

6 Commits

Author SHA1 Message Date
cofecatt
59ff5e02ab fix: Add support for including underscores for username (#1210)
* fix: Add support for including underscores for username

* Update check.go

Co-authored-by: Yang Luo <hsluoyz@qq.com>
2022-10-11 19:39:19 +08:00
xxrl
8d41508d6b fix: center loading in account page (#1209)
* fix: center loading in account page

* Update UserEditPage.js

Co-authored-by: Yang Luo <hsluoyz@qq.com>
2022-10-11 00:52:08 +08:00
Gucheng Wang
04f70cf012 Improve renderRightDropdown() 2022-10-10 22:53:47 +08:00
Chell
83724c73f9 feat: fix pad and mobile views (#1202)
* fix figure width

* fix: pad resolution menu

* feat: drawer style mobile menu

* fix: menu button i18n
2022-10-10 22:37:25 +08:00
Gucheng Wang
33e419e133 Show more items to org admin 2022-10-10 21:58:17 +08:00
Gucheng Wang
b832c304ae Can get owner in getObject() 2022-10-10 20:56:55 +08:00
14 changed files with 69 additions and 35 deletions

View File

@@ -322,11 +322,9 @@ func CheckUsername(name string) string {
} }
// https://stackoverflow.com/questions/58726546/github-username-convention-using-regex // https://stackoverflow.com/questions/58726546/github-username-convention-using-regex
re, _ := regexp.Compile("^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$") re, _ := regexp.Compile("^[a-zA-Z0-9]+((?:-[a-zA-Z0-9]+)|(?:_[a-zA-Z0-9]+))*$")
if !re.MatchString(name) { if !re.MatchString(name) {
return fmt.Sprintf("The name '%s' may only contain alphanumeric characters or hyphens, "+ return "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline."
"cannot have multiple consecutive hyphens, "+
"and cannot begin or end with a hyphen.", name)
} }
return "" return ""

View File

@@ -63,11 +63,16 @@ func getObject(ctx *context.Context) (string, string) {
if method == http.MethodGet { if method == http.MethodGet {
// query == "?id=built-in/admin" // query == "?id=built-in/admin"
id := ctx.Input.Query("id") id := ctx.Input.Query("id")
if id == "" { if id != "" {
return "", "" return util.GetOwnerAndNameFromId(id)
} }
return util.GetOwnerAndNameFromId(id) owner := ctx.Input.Query("owner")
if owner != "" {
return owner, ""
}
return "", ""
} else { } else {
body := ctx.Input.RequestBody body := ctx.Input.RequestBody

View File

@@ -16,8 +16,8 @@ import React, {Component} from "react";
import "./App.less"; import "./App.less";
import {Helmet} from "react-helmet"; import {Helmet} from "react-helmet";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
import {DownOutlined, LogoutOutlined, SettingOutlined} from "@ant-design/icons"; import {BarsOutlined, DownOutlined, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
import {Avatar, BackTop, Button, Card, Dropdown, Layout, Menu, Result} from "antd"; import {Avatar, BackTop, Button, Card, Drawer, Dropdown, Layout, Menu, Result} from "antd";
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom"; import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
import OrganizationListPage from "./OrganizationListPage"; import OrganizationListPage from "./OrganizationListPage";
import OrganizationEditPage from "./OrganizationEditPage"; import OrganizationEditPage from "./OrganizationEditPage";
@@ -85,6 +85,7 @@ class App extends Component {
selectedMenuKey: 0, selectedMenuKey: 0,
account: undefined, account: undefined,
uri: null, uri: null,
menuVisible: false,
}; };
Setting.initServerUrl(); Setting.initServerUrl();
@@ -298,12 +299,12 @@ class App extends Component {
<Menu onClick={this.handleRightDropdownClick.bind(this)}> <Menu onClick={this.handleRightDropdownClick.bind(this)}>
<Menu.Item key="/account"> <Menu.Item key="/account">
<SettingOutlined /> <SettingOutlined />
&nbsp; &nbsp;&nbsp;
{i18next.t("account:My Account")} {i18next.t("account:My Account")}
</Menu.Item> </Menu.Item>
<Menu.Item key="/logout"> <Menu.Item key="/logout">
<LogoutOutlined /> <LogoutOutlined />
&nbsp; &nbsp;&nbsp;
{i18next.t("account:Logout")} {i18next.t("account:Logout")}
</Menu.Item> </Menu.Item>
</Menu> </Menu>
@@ -388,9 +389,6 @@ class App extends Component {
</Link> </Link>
</Menu.Item> </Menu.Item>
); );
}
if (Setting.isAdminUser(this.state.account)) {
res.push( res.push(
<Menu.Item key="/roles"> <Menu.Item key="/roles">
<Link to="/roles"> <Link to="/roles">
@@ -598,6 +596,18 @@ class App extends Component {
); );
} }
onClose = () => {
this.setState({
menuVisible: false,
});
};
showMenu = () => {
this.setState({
menuVisible: true,
});
};
renderContent() { renderContent() {
if (!Setting.isMobile()) { if (!Setting.isMobile()) {
return ( return (
@@ -616,7 +626,7 @@ class App extends Component {
// theme="dark" // theme="dark"
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"} mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
selectedKeys={[`${this.state.selectedMenuKey}`]} selectedKeys={[`${this.state.selectedMenuKey}`]}
style={{lineHeight: "64px", width: "78%", position: "absolute", left: "145px"}} style={{lineHeight: "64px", position: "absolute", left: "145px", right: "200px"}}
> >
{ {
this.renderMenu() this.renderMenu()
@@ -649,22 +659,28 @@ class App extends Component {
</Link> </Link>
) )
} }
<Menu <Drawer title={i18next.t("general:Close")} placement="left" visible={this.state.menuVisible} onClose={this.onClose}>
// theme="dark" <Menu
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"} // theme="dark"
selectedKeys={[`${this.state.selectedMenuKey}`]} mode={(Setting.isMobile()) ? "inline" : "horizontal"}
style={{lineHeight: "64px"}} selectedKeys={[`${this.state.selectedMenuKey}`]}
> style={{lineHeight: "64px"}}
{ onClick={this.onClose}
this.renderMenu() >
}
<div style = {{float: "right"}}>
{ {
this.renderAccount() this.renderMenu()
} }
<SelectLanguageBox /> </Menu>
</div> </Drawer>
</Menu> <Button icon={<BarsOutlined />} onClick={this.showMenu} type="text">
{i18next.t("general:Menu")}
</Button>
<div style = {{float: "right"}}>
{
this.renderAccount()
}
<SelectLanguageBox />
</div>
</Header> </Header>
{ {
this.renderRouter() this.renderRouter()

View File

@@ -341,7 +341,7 @@ class PermissionListPage extends BaseListPage {
this.setState({loading: true}); this.setState({loading: true});
const getPermissions = Setting.isLocalAdminUser(this.props.account) ? PermissionBackend.getPermissions : PermissionBackend.getPermissionsBySubmitter; const getPermissions = Setting.isLocalAdminUser(this.props.account) ? PermissionBackend.getPermissions : PermissionBackend.getPermissionsBySubmitter;
getPermissions("", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder) getPermissions(Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
.then((res) => { .then((res) => {
if (res.status === "ok") { if (res.status === "ok") {
this.setState({ this.setState({

View File

@@ -25,7 +25,7 @@ class RoleListPage extends BaseListPage {
newRole() { newRole() {
const randomName = Setting.getRandomName(); const randomName = Setting.getRandomName();
return { return {
owner: "built-in", owner: this.props.account.owner,
name: `role_${randomName}`, name: `role_${randomName}`,
createdTime: moment().format(), createdTime: moment().format(),
displayName: `New Role - ${randomName}`, displayName: `New Role - ${randomName}`,
@@ -211,7 +211,7 @@ class RoleListPage extends BaseListPage {
value = params.type; value = params.type;
} }
this.setState({loading: true}); this.setState({loading: true});
RoleBackend.getRoles("", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder) RoleBackend.getRoles(Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
.then((res) => { .then((res) => {
if (res.status === "ok") { if (res.status === "ok") {
this.setState({ this.setState({

View File

@@ -661,7 +661,7 @@ class UserEditPage extends React.Component {
return ( return (
<div> <div>
{ {
this.state.loading ? <Spin size="large" /> : ( this.state.loading ? <Spin size="large" style={{marginLeft: "50%", marginTop: "10%"}} /> : (
this.state.user !== null ? this.renderUser() : this.state.user !== null ? this.renderUser() :
<Result <Result
status="404" status="404"

View File

@@ -44,10 +44,11 @@ class SingleCard extends React.Component {
return ( return (
<Card.Grid style={gridStyle} onClick={() => Setting.goToLinkSoft(this, silentSigninLink)}> <Card.Grid style={gridStyle} onClick={() => Setting.goToLinkSoft(this, silentSigninLink)}>
<img src={logo} alt="logo" height={60} style={{marginBottom: "20px"}} /> <img src={logo} alt="logo" width={"100%"} style={{marginBottom: "20px"}} />
<Meta <Meta
title={title} title={title}
description={desc} description={desc}
style={{justifyContent: "center"}}
/> />
</Card.Grid> </Card.Grid>
); );
@@ -61,7 +62,7 @@ class SingleCard extends React.Component {
<Card <Card
hoverable hoverable
cover={ cover={
<img alt="logo" src={logo} style={{width: "100%", height: "210px", objectFit: "scale-down"}} /> <img alt="logo" src={logo} style={{width: "100%", objectFit: "scale-down"}} />
} }
onClick={() => Setting.goToLinkSoft(this, silentSigninLink)} onClick={() => Setting.goToLinkSoft(this, silentSigninLink)}
style={isSingle ? {width: "320px"} : {width: "100%"}} style={isSingle ? {width: "320px"} : {width: "100%"}}

View File

@@ -133,6 +133,7 @@
"Certs": "Certs", "Certs": "Certs",
"Click to Upload": "Click to Upload", "Click to Upload": "Click to Upload",
"Client IP": "Client-IP", "Client IP": "Client-IP",
"Close": "Close",
"Created time": "Erstellte Zeit", "Created time": "Erstellte Zeit",
"Default application": "Default application", "Default application": "Default application",
"Default application - Tooltip": "Default application - Tooltip", "Default application - Tooltip": "Default application - Tooltip",
@@ -165,6 +166,7 @@
"Logo - Tooltip": "App's image tag", "Logo - Tooltip": "App's image tag",
"Master password": "Master-Passwort", "Master password": "Master-Passwort",
"Master password - Tooltip": "Masterpasswort - Tooltip", "Master password - Tooltip": "Masterpasswort - Tooltip",
"Menu": "Menu",
"Method": "Methode", "Method": "Methode",
"Model": "Model", "Model": "Model",
"Model - Tooltip": "Model - Tooltip", "Model - Tooltip": "Model - Tooltip",

View File

@@ -133,6 +133,7 @@
"Certs": "Certs", "Certs": "Certs",
"Click to Upload": "Click to Upload", "Click to Upload": "Click to Upload",
"Client IP": "Client IP", "Client IP": "Client IP",
"Close": "Close",
"Created time": "Created time", "Created time": "Created time",
"Default application": "Default application", "Default application": "Default application",
"Default application - Tooltip": "Default application - Tooltip", "Default application - Tooltip": "Default application - Tooltip",
@@ -165,6 +166,7 @@
"Logo - Tooltip": "Logo - Tooltip", "Logo - Tooltip": "Logo - Tooltip",
"Master password": "Master password", "Master password": "Master password",
"Master password - Tooltip": "Master password - Tooltip", "Master password - Tooltip": "Master password - Tooltip",
"Menu": "Menu",
"Method": "Method", "Method": "Method",
"Model": "Model", "Model": "Model",
"Model - Tooltip": "Model - Tooltip", "Model - Tooltip": "Model - Tooltip",

View File

@@ -133,6 +133,7 @@
"Certs": "Certes", "Certs": "Certes",
"Click to Upload": "Click to Upload", "Click to Upload": "Click to Upload",
"Client IP": "IP du client", "Client IP": "IP du client",
"Close": "Close",
"Created time": "Date de création", "Created time": "Date de création",
"Default application": "Default application", "Default application": "Default application",
"Default application - Tooltip": "Default application - Tooltip", "Default application - Tooltip": "Default application - Tooltip",
@@ -165,6 +166,7 @@
"Logo - Tooltip": "App's image tag", "Logo - Tooltip": "App's image tag",
"Master password": "Mot de passe maître", "Master password": "Mot de passe maître",
"Master password - Tooltip": "Mot de passe maître - Infobulle", "Master password - Tooltip": "Mot de passe maître - Infobulle",
"Menu": "Menu",
"Method": "Méthode", "Method": "Méthode",
"Model": "Model", "Model": "Model",
"Model - Tooltip": "Model - Tooltip", "Model - Tooltip": "Model - Tooltip",

View File

@@ -133,6 +133,7 @@
"Certs": "Certs", "Certs": "Certs",
"Click to Upload": "Click to Upload", "Click to Upload": "Click to Upload",
"Client IP": "クライアント IP", "Client IP": "クライアント IP",
"Close": "Close",
"Created time": "作成日時", "Created time": "作成日時",
"Default application": "Default application", "Default application": "Default application",
"Default application - Tooltip": "Default application - Tooltip", "Default application - Tooltip": "Default application - Tooltip",
@@ -165,6 +166,7 @@
"Logo - Tooltip": "App's image tag", "Logo - Tooltip": "App's image tag",
"Master password": "マスターパスワード", "Master password": "マスターパスワード",
"Master password - Tooltip": "マスターパスワード - ツールチップ", "Master password - Tooltip": "マスターパスワード - ツールチップ",
"Menu": "Menu",
"Method": "方法", "Method": "方法",
"Model": "Model", "Model": "Model",
"Model - Tooltip": "Model - Tooltip", "Model - Tooltip": "Model - Tooltip",

View File

@@ -133,6 +133,7 @@
"Certs": "Certs", "Certs": "Certs",
"Click to Upload": "Click to Upload", "Click to Upload": "Click to Upload",
"Client IP": "Client IP", "Client IP": "Client IP",
"Close": "Close",
"Created time": "Created time", "Created time": "Created time",
"Default application": "Default application", "Default application": "Default application",
"Default application - Tooltip": "Default application - Tooltip", "Default application - Tooltip": "Default application - Tooltip",
@@ -165,6 +166,7 @@
"Logo - Tooltip": "App's image tag", "Logo - Tooltip": "App's image tag",
"Master password": "Master password", "Master password": "Master password",
"Master password - Tooltip": "Master password - Tooltip", "Master password - Tooltip": "Master password - Tooltip",
"Menu": "Menu",
"Method": "Method", "Method": "Method",
"Model": "Model", "Model": "Model",
"Model - Tooltip": "Model - Tooltip", "Model - Tooltip": "Model - Tooltip",

View File

@@ -133,6 +133,7 @@
"Certs": "Сертификаты", "Certs": "Сертификаты",
"Click to Upload": "Нажмите здесь, чтобы загрузить", "Click to Upload": "Нажмите здесь, чтобы загрузить",
"Client IP": "IP клиента", "Client IP": "IP клиента",
"Close": "Close",
"Created time": "Время создания", "Created time": "Время создания",
"Default application": "Default application", "Default application": "Default application",
"Default application - Tooltip": "Default application - Tooltip", "Default application - Tooltip": "Default application - Tooltip",
@@ -165,6 +166,7 @@
"Logo - Tooltip": "App's image tag", "Logo - Tooltip": "App's image tag",
"Master password": "Мастер-пароль", "Master password": "Мастер-пароль",
"Master password - Tooltip": "Мастер-пароль - Tooltip", "Master password - Tooltip": "Мастер-пароль - Tooltip",
"Menu": "Menu",
"Method": "Метод", "Method": "Метод",
"Model": "Модель", "Model": "Модель",
"Model - Tooltip": "Модель - Подсказка", "Model - Tooltip": "Модель - Подсказка",

View File

@@ -133,6 +133,7 @@
"Certs": "证书", "Certs": "证书",
"Click to Upload": "点击上传", "Click to Upload": "点击上传",
"Client IP": "客户端IP", "Client IP": "客户端IP",
"Close": "关闭",
"Created time": "创建时间", "Created time": "创建时间",
"Default application": "默认应用", "Default application": "默认应用",
"Default application - Tooltip": "默认应用", "Default application - Tooltip": "默认应用",
@@ -165,6 +166,7 @@
"Logo - Tooltip": "应用程序向外展示的图标", "Logo - Tooltip": "应用程序向外展示的图标",
"Master password": "万能密码", "Master password": "万能密码",
"Master password - Tooltip": "可用来登录该组织下的所有用户,方便管理员以该用户身份登录,以解决技术问题", "Master password - Tooltip": "可用来登录该组织下的所有用户,方便管理员以该用户身份登录,以解决技术问题",
"Menu": "目录",
"Method": "方法", "Method": "方法",
"Model": "模型", "Model": "模型",
"Model - Tooltip": "Casbin模型", "Model - Tooltip": "Casbin模型",