feat: add server-side pagination (#312)

Signed-off-by: “seriouszyx” <seriouszyx@foxmail.com>
This commit is contained in:
Yixiang Zhao 2021-11-06 11:32:22 +08:00 committed by GitHub
parent 7520b71198
commit b1db47bad1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 444 additions and 103 deletions

View File

@ -16,7 +16,10 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/casbin/casdoor/object" "github.com/casbin/casdoor/object"
"github.com/casbin/casdoor/util"
) )
// GetApplications // GetApplications
@ -27,9 +30,17 @@ import (
// @router /get-applications [get] // @router /get-applications [get]
func (c *ApiController) GetApplications() { func (c *ApiController) GetApplications() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize")
c.Data["json"] = object.GetApplications(owner) page := c.Input().Get("p")
c.ServeJSON() if limit == "" || page == "" {
c.Data["json"] = object.GetApplications(owner)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetApplicationCount(owner)))
applications := object.GetPaginationApplications(owner, paginator.Offset(), limit)
c.ResponseOk(applications, paginator.Nums())
}
} }
// GetApplication // GetApplication

View File

@ -17,7 +17,9 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/casbin/casdoor/object" "github.com/casbin/casdoor/object"
"github.com/casbin/casdoor/util"
) )
// GetOrganizations ... // GetOrganizations ...
@ -28,9 +30,17 @@ import (
// @router /get-organizations [get] // @router /get-organizations [get]
func (c *ApiController) GetOrganizations() { func (c *ApiController) GetOrganizations() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize")
c.Data["json"] = object.GetOrganizations(owner) page := c.Input().Get("p")
c.ServeJSON() if limit == "" || page == "" {
c.Data["json"] = object.GetOrganizations(owner)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetOrganizationCount(owner)))
organizations := object.GetPaginationOrganizations(owner, paginator.Offset(), limit)
c.ResponseOk(organizations, paginator.Nums())
}
} }
// GetOrganization ... // GetOrganization ...

View File

@ -17,7 +17,9 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/casbin/casdoor/object" "github.com/casbin/casdoor/object"
"github.com/casbin/casdoor/util"
) )
// GetProviders // GetProviders
@ -28,9 +30,17 @@ import (
// @router /get-providers [get] // @router /get-providers [get]
func (c *ApiController) GetProviders() { func (c *ApiController) GetProviders() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize")
c.Data["json"] = object.GetProviders(owner) page := c.Input().Get("p")
c.ServeJSON() if limit == "" || page == "" {
c.Data["json"] = object.GetProviders(owner)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetProviderCount(owner)))
providers := object.GetPaginationProviders(owner, paginator.Offset(), limit)
c.ResponseOk(providers, paginator.Nums())
}
} }
// @Title GetProvider // @Title GetProvider

View File

@ -17,17 +17,30 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/casbin/casdoor/object" "github.com/casbin/casdoor/object"
"github.com/casbin/casdoor/util"
) )
// GetRecords // GetRecords
// @Title GetRecords // @Title GetRecords
// @Description get all records // @Description get all records
// @Param pageSize query string true "The size of each page"
// @Param p query string true "The number of the page"
// @Success 200 {array} object.Records The Response object // @Success 200 {array} object.Records The Response object
// @router /get-records [get] // @router /get-records [get]
func (c *ApiController) GetRecords() { func (c *ApiController) GetRecords() {
c.Data["json"] = object.GetRecords() limit := c.Input().Get("pageSize")
c.ServeJSON() page := c.Input().Get("p")
if limit == "" || page == "" {
c.Data["json"] = object.GetRecords()
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetRecordCount()))
records := object.GetPaginationRecords(paginator.Offset(), limit)
c.ResponseOk(records, paginator.Nums())
}
} }
// GetRecordsByFilter // GetRecordsByFilter

View File

@ -22,6 +22,7 @@ import (
"mime" "mime"
"path/filepath" "path/filepath"
"github.com/astaxie/beego/utils/pagination"
"github.com/casbin/casdoor/object" "github.com/casbin/casdoor/object"
"github.com/casbin/casdoor/util" "github.com/casbin/casdoor/util"
) )
@ -29,9 +30,17 @@ import (
func (c *ApiController) GetResources() { func (c *ApiController) GetResources() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
user := c.Input().Get("user") user := c.Input().Get("user")
limit := c.Input().Get("pageSize")
c.Data["json"] = object.GetResources(owner, user) page := c.Input().Get("p")
c.ServeJSON() if limit == "" || page == "" {
c.Data["json"] = object.GetResources(owner, user)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetResourceCount(owner, user)))
resources := object.GetPaginationResources(owner, user, paginator.Offset(), limit)
c.ResponseOk(resources, paginator.Nums())
}
} }
func (c *ApiController) GetResource() { func (c *ApiController) GetResource() {

View File

@ -17,20 +17,32 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"github.com/astaxie/beego/utils/pagination"
"github.com/casbin/casdoor/object" "github.com/casbin/casdoor/object"
"github.com/casbin/casdoor/util"
) )
// GetTokens // GetTokens
// @Title GetTokens // @Title GetTokens
// @Description get tokens // @Description get tokens
// @Param owner query string true "The owner of tokens" // @Param owner query string true "The owner of tokens"
// @Param pageSize query string true "The size of each page"
// @Param p query string true "The number of the page"
// @Success 200 {array} object.Token The Response object // @Success 200 {array} object.Token The Response object
// @router /get-tokens [get] // @router /get-tokens [get]
func (c *ApiController) GetTokens() { func (c *ApiController) GetTokens() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize")
c.Data["json"] = object.GetTokens(owner) page := c.Input().Get("p")
c.ServeJSON() if limit == "" || page == "" {
c.Data["json"] = object.GetTokens(owner)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetTokenCount(owner)))
tokens := object.GetPaginationTokens(owner, paginator.Offset(), limit)
c.ResponseOk(tokens, paginator.Nums())
}
} }
// GetToken // GetToken

View File

@ -19,8 +19,10 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/astaxie/beego/utils/pagination"
"github.com/casbin/casdoor/object" "github.com/casbin/casdoor/object"
"github.com/casbin/casdoor/original" "github.com/casbin/casdoor/original"
"github.com/casbin/casdoor/util"
) )
// GetGlobalUsers // GetGlobalUsers
@ -29,8 +31,17 @@ import (
// @Success 200 {array} object.User The Response object // @Success 200 {array} object.User The Response object
// @router /get-global-users [get] // @router /get-global-users [get]
func (c *ApiController) GetGlobalUsers() { func (c *ApiController) GetGlobalUsers() {
c.Data["json"] = object.GetMaskedUsers(object.GetGlobalUsers()) limit := c.Input().Get("pageSize")
c.ServeJSON() page := c.Input().Get("p")
if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedUsers(object.GetGlobalUsers())
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalUserCount()))
users := object.GetPaginationGlobalUsers(paginator.Offset(), limit)
c.ResponseOk(users, paginator.Nums())
}
} }
// GetUsers // GetUsers
@ -41,9 +52,17 @@ func (c *ApiController) GetGlobalUsers() {
// @router /get-users [get] // @router /get-users [get]
func (c *ApiController) GetUsers() { func (c *ApiController) GetUsers() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize")
c.Data["json"] = object.GetMaskedUsers(object.GetUsers(owner)) page := c.Input().Get("p")
c.ServeJSON() if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedUsers(object.GetUsers(owner))
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetUserCount(owner)))
users := object.GetPaginationUsers(owner, paginator.Offset(), limit)
c.ResponseOk(users, paginator.Nums())
}
} }
// GetUser // GetUser

View File

@ -48,6 +48,15 @@ type Application struct {
SigninHtml string `xorm:"mediumtext" json:"signinHtml"` SigninHtml string `xorm:"mediumtext" json:"signinHtml"`
} }
func GetApplicationCount(owner string) int {
count, err := adapter.Engine.Count(&Application{Owner: owner})
if err != nil {
panic(err)
}
return int(count)
}
func GetApplications(owner string) []*Application { func GetApplications(owner string) []*Application {
applications := []*Application{} applications := []*Application{}
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner}) err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner})
@ -58,6 +67,16 @@ func GetApplications(owner string) []*Application {
return applications return applications
} }
func GetPaginationApplications(owner string, offset, limit int) []*Application {
applications := []*Application{}
err := adapter.Engine.Desc("created_time").Limit(limit, offset).Find(&applications, &Application{Owner: owner})
if err != nil {
panic(err)
}
return applications
}
func getProviderMap(owner string) map[string]*Provider { func getProviderMap(owner string) map[string]*Provider {
providers := GetProviders(owner) providers := GetProviders(owner)
m := map[string]*Provider{} m := map[string]*Provider{}

View File

@ -33,6 +33,15 @@ type Organization struct {
DefaultAvatar string `xorm:"varchar(100)" json:"defaultAvatar"` DefaultAvatar string `xorm:"varchar(100)" json:"defaultAvatar"`
} }
func GetOrganizationCount(owner string) int {
count, err := adapter.Engine.Count(&Organization{Owner: owner})
if err != nil {
panic(err)
}
return int(count)
}
func GetOrganizations(owner string) []*Organization { func GetOrganizations(owner string) []*Organization {
organizations := []*Organization{} organizations := []*Organization{}
err := adapter.Engine.Desc("created_time").Find(&organizations, &Organization{Owner: owner}) err := adapter.Engine.Desc("created_time").Find(&organizations, &Organization{Owner: owner})
@ -43,6 +52,16 @@ func GetOrganizations(owner string) []*Organization {
return organizations return organizations
} }
func GetPaginationOrganizations(owner string, offset, limit int) []*Organization {
organizations := []*Organization{}
err := adapter.Engine.Desc("created_time").Limit(limit, offset).Find(&organizations, &Provider{Owner: owner})
if err != nil {
panic(err)
}
return organizations
}
func getOrganization(owner string, name string) *Organization { func getOrganization(owner string, name string) *Organization {
if owner == "" || name == "" { if owner == "" || name == "" {
return nil return nil
@ -57,7 +76,7 @@ func getOrganization(owner string, name string) *Organization {
if existed { if existed {
return &organization return &organization
} }
return nil return nil
} }

View File

@ -64,6 +64,15 @@ func getMaskedProvider(provider *Provider) *Provider {
return p return p
} }
func GetProviderCount(owner string) int {
count, err := adapter.Engine.Count(&Provider{Owner: owner})
if err != nil {
panic(err)
}
return int(count)
}
func GetProviders(owner string) []*Provider { func GetProviders(owner string) []*Provider {
providers := []*Provider{} providers := []*Provider{}
err := adapter.Engine.Desc("created_time").Find(&providers, &Provider{Owner: owner}) err := adapter.Engine.Desc("created_time").Find(&providers, &Provider{Owner: owner})
@ -74,6 +83,16 @@ func GetProviders(owner string) []*Provider {
return providers return providers
} }
func GetPaginationProviders(owner string, offset, limit int) []*Provider {
providers := []*Provider{}
err := adapter.Engine.Desc("created_time").Limit(limit, offset).Find(&providers, &Provider{Owner: owner})
if err != nil {
panic(err)
}
return providers
}
func getProvider(owner string, name string) *Provider { func getProvider(owner string, name string) *Provider {
if owner == "" || name == "" { if owner == "" || name == "" {
return nil return nil

View File

@ -54,6 +54,16 @@ func GetRecords() []*Records {
return records return records
} }
func GetPaginationRecords(offset, limit int) []*Records {
records := []*Records{}
err := adapter.Engine.Desc("id").Limit(limit, offset).Find(&records)
if err != nil {
panic(err)
}
return records
}
func GetRecordsByField(record *Records) []*Records { func GetRecordsByField(record *Records) []*Records {
records := []*Records{} records := []*Records{}
err := adapter.Engine.Find(&records, record) err := adapter.Engine.Find(&records, record)

View File

@ -38,6 +38,15 @@ type Resource struct {
Url string `xorm:"varchar(1000)" json:"url"` Url string `xorm:"varchar(1000)" json:"url"`
} }
func GetResourceCount(owner string, user string) int {
count, err := adapter.Engine.Count(&Resource{Owner: owner, User: user})
if err != nil {
panic(err)
}
return int(count)
}
func GetResources(owner string, user string) []*Resource { func GetResources(owner string, user string) []*Resource {
if owner == "built-in" { if owner == "built-in" {
owner = "" owner = ""
@ -53,6 +62,21 @@ func GetResources(owner string, user string) []*Resource {
return resources return resources
} }
func GetPaginationResources(owner, user string, offset, limit int) []*Resource {
if owner == "built-in" {
owner = ""
user = ""
}
resources := []*Resource{}
err := adapter.Engine.Desc("created_time").Limit(limit, offset).Find(&resources, &Resource{Owner: owner, User: user})
if err != nil {
panic(err)
}
return resources
}
func getResource(owner string, name string) *Resource { func getResource(owner string, name string) *Resource {
resource := Resource{Owner: owner, Name: name} resource := Resource{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&resource) existed, err := adapter.Engine.Get(&resource)

View File

@ -49,6 +49,15 @@ type TokenWrapper struct {
Scope string `json:"scope"` Scope string `json:"scope"`
} }
func GetTokenCount(owner string) int {
count, err := adapter.Engine.Count(&Token{Owner: owner})
if err != nil {
panic(err)
}
return int(count)
}
func GetTokens(owner string) []*Token { func GetTokens(owner string) []*Token {
tokens := []*Token{} tokens := []*Token{}
err := adapter.Engine.Desc("created_time").Find(&tokens, &Token{Owner: owner}) err := adapter.Engine.Desc("created_time").Find(&tokens, &Token{Owner: owner})
@ -59,6 +68,16 @@ func GetTokens(owner string) []*Token {
return tokens return tokens
} }
func GetPaginationTokens(owner string, offset, limit int) []*Token {
tokens := []*Token{}
err := adapter.Engine.Desc("created_time").Limit(limit, offset).Find(&tokens, &Token{Owner: owner})
if err != nil {
panic(err)
}
return tokens
}
func getToken(owner string, name string) *Token { func getToken(owner string, name string) *Token {
if owner == "" || name == "" { if owner == "" || name == "" {
return nil return nil
@ -73,7 +92,7 @@ func getToken(owner string, name string) *Token {
if existed { if existed {
return &token return &token
} }
return nil return nil
} }
@ -87,7 +106,7 @@ func getTokenByCode(code string) *Token {
if existed { if existed {
return &token return &token
} }
return nil return nil
} }

View File

@ -72,6 +72,15 @@ type User struct {
Properties map[string]string `json:"properties"` Properties map[string]string `json:"properties"`
} }
func GetGlobalUserCount() int {
count, err := adapter.Engine.Count(&User{})
if err != nil {
panic(err)
}
return int(count)
}
func GetGlobalUsers() []*User { func GetGlobalUsers() []*User {
users := []*User{} users := []*User{}
err := adapter.Engine.Desc("created_time").Find(&users) err := adapter.Engine.Desc("created_time").Find(&users)
@ -82,6 +91,25 @@ func GetGlobalUsers() []*User {
return users return users
} }
func GetPaginationGlobalUsers(offset, limit int) []*User {
users := []*User{}
err := adapter.Engine.Desc("created_time").Limit(limit, offset).Find(&users)
if err != nil {
panic(err)
}
return users
}
func GetUserCount(owner string) int {
count, err := adapter.Engine.Count(&User{Owner: owner})
if err != nil {
panic(err)
}
return int(count)
}
func GetUsers(owner string) []*User { func GetUsers(owner string) []*User {
users := []*User{} users := []*User{}
err := adapter.Engine.Desc("created_time").Find(&users, &User{Owner: owner}) err := adapter.Engine.Desc("created_time").Find(&users, &User{Owner: owner})
@ -92,6 +120,16 @@ func GetUsers(owner string) []*User {
return users return users
} }
func GetPaginationUsers(owner string, offset, limit int) []*User {
users := []*User{}
err := adapter.Engine.Desc("created_time").Limit(limit, offset).Find(&users, &User{Owner: owner})
if err != nil {
panic(err)
}
return users
}
func getUser(owner string, name string) *User { func getUser(owner string, name string) *User {
if owner == "" || name == "" { if owner == "" || name == "" {
return nil return nil

View File

@ -27,28 +27,33 @@ class ApplicationListPage extends React.Component {
this.state = { this.state = {
classes: props, classes: props,
applications: null, applications: null,
total: 0,
}; };
} }
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this.getApplications(); this.getApplications(1, 10);
} }
getApplications() { getApplications(page, pageSize) {
ApplicationBackend.getApplications("admin") ApplicationBackend.getApplications("admin", page, pageSize)
.then((res) => { .then((res) => {
this.setState({ if (res.status === "ok") {
applications: res, this.setState({
}); applications: res.data,
total: res.data2
});
}
}); });
} }
newApplication() { newApplication() {
var randomName = Math.random().toString(36).slice(-6)
return { return {
owner: "admin", // this.props.account.applicationname, owner: "admin", // this.props.account.applicationname,
name: `application_${this.state.applications.length}`, name: `application_${randomName}`,
createdTime: moment().format(), createdTime: moment().format(),
displayName: `New Application - ${this.state.applications.length}`, displayName: `New Application - ${randomName}`,
logo: "https://cdn.casbin.com/logo/logo_1024x256.png", logo: "https://cdn.casbin.com/logo/logo_1024x256.png",
enablePassword: true, enablePassword: true,
enableSignUp: true, enableSignUp: true,
@ -75,6 +80,7 @@ class ApplicationListPage extends React.Component {
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),
total: this.state.total + 1
}); });
} }
) )
@ -89,6 +95,7 @@ class ApplicationListPage extends React.Component {
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),
total: this.state.total - 1
}); });
} }
) )
@ -213,9 +220,18 @@ class ApplicationListPage extends React.Component {
}, },
]; ];
const paginationProps = {
total: this.state.total,
showQuickJumper: true,
showSizeChanger: true,
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.total),
onChange: (page, pageSize) => this.getApplications(page, pageSize),
onShowSizeChange: (current, size) => this.getApplications(current, size),
};
return ( return (
<div> <div>
<Table scroll={{x: 'max-content'}} columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table scroll={{x: 'max-content'}} columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={paginationProps}
title={() => ( title={() => (
<div> <div>
{i18next.t("general:Applications")}&nbsp;&nbsp;&nbsp;&nbsp; {i18next.t("general:Applications")}&nbsp;&nbsp;&nbsp;&nbsp;

View File

@ -26,28 +26,33 @@ class OrganizationListPage extends React.Component {
this.state = { this.state = {
classes: props, classes: props,
organizations: null, organizations: null,
total: 0
}; };
} }
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this.getOrganizations(); this.getOrganizations(1, 10);
} }
getOrganizations() { getOrganizations(page, pageSize) {
OrganizationBackend.getOrganizations("admin") OrganizationBackend.getOrganizations("admin", page, pageSize)
.then((res) => { .then((res) => {
this.setState({ if (res.status === "ok") {
organizations: res, this.setState({
}); organizations: res.data,
total: res.data2
});
}
}); });
} }
newOrganization() { newOrganization() {
var randomName = Math.random().toString(36).slice(-6)
return { return {
owner: "admin", // this.props.account.organizationname, owner: "admin", // this.props.account.organizationname,
name: `organization_${this.state.organizations.length}`, name: `organization_${randomName}`,
createdTime: moment().format(), createdTime: moment().format(),
displayName: `New Organization - ${this.state.organizations.length}`, displayName: `New Organization - ${randomName}`,
websiteUrl: "https://door.casbin.com", websiteUrl: "https://door.casbin.com",
favicon: "https://cdn.casbin.com/static/favicon.ico", favicon: "https://cdn.casbin.com/static/favicon.ico",
passwordType: "plain", passwordType: "plain",
@ -64,6 +69,7 @@ class OrganizationListPage extends React.Component {
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),
total: this.state.total + 1
}); });
} }
) )
@ -78,6 +84,7 @@ class OrganizationListPage extends React.Component {
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),
total: this.state.total - 1
}); });
} }
) )
@ -197,9 +204,18 @@ class OrganizationListPage extends React.Component {
}, },
]; ];
const paginationProps = {
total: this.state.total,
showQuickJumper: true,
showSizeChanger: true,
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.total),
onChange: (page, pageSize) => this.getOrganizations(page, pageSize),
onShowSizeChange: (current, size) => this.getOrganizations(current, size),
};
return ( return (
<div> <div>
<Table scroll={{x: 'max-content'}} columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table scroll={{x: 'max-content'}} columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={paginationProps}
title={() => ( title={() => (
<div> <div>
{i18next.t("general:Organizations")}&nbsp;&nbsp;&nbsp;&nbsp; {i18next.t("general:Organizations")}&nbsp;&nbsp;&nbsp;&nbsp;

View File

@ -27,28 +27,33 @@ class ProviderListPage extends React.Component {
this.state = { this.state = {
classes: props, classes: props,
providers: null, providers: null,
total: 0,
}; };
} }
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this.getProviders(); this.getProviders(1, 10);
} }
getProviders() { getProviders(page, pageSize) {
ProviderBackend.getProviders("admin") ProviderBackend.getProviders("admin", page, pageSize)
.then((res) => { .then((res) => {
this.setState({ if (res.status === "ok") {
providers: res, this.setState({
}); providers: res.data,
total: res.data2
});
}
}); });
} }
newProvider() { newProvider() {
var randomName = Math.random().toString(36).slice(-6)
return { return {
owner: "admin", // this.props.account.providername, owner: "admin", // this.props.account.providername,
name: `provider_${this.state.providers.length}`, name: `provider_${randomName}`,
createdTime: moment().format(), createdTime: moment().format(),
displayName: `New Provider - ${this.state.providers.length}`, displayName: `New Provider - ${randomName}`,
category: "OAuth", category: "OAuth",
type: "GitHub", type: "GitHub",
method: "Normal", method: "Normal",
@ -68,6 +73,7 @@ class ProviderListPage extends React.Component {
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),
total: this.state.total + 1
}); });
} }
) )
@ -82,6 +88,7 @@ class ProviderListPage extends React.Component {
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),
total: this.state.total - 1
}); });
} }
) )
@ -212,9 +219,18 @@ class ProviderListPage extends React.Component {
}, },
]; ];
const paginationProps = {
total: this.state.total,
showQuickJumper: true,
showSizeChanger: true,
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.total),
onChange: (page, pageSize) => this.getProviders(page, pageSize),
onShowSizeChange: (current, size) => this.getProviders(current, size),
};
return ( return (
<div> <div>
<Table scroll={{x: 'max-content'}} columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table scroll={{x: 'max-content'}} columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={paginationProps}
title={() => ( title={() => (
<div> <div>
{i18next.t("general:Providers")}&nbsp;&nbsp;&nbsp;&nbsp; {i18next.t("general:Providers")}&nbsp;&nbsp;&nbsp;&nbsp;

View File

@ -25,19 +25,23 @@ class RecordListPage extends React.Component {
this.state = { this.state = {
classes: props, classes: props,
records: null, records: null,
total: 0,
}; };
} }
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this.getRecords(); this.getRecords(1, 10);
} }
getRecords() { getRecords(page, pageSize) {
RecordBackend.getRecords() RecordBackend.getRecords(page, pageSize)
.then((res) => { .then((res) => {
this.setState({ if (res.status === "ok") {
records: res, this.setState({
}); records: res.data,
total: res.data2
});
}
}); });
} }
@ -124,9 +128,18 @@ class RecordListPage extends React.Component {
}, },
]; ];
const paginationProps = {
total: this.state.total,
showQuickJumper: true,
showSizeChanger: true,
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.total),
onChange: (page, pageSize) => this.getRecords(page, pageSize),
onShowSizeChange: (current, size) => this.getRecords(current, size),
};
return ( return (
<div> <div>
<Table scroll={{x: 'max-content'}} columns={columns} dataSource={records} rowKey="id" size="middle" bordered pagination={{pageSize: 100}} <Table scroll={{x: 'max-content'}} columns={columns} dataSource={records} rowKey="id" size="middle" bordered pagination={paginationProps}
title={() => ( title={() => (
<div> <div>
{i18next.t("general:Records")}&nbsp;&nbsp;&nbsp;&nbsp; {i18next.t("general:Records")}&nbsp;&nbsp;&nbsp;&nbsp;

View File

@ -29,19 +29,23 @@ class ResourceListPage extends React.Component {
resources: null, resources: null,
fileList: [], fileList: [],
uploading: false, uploading: false,
total: 0,
}; };
} }
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this.getResources(); this.getResources(1, 10);
} }
getResources() { getResources(page, pageSize) {
ResourceBackend.getResources(this.props.account.owner, this.props.account.name) ResourceBackend.getResources(this.props.account.owner, this.props.account.name, page, pageSize)
.then((res) => { .then((res) => {
this.setState({ if (res.status === "ok") {
resources: res, this.setState({
}); resources: res.data,
total: res.data2
});
}
}); });
} }
@ -51,6 +55,7 @@ class ResourceListPage extends React.Component {
Setting.showMessage("success", `Resource deleted successfully`); Setting.showMessage("success", `Resource deleted successfully`);
this.setState({ this.setState({
resources: Setting.deleteRow(this.state.resources, i), resources: Setting.deleteRow(this.state.resources, i),
total: this.state.total - 1
}); });
} }
) )
@ -260,9 +265,18 @@ class ResourceListPage extends React.Component {
}, },
]; ];
const paginationProps = {
total: this.state.total,
showQuickJumper: true,
showSizeChanger: true,
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.total),
onChange: (page, pageSize) => this.getResources(page, pageSize),
onShowSizeChange: (current, size) => this.getResources(current, size),
};
return ( return (
<div> <div>
<Table scroll={{x: 'max-content'}} columns={columns} dataSource={resources} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table scroll={{x: 'max-content'}} columns={columns} dataSource={resources} rowKey="name" size="middle" bordered pagination={paginationProps}
title={() => ( title={() => (
<div> <div>
{i18next.t("general:Resources")}&nbsp;&nbsp;&nbsp;&nbsp; {i18next.t("general:Resources")}&nbsp;&nbsp;&nbsp;&nbsp;

View File

@ -26,26 +26,30 @@ class TokenListPage extends React.Component {
this.state = { this.state = {
classes: props, classes: props,
tokens: null, tokens: null,
total: 0,
}; };
} }
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this.getTokens(); this.getTokens(1, 10);
} }
getTokens() { getTokens(page, pageSize) {
TokenBackend.getTokens("admin") TokenBackend.getTokens("admin", page, pageSize)
.then((res) => { .then((res) => {
this.setState({ if (res.status === "ok") {
tokens: res, this.setState({
}); tokens: res.data,
total: res.data2
});
}
}); });
} }
newToken() { newToken() {
return { return {
owner: "admin", // this.props.account.tokenname, owner: "admin", // this.props.account.tokenname,
name: `token_${this.state.tokens.length}`, name: `token_${Math.random().toString(36).slice(-6)}`,
createdTime: moment().format(), createdTime: moment().format(),
application: "app-built-in", application: "app-built-in",
accessToken: "", accessToken: "",
@ -62,6 +66,7 @@ class TokenListPage extends React.Component {
Setting.showMessage("success", `Token added successfully`); Setting.showMessage("success", `Token added successfully`);
this.setState({ this.setState({
tokens: Setting.prependRow(this.state.tokens, newToken), tokens: Setting.prependRow(this.state.tokens, newToken),
total: this.state.total + 1
}); });
} }
) )
@ -76,6 +81,7 @@ class TokenListPage extends React.Component {
Setting.showMessage("success", `Token deleted successfully`); Setting.showMessage("success", `Token deleted successfully`);
this.setState({ this.setState({
tokens: Setting.deleteRow(this.state.tokens, i), tokens: Setting.deleteRow(this.state.tokens, i),
total: this.state.total - 1
}); });
} }
) )
@ -217,9 +223,18 @@ class TokenListPage extends React.Component {
}, },
]; ];
const paginationProps = {
total: this.state.total,
showQuickJumper: true,
showSizeChanger: true,
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.total),
onChange: (page, pageSize) => this.getTokens(page, pageSize),
onShowSizeChange: (current, size) => this.getTokens(current, size),
};
return ( return (
<div> <div>
<Table scroll={{x: 'max-content'}} columns={columns} dataSource={tokens} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table scroll={{x: 'max-content'}} columns={columns} dataSource={tokens} rowKey="name" size="middle" bordered pagination={paginationProps}
title={() => ( title={() => (
<div> <div>
{i18next.t("general:Tokens")}&nbsp;&nbsp;&nbsp;&nbsp; {i18next.t("general:Tokens")}&nbsp;&nbsp;&nbsp;&nbsp;

View File

@ -27,39 +27,47 @@ class UserListPage extends React.Component {
classes: props, classes: props,
users: null, users: null,
organizationName: props.match.params.organizationName, organizationName: props.match.params.organizationName,
total: 0,
}; };
} }
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this.getUsers(); this.getUsers(1, 10);
} }
getUsers() { getUsers(page, pageSize) {
if (this.state.organizationName === undefined) { if (this.state.organizationName === undefined) {
UserBackend.getGlobalUsers() UserBackend.getGlobalUsers(page, pageSize)
.then((res) => { .then((res) => {
this.setState({ if (res.status === "ok") {
users: res, this.setState({
}); users: res.data,
total: res.data2
});
}
}); });
} else { } else {
UserBackend.getUsers(this.state.organizationName) UserBackend.getUsers(this.state.organizationName, page, pageSize)
.then((res) => { .then((res) => {
this.setState({ if (res.status === "ok") {
users: res, this.setState({
}); users: res.data,
total: res.data2
});
}
}); });
} }
} }
newUser() { newUser() {
var randomName = Math.random().toString(36).slice(-6)
return { return {
owner: "built-in", // this.props.account.username, owner: "built-in", // this.props.account.username,
name: `user_${this.state.users.length}`, name: `user_${randomName}`,
createdTime: moment().format(), createdTime: moment().format(),
type: "normal-user", type: "normal-user",
password: "123", password: "123",
displayName: `New User - ${this.state.users.length}`, displayName: `New User - ${randomName}`,
avatar: "https://casbin.org/img/casbin.svg", avatar: "https://casbin.org/img/casbin.svg",
email: "user@example.com", email: "user@example.com",
phone: "12345678", phone: "12345678",
@ -81,6 +89,7 @@ class UserListPage extends React.Component {
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),
total: this.state.total + 1
}); });
} }
) )
@ -95,6 +104,7 @@ class UserListPage extends React.Component {
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),
total: this.state.total - 1
}); });
} }
) )
@ -287,9 +297,18 @@ class UserListPage extends React.Component {
}, },
]; ];
const paginationProps = {
total: this.state.total,
showQuickJumper: true,
showSizeChanger: true,
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.total),
onChange: (page, pageSize) => this.getUsers(page, pageSize),
onShowSizeChange: (current, size) => this.getUsers(current, size),
};
return ( return (
<div> <div>
<Table scroll={{x: 'max-content'}} columns={columns} dataSource={users} rowKey="name" size="middle" bordered pagination={{pageSize: 100}} <Table scroll={{x: 'max-content'}} columns={columns} dataSource={users} rowKey="name" size="middle" bordered pagination={paginationProps}
title={() => ( title={() => (
<div> <div>
{i18next.t("general:Users")}&nbsp;&nbsp;&nbsp;&nbsp; {i18next.t("general:Users")}&nbsp;&nbsp;&nbsp;&nbsp;

View File

@ -14,8 +14,8 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getApplications(owner) { export function getApplications(owner, page, pageSize) {
return fetch(`${Setting.ServerUrl}/api/get-applications?owner=${owner}`, { return fetch(`${Setting.ServerUrl}/api/get-applications?owner=${owner}&p=${page}&pageSize=${pageSize}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());

View File

@ -14,8 +14,8 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getOrganizations(owner) { export function getOrganizations(owner, page, pageSize) {
return fetch(`${Setting.ServerUrl}/api/get-organizations?owner=${owner}`, { return fetch(`${Setting.ServerUrl}/api/get-organizations?owner=${owner}&p=${page}&pageSize=${pageSize}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());

View File

@ -14,8 +14,8 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getProviders(owner) { export function getProviders(owner, page, pageSize) {
return fetch(`${Setting.ServerUrl}/api/get-providers?owner=${owner}`, { return fetch(`${Setting.ServerUrl}/api/get-providers?owner=${owner}&p=${page}&pageSize=${pageSize}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());

View File

@ -14,8 +14,8 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getRecords() { export function getRecords(page, pageSize) {
return fetch(`${Setting.ServerUrl}/api/get-records`, { return fetch(`${Setting.ServerUrl}/api/get-records?pageSize=${pageSize}&p=${page}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());

View File

@ -14,8 +14,8 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getResources(owner, user) { export function getResources(owner, user, page, pageSize) {
return fetch(`${Setting.ServerUrl}/api/get-resources?owner=${owner}&user=${user}`, { return fetch(`${Setting.ServerUrl}/api/get-resources?owner=${owner}&user=${user}&p=${page}&pageSize=${pageSize}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());

View File

@ -14,8 +14,8 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
export function getTokens(owner) { export function getTokens(owner, page, pageSize) {
return fetch(`${Setting.ServerUrl}/api/get-tokens?owner=${owner}`, { return fetch(`${Setting.ServerUrl}/api/get-tokens?owner=${owner}&p=${page}&pageSize=${pageSize}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());

View File

@ -15,15 +15,15 @@
import * as Setting from "../Setting"; import * as Setting from "../Setting";
import i18next from "i18next"; import i18next from "i18next";
export function getGlobalUsers() { export function getGlobalUsers(page, pageSize) {
return fetch(`${Setting.ServerUrl}/api/get-global-users`, { return fetch(`${Setting.ServerUrl}/api/get-global-users?p=${page}&pageSize=${pageSize}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());
} }
export function getUsers(owner) { export function getUsers(owner, page, pageSize) {
return fetch(`${Setting.ServerUrl}/api/get-users?owner=${owner}`, { return fetch(`${Setting.ServerUrl}/api/get-users?owner=${owner}&p=${page}&pageSize=${pageSize}`, {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}).then(res => res.json()); }).then(res => res.json());