Compare commits

...

16 Commits

Author SHA1 Message Date
hsluoyz
6db9c6861d Revert "feat: fix the bug that sycner does not initialize (#1924)"
This reverts commit ec3c24ba68.
2023-06-03 09:12:49 +08:00
Yang Luo
0ec22ae6ff Fix null bug in getLanguage() 2023-06-03 00:29:08 +08:00
Yaodong Yu
ec3c24ba68 feat: fix the bug that sycner does not initialize (#1924) 2023-06-03 00:15:28 +08:00
Yang Luo
ed688efdbb Fix bug in org user list page 2023-06-02 22:09:18 +08:00
Yang Luo
06543a01d3 Add organization to /userinfo 2023-06-02 21:51:05 +08:00
Yang Luo
70c372c3f7 Fix Provider API responses 2023-06-02 11:49:38 +08:00
Yang Luo
b1b3184e75 Speed up user pagination query 2023-06-01 22:55:44 +08:00
Yang Luo
5349fa7ff3 Speed up object.DoMigration() 2023-06-01 22:25:19 +08:00
907997375
9147225956 feat: fix table sticky columns on chat and message pages (#1917) 2023-06-01 21:02:21 +08:00
Yang Luo
11f3af1ede Improve Select modes 2023-05-31 17:36:11 +08:00
Yang Luo
0aa4df40c6 Fix i18n 2023-05-31 11:46:03 +08:00
Yang Luo
7caa885131 Fix subscription bugs 2023-05-31 11:33:01 +08:00
Yang Luo
f4b69cad9b Add owner to select-plan page 2023-05-31 00:29:54 +08:00
Yang Luo
fb1db7823b Add DummyPaymentProvider 2023-05-30 23:25:58 +08:00
Sergey Zabodalov
10e66f8020 fix: Get logger configuration from app.conf file (#1907)
* feat: Get logger configuration from file

* feat: Get logger configuration from file

* Remove GetConfigLogs()
2023-05-30 21:30:09 +08:00
Yang Luo
4c8648d323 Add PaypalPaymentProvider 2023-05-30 20:32:05 +08:00
49 changed files with 545 additions and 430 deletions

View File

@@ -21,3 +21,4 @@ isDemoMode = false
batchSize = 100
ldapServerPort = 389
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}

View File

@@ -109,3 +109,19 @@ func TestGetConfigQuota(t *testing.T) {
assert.Equal(t, scenery.expected, quota)
}
}
func TestGetConfigLogs(t *testing.T) {
scenarios := []struct {
description string
expected string
}{
{"Default log config", `{"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}`},
}
err := beego.LoadAppConfig("ini", "app.conf")
assert.Nil(t, err)
for _, scenery := range scenarios {
quota := GetConfigString("logConfig")
assert.Equal(t, scenery.expected, quota)
}
}

View File

@@ -49,8 +49,7 @@ func (c *ApiController) GetProviders() {
panic(err)
}
c.Data["json"] = object.GetMaskedProviders(providers, isMaskEnabled)
c.ServeJSON()
c.ResponseOk(object.GetMaskedProviders(providers, isMaskEnabled))
} else {
limit := util.ParseInt(limit)
count, err := object.GetProviderCount(owner, field, value)
@@ -96,8 +95,7 @@ func (c *ApiController) GetGlobalProviders() {
panic(err)
}
c.Data["json"] = object.GetMaskedProviders(globalProviders, isMaskEnabled)
c.ServeJSON()
c.ResponseOk(object.GetMaskedProviders(globalProviders, isMaskEnabled))
} else {
limit := util.ParseInt(limit)
count, err := object.GetGlobalProviderCount(field, value)
@@ -138,8 +136,7 @@ func (c *ApiController) GetProvider() {
return
}
c.Data["json"] = object.GetMaskedProvider(provider, isMaskEnabled)
c.ServeJSON()
c.ResponseOk(object.GetMaskedProvider(provider, isMaskEnabled))
}
// UpdateProvider

1
go.mod
View File

@@ -42,6 +42,7 @@ require (
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
github.com/nyaruka/phonenumbers v1.1.5
github.com/pkoukk/tiktoken-go v0.1.1
github.com/plutov/paypal/v4 v4.7.0
github.com/prometheus/client_golang v1.11.1
github.com/prometheus/client_model v0.2.0
github.com/qiangmzsx/string-adapter/v2 v2.1.0

3
go.sum
View File

@@ -495,6 +495,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkoukk/tiktoken-go v0.1.1 h1:jtkYlIECjyM9OW1w4rjPmTohK4arORP9V25y6TM6nXo=
github.com/pkoukk/tiktoken-go v0.1.1/go.mod h1:boMWvk9pQCOTx11pgu0DrIdrAKgQzzJKUP6vLXaz7Rw=
github.com/plutov/paypal/v4 v4.7.0 h1:6TRvYD4ny6yQfHaABeStNf43GFM1wpW5jU/XEDGQmq0=
github.com/plutov/paypal/v4 v4.7.0/go.mod h1:D56boafCRGcF/fEM0w282kj0fCDKIyrwOPX/Te1jCmw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -593,6 +595,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=

View File

@@ -73,7 +73,7 @@ func main() {
beego.BConfig.WebConfig.Session.SessionCookieLifeTime = 3600 * 24 * 30
// beego.BConfig.WebConfig.Session.SessionCookieSameSite = http.SameSiteNoneMode
err := logs.SetLogger("file", `{"filename":"logs/casdoor.log","maxdays":99999,"perm":"0770"}`)
err := logs.SetLogger(logs.AdapterFile, conf.GetConfigString("logConfig"))
if err != nil {
panic(err)
}

View File

@@ -280,3 +280,48 @@ func GetSession(owner string, offset, limit int, field, value, sortField, sortOr
}
return session
}
func GetSessionForUser(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
session := adapter.Engine.Prepare()
if offset != -1 && limit != -1 {
session.Limit(limit, offset)
}
if owner != "" {
if offset == -1 {
session = session.And("owner=?", owner)
} else {
session = session.And("a.owner=?", owner)
}
}
if field != "" && value != "" {
if filterField(field) {
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
}
}
if sortField == "" || sortOrder == "" {
sortField = "created_time"
}
tableName := "user"
if offset == -1 {
if sortOrder == "ascend" {
session = session.Asc(util.SnakeString(sortField))
} else {
session = session.Desc(util.SnakeString(sortField))
}
} else {
if sortOrder == "ascend" {
session = session.Alias("a").
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
Select("b.*").
Asc("a." + util.SnakeString(sortField))
} else {
session = session.Alias("a").
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
Select("b.*").
Desc("a." + util.SnakeString(sortField))
}
}
return session
}

View File

@@ -22,20 +22,13 @@ import (
type Migrator_1_314_0_PR_1841 struct{}
func (*Migrator_1_314_0_PR_1841) IsMigrationNeeded() bool {
users := []*User{}
err := adapter.Engine.Table("user").Find(&users)
count, err := adapter.Engine.Where("password_type=?", "").Count(&User{})
if err != nil {
// table doesn't exist
return false
}
for _, u := range users {
if u.PasswordType != "" {
return false
}
}
return true
return count > 100
}
func (*Migrator_1_314_0_PR_1841) DoMigration() *migrate.Migration {

View File

@@ -210,6 +210,11 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
ReturnUrl: product.ReturnUrl,
State: "Created",
}
if provider.Type == "Dummy" {
payment.State = "Paid"
}
affected, err := AddPayment(&payment)
if err != nil {
return "", err

View File

@@ -29,15 +29,14 @@ type Subscription struct {
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
DisplayName string `xorm:"varchar(100)" json:"displayName"`
Duration int `json:"duration"`
Description string `xorm:"varchar(100)" json:"description"`
Plan string `xorm:"varchar(100)" json:"plan"`
StartDate time.Time `json:"startDate"`
EndDate time.Time `json:"endDate"`
StartDate time.Time `json:"startDate"`
EndDate time.Time `json:"endDate"`
Duration int `json:"duration"`
Description string `xorm:"varchar(100)" json:"description"`
User string `xorm:"mediumtext" json:"user"`
Plan string `xorm:"varchar(100)" json:"plan"`
IsEnabled bool `json:"isEnabled"`
Submitter string `xorm:"varchar(100)" json:"submitter"`

View File

@@ -34,7 +34,7 @@ const (
type User struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
CreatedTime string `xorm:"varchar(100) index" json:"createdTime"`
UpdatedTime string `xorm:"varchar(100)" json:"updatedTime"`
Id string `xorm:"varchar(100) index" json:"id"`
@@ -173,15 +173,16 @@ type User struct {
}
type Userinfo struct {
Sub string `json:"sub"`
Iss string `json:"iss"`
Aud string `json:"aud"`
Name string `json:"preferred_username,omitempty"`
DisplayName string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
Avatar string `json:"picture,omitempty"`
Address string `json:"address,omitempty"`
Phone string `json:"phone,omitempty"`
Sub string `json:"sub"`
Iss string `json:"iss"`
Aud string `json:"aud"`
Organization string `json:"organization,omitempty"`
Name string `json:"preferred_username,omitempty"`
DisplayName string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
Avatar string `json:"picture,omitempty"`
Address string `json:"address,omitempty"`
Phone string `json:"phone,omitempty"`
}
type ManagedAccount struct {
@@ -208,7 +209,7 @@ func GetGlobalUsers() ([]*User, error) {
func GetPaginationGlobalUsers(offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) {
users := []*User{}
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
session := GetSessionForUser("", offset, limit, field, value, sortField, sortOrder)
err := session.Find(&users)
if err != nil {
return nil, err
@@ -258,7 +259,7 @@ func GetSortedUsers(owner string, sorter string, limit int) ([]*User, error) {
func GetPaginationUsers(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) {
users := []*User{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
session := GetSessionForUser(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&users)
if err != nil {
return nil, err
@@ -554,6 +555,10 @@ func AddUser(user *User) (bool, error) {
return false, nil
}
if user.PasswordType == "" && organization.PasswordType != "" {
user.PasswordType = organization.PasswordType
}
user.UpdateUserPassword(organization)
err = user.UpdateUserHash()
@@ -675,6 +680,7 @@ func GetUserInfo(user *User, scope string, aud string, host string) *Userinfo {
Aud: aud,
}
if strings.Contains(scope, "profile") {
resp.Organization = user.Owner
resp.Name = user.Name
resp.DisplayName = user.DisplayName
resp.Avatar = user.Avatar

44
pp/dummy.go Normal file
View File

@@ -0,0 +1,44 @@
// Copyright 2023 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.
package pp
import (
"fmt"
"net/http"
)
type DummyPaymentProvider struct{}
func NewDummyPaymentProvider() (*DummyPaymentProvider, error) {
pp := &DummyPaymentProvider{}
return pp, nil
}
func (pp *DummyPaymentProvider) Pay(providerName string, productName string, payerName string, paymentName string, productDisplayName string, price float64, returnUrl string, notifyUrl string) (string, error) {
payUrl := fmt.Sprintf("/payments/%s/result", paymentName)
return payUrl, nil
}
func (pp *DummyPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string) (string, string, float64, string, string, error) {
return "", "", 0, "", "", nil
}
func (pp *DummyPaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
return "", nil
}
func (pp *DummyPaymentProvider) GetResponseError(err error) string {
return ""
}

98
pp/paypal.go Normal file
View File

@@ -0,0 +1,98 @@
// Copyright 2023 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.
package pp
import (
"context"
"fmt"
"net/http"
"github.com/plutov/paypal/v4"
)
type PaypalPaymentProvider struct {
Client *paypal.Client
}
func NewPaypalPaymentProvider(clientID string, secret string) (*PaypalPaymentProvider, error) {
pp := &PaypalPaymentProvider{}
client, err := paypal.NewClient(clientID, secret, paypal.APIBaseSandBox)
if err != nil {
return nil, err
}
pp.Client = client
return pp, nil
}
func (pp *PaypalPaymentProvider) Pay(providerName string, productName string, payerName string, paymentName string, productDisplayName string, price float64, returnUrl string, notifyUrl string) (string, error) {
// pp.Client.SetLog(os.Stdout) // Set log to terminal stdout
receiverEmail := "sb-tmsqa26118644@business.example.com"
amount := paypal.AmountPayout{
Value: fmt.Sprintf("%.2f", price),
Currency: "USD",
}
description := fmt.Sprintf("%s-%s", providerName, productName)
payout := paypal.Payout{
SenderBatchHeader: &paypal.SenderBatchHeader{
EmailSubject: description,
},
Items: []paypal.PayoutItem{
{
RecipientType: "EMAIL",
Receiver: receiverEmail,
Amount: &amount,
Note: description,
SenderItemID: description,
},
},
}
_, err := pp.Client.GetAccessToken(context.Background())
if err != nil {
return "", err
}
payoutResponse, err := pp.Client.CreatePayout(context.Background(), payout)
if err != nil {
return "", err
}
payUrl := payoutResponse.Links[0].Href
return payUrl, nil
}
func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string) (string, string, float64, string, string, error) {
// The PayPal SDK does not directly support IPN verification.
// So, you need to implement this part according to PayPal's IPN guide.
return "", "", 0, "", "", nil
}
func (pp *PaypalPaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
return "", nil
}
func (pp *PaypalPaymentProvider) GetResponseError(err error) string {
if err == nil {
return "success"
} else {
return "fail"
}
}

View File

@@ -24,20 +24,32 @@ type PaymentProvider interface {
}
func GetPaymentProvider(typ string, clientId string, clientSecret string, host string, appCertificate string, appPrivateKey string, authorityPublicKey string, authorityRootPublicKey string, clientId2 string) (PaymentProvider, error) {
if typ == "Alipay" {
newAlipayPaymentProvider, err := NewAlipayPaymentProvider(clientId, appCertificate, appPrivateKey, authorityPublicKey, authorityRootPublicKey)
if typ == "Dummy" {
pp, err := NewDummyPaymentProvider()
if err != nil {
return nil, err
}
return newAlipayPaymentProvider, nil
return pp, nil
} else if typ == "Alipay" {
pp, err := NewAlipayPaymentProvider(clientId, appCertificate, appPrivateKey, authorityPublicKey, authorityRootPublicKey)
if err != nil {
return nil, err
}
return pp, nil
} else if typ == "GC" {
return NewGcPaymentProvider(clientId, clientSecret, host), nil
} else if typ == "WeChat Pay" {
newWechatPaymentProvider, err := NewWechatPaymentProvider(clientId, clientSecret, clientId2, appCertificate, appPrivateKey)
pp, err := NewWechatPaymentProvider(clientId, clientSecret, clientId2, appCertificate, appPrivateKey)
if err != nil {
return nil, err
}
return newWechatPaymentProvider, nil
return pp, nil
} else if typ == "PayPal" {
pp, err := NewPaypalPaymentProvider(clientId, clientSecret)
if err != nil {
return nil, err
}
return pp, nil
}
return nil, nil

View File

@@ -30,8 +30,8 @@ type WechatPayNotifyResponse struct {
}
type WechatPaymentProvider struct {
ClientV3 *wechat.ClientV3
appId string
Client *wechat.ClientV3
appId string
}
func NewWechatPaymentProvider(mchId string, apiV3Key string, appId string, mchCertSerialNumber string, privateKey string) (*WechatPaymentProvider, error) {
@@ -51,7 +51,7 @@ func NewWechatPaymentProvider(mchId string, apiV3Key string, appId string, mchCe
return nil, err
}
pp.ClientV3 = clientV3.SetPlatformCert([]byte(platformCert), serialNo)
pp.Client = clientV3.SetPlatformCert([]byte(platformCert), serialNo)
return pp, nil
}
@@ -71,7 +71,7 @@ func (pp *WechatPaymentProvider) Pay(providerName string, productName string, pa
bm.Set("currency", "CNY")
})
wxRsp, err := pp.ClientV3.V3TransactionNative(context.Background(), bm)
wxRsp, err := pp.Client.V3TransactionNative(context.Background(), bm)
if err != nil {
return "", err
}
@@ -89,13 +89,13 @@ func (pp *WechatPaymentProvider) Notify(request *http.Request, body []byte, auth
panic(err)
}
cert := pp.ClientV3.WxPublicKey()
cert := pp.Client.WxPublicKey()
err = notifyReq.VerifySignByPK(cert)
if err != nil {
return "", "", 0, "", "", err
}
apiKey := string(pp.ClientV3.ApiV3Key)
apiKey := string(pp.Client.ApiV3Key)
result, err := notifyReq.DecryptCipherText(apiKey)
if err != nil {
return "", "", 0, "", "", err

View File

@@ -585,11 +585,11 @@ class App extends Component {
<Route exact path="/messages" render={(props) => this.renderLoginIfNotLoggedIn(<MessageListPage account={this.state.account} {...props} />)} />
<Route exact path="/messages/:messageName" render={(props) => this.renderLoginIfNotLoggedIn(<MessageEditPage account={this.state.account} {...props} />)} />
<Route exact path="/plans" render={(props) => this.renderLoginIfNotLoggedIn(<PlanListPage account={this.state.account} {...props} />)} />
<Route exact path="/plan/:organizationName/:planName" render={(props) => this.renderLoginIfNotLoggedIn(<PlanEditPage account={this.state.account} {...props} />)} />
<Route exact path="/plans/:organizationName/:planName" render={(props) => this.renderLoginIfNotLoggedIn(<PlanEditPage account={this.state.account} {...props} />)} />
<Route exact path="/pricings" render={(props) => this.renderLoginIfNotLoggedIn(<PricingListPage account={this.state.account} {...props} />)} />
<Route exact path="/pricing/:organizationName/:pricingName" render={(props) => this.renderLoginIfNotLoggedIn(<PricingEditPage account={this.state.account} {...props} />)} />
<Route exact path="/pricings/:organizationName/:pricingName" render={(props) => this.renderLoginIfNotLoggedIn(<PricingEditPage account={this.state.account} {...props} />)} />
<Route exact path="/subscriptions" render={(props) => this.renderLoginIfNotLoggedIn(<SubscriptionListPage account={this.state.account} {...props} />)} />
<Route exact path="/subscription/:organizationName/:subscriptionName" render={(props) => this.renderLoginIfNotLoggedIn(<SubscriptionEditPage account={this.state.account} {...props} />)} />
<Route exact path="/subscriptions/:organizationName/:subscriptionName" render={(props) => this.renderLoginIfNotLoggedIn(<SubscriptionEditPage account={this.state.account} {...props} />)} />
<Route exact path="/products" render={(props) => this.renderLoginIfNotLoggedIn(<ProductListPage account={this.state.account} {...props} />)} />
<Route exact path="/products/:productName" render={(props) => this.renderLoginIfNotLoggedIn(<ProductEditPage account={this.state.account} {...props} />)} />
<Route exact path="/products/:productName/buy" render={(props) => this.renderLoginIfNotLoggedIn(<ProductBuyPage account={this.state.account} {...props} />)} />

View File

@@ -155,11 +155,16 @@ class ApplicationEditPage extends React.Component {
}
getProviders() {
ProviderBackend.getProviders(this.state.owner).then((res => {
this.setState({
providers: res,
ProviderBackend.getProviders(this.state.owner)
.then((res) => {
if (res.status === "ok") {
this.setState({
providers: res.data,
});
} else {
Setting.showMessage("error", res.msg);
}
});
}));
}
getSamlMetadata() {
@@ -564,7 +569,7 @@ class ApplicationEditPage extends React.Component {
{Setting.getLabel(i18next.t("application:Grant types"), i18next.t("application:Grant types - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} mode="tags" style={{width: "100%"}}
<Select virtual={false} mode="multiple" style={{width: "100%"}}
value={this.state.application.grantTypes}
onChange={(value => {
this.updateApplicationField("grantTypes", value);

View File

@@ -175,7 +175,7 @@ class ChatEditPage extends React.Component {
{Setting.getLabel(i18next.t("general:Users"), i18next.t("chat:Users - Tooltip"))} :
</Col>
<Col span={22} >
<Select mode="tags" style={{width: "100%"}} value={this.state.chat.users}
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.chat.users}
onChange={(value => {this.updateChatField("users", value);})}
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))}
/>

View File

@@ -82,6 +82,7 @@ class ChatListPage extends BaseListPage {
dataIndex: "organization",
key: "organization",
width: "150px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("organization"),
render: (text, record, index) => {
@@ -165,7 +166,6 @@ class ChatListPage extends BaseListPage {
dataIndex: "user1",
key: "user1",
width: "120px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("user1"),
render: (text, record, index) => {
@@ -181,7 +181,6 @@ class ChatListPage extends BaseListPage {
dataIndex: "user2",
key: "user2",
width: "120px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("user2"),
render: (text, record, index) => {

View File

@@ -102,7 +102,7 @@ class EntryPage extends React.Component {
<Route exact path="/result/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ResultPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
<Route exact path="/cas/:owner/:casApplicationName/login" render={(props) => {return (<LoginPage {...this.props} application={this.state.application} type={"cas"} mode={"signin"} onUpdateApplication={onUpdateApplication} {...props} />);}} />
<Route exact path="/select-plan/:pricingName" render={(props) => this.renderHomeIfLoggedIn(<PricingPage {...this.props} pricing={this.state.pricing} onUpdatePricing={onUpdatePricing} {...props} />)} />
<Route exact path="/select-plan/:owner/:pricingName" render={(props) => this.renderHomeIfLoggedIn(<PricingPage {...this.props} pricing={this.state.pricing} onUpdatePricing={onUpdatePricing} {...props} />)} />
</Switch>
</div>
);

View File

@@ -78,6 +78,7 @@ class MessageListPage extends BaseListPage {
dataIndex: "organization",
key: "organization",
width: "150px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("organization"),
render: (text, record, index) => {
@@ -119,7 +120,6 @@ class MessageListPage extends BaseListPage {
dataIndex: "chat",
key: "chat",
width: "120px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("chat"),
render: (text, record, index) => {
@@ -135,7 +135,6 @@ class MessageListPage extends BaseListPage {
dataIndex: "author",
key: "author",
width: "120px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("author"),
render: (text, record, index) => {

View File

@@ -205,7 +205,7 @@ class OrganizationEditPage extends React.Component {
{Setting.getLabel(i18next.t("general:Languages"), i18next.t("general:Languages - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} mode="tags" style={{width: "100%"}}
<Select virtual={false} mode="multiple" style={{width: "100%"}}
options={Setting.Countries.map((item) => {
return Setting.getOption(item.label, item.key);
})}

View File

@@ -217,7 +217,7 @@ class PermissionEditPage extends React.Component {
{Setting.getLabel(i18next.t("role:Sub users"), i18next.t("role:Sub users - Tooltip"))} :
</Col>
<Col span={22} >
<Select mode="tags" style={{width: "100%"}} value={this.state.permission.users}
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.permission.users}
onChange={(value => {this.updatePermissionField("users", value);})}
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))}
/>
@@ -228,7 +228,7 @@ class PermissionEditPage extends React.Component {
{Setting.getLabel(i18next.t("role:Sub roles"), i18next.t("role:Sub roles - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} disabled={!this.hasRoleDefinition(this.state.model)} mode="tags" style={{width: "100%"}} value={this.state.permission.roles}
<Select disabled={!this.hasRoleDefinition(this.state.model)} virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.permission.roles}
onChange={(value => {this.updatePermissionField("roles", value);})}
options={this.state.roles.filter(roles => (roles.owner !== this.state.roles.owner || roles.name !== this.state.roles.name)).map((permission) => Setting.getOption(`${permission.owner}/${permission.name}`, `${permission.owner}/${permission.name}`))
} />
@@ -267,7 +267,7 @@ class PermissionEditPage extends React.Component {
{Setting.getLabel(i18next.t("general:Resources"), i18next.t("permission:Resources - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} mode="tags" style={{width: "100%"}} value={this.state.permission.resources}
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.permission.resources}
onChange={(value => {this.updatePermissionField("resources", value);})}
options={this.state.resources.map((resource) => Setting.getOption(`${resource.name}`, `${resource.name}`))
} />
@@ -278,7 +278,7 @@ class PermissionEditPage extends React.Component {
{Setting.getLabel(i18next.t("permission:Actions"), i18next.t("permission:Actions - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} mode="tags" style={{width: "100%"}} value={this.state.permission.actions} onChange={(value => {
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.permission.actions} onChange={(value => {
this.updatePermissionField("actions", value);
})}
options={[

View File

@@ -146,7 +146,7 @@ class PlanEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("role:Sub roles"), i18next.t("plan:Sub roles - Tooltip"))} :
{Setting.getLabel(i18next.t("general:Role"), i18next.t("general:Role - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.plan.role} onChange={(value => {this.updatePlanField("role", value);})}
@@ -166,7 +166,7 @@ class PlanEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("plan:PricePerMonth"), i18next.t("plan:PricePerMonth - Tooltip"))} :
{Setting.getLabel(i18next.t("plan:Price per month"), i18next.t("plan:Price per month - Tooltip"))} :
</Col>
<Col span={22} >
<InputNumber value={this.state.plan.pricePerMonth} onChange={value => {
@@ -176,7 +176,7 @@ class PlanEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("plan:PricePerYear"), i18next.t("plan:PricePerYear - Tooltip"))} :
{Setting.getLabel(i18next.t("plan:Price per year"), i18next.t("plan:Price per year - Tooltip"))} :
</Col>
<Col span={22} >
<InputNumber value={this.state.plan.pricePerYear} onChange={value => {
@@ -228,7 +228,7 @@ class PlanEditPage extends React.Component {
if (willExist) {
this.props.history.push("/plans");
} else {
this.props.history.push(`/plan/${this.state.plan.owner}/${this.state.plan.name}`);
this.props.history.push(`/plans/${this.state.plan.owner}/${this.state.plan.name}`);
}
} else {
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);

View File

@@ -43,7 +43,7 @@ class PlanListPage extends BaseListPage {
PlanBackend.addPlan(newPlan)
.then((res) => {
if (res.status === "ok") {
this.props.history.push({pathname: `/plan/${newPlan.owner}/${newPlan.name}`, mode: "add"});
this.props.history.push({pathname: `/plans/${newPlan.owner}/${newPlan.name}`, mode: "add"});
Setting.showMessage("success", i18next.t("general:Successfully added"));
} else {
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
@@ -84,7 +84,7 @@ class PlanListPage extends BaseListPage {
...this.getColumnSearchProps("name"),
render: (text, record, index) => {
return (
<Link to={`/plans/${text}`}>
<Link to={`/plans/${record.owner}/${record.name}`}>
{text}
</Link>
);
@@ -138,11 +138,18 @@ class PlanListPage extends BaseListPage {
...this.getColumnSearchProps("pricePerYear"),
},
{
title: i18next.t("plan:Sub role"),
title: i18next.t("general:Role"),
dataIndex: "role",
key: "role",
width: "140px",
...this.getColumnSearchProps("role"),
render: (text, record, index) => {
return (
<Link to={`/roles/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Is enabled"),
@@ -165,7 +172,7 @@ class PlanListPage extends BaseListPage {
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/plan/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/plans/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
<PopconfirmModal
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
onConfirm={() => this.deletePlan(index)}

View File

@@ -178,10 +178,10 @@ class PricingEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("pricing:Sub plans"), i18next.t("pricing:Sub plans - Tooltip"))} :
{Setting.getLabel(i18next.t("general:Plans"), i18next.t("general:Plans - Tooltip"))} :
</Col>
<Col span={22} >
<Select mode="tags" style={{width: "100%"}} value={this.state.pricing.plans}
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.pricing.plans}
onChange={(value => {
this.updatePricingField("plans", value);
})}
@@ -194,7 +194,7 @@ class PricingEditPage extends React.Component {
{Setting.getLabel(i18next.t("pricing:Has trial"), i18next.t("pricing:Has trial - Tooltip"))} :
</Col>
<Col span={1} >
<Switch disabled={true} checked={this.state.pricing.hasTrial} onChange={checked => {
<Switch checked={this.state.pricing.hasTrial} onChange={checked => {
this.updatePricingField("hasTrial", checked);
}} />
</Col>
@@ -244,7 +244,7 @@ class PricingEditPage extends React.Component {
if (willExist) {
this.props.history.push("/pricings");
} else {
this.props.history.push(`/pricing/${this.state.pricing.owner}/${this.state.pricing.name}`);
this.props.history.push(`/pricings/${this.state.pricing.owner}/${this.state.pricing.name}`);
}
} else {
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
@@ -286,7 +286,7 @@ class PricingEditPage extends React.Component {
}
renderPreview() {
const pricingUrl = `/select-plan/${this.state.pricing.name}`;
const pricingUrl = `/select-plan/${this.state.pricing.owner}/${this.state.pricing.name}`;
return (
<React.Fragment>
<Col>

View File

@@ -33,7 +33,7 @@ class PricingListPage extends BaseListPage {
createdTime: moment().format(),
plans: [],
displayName: `New Pricing - ${randomName}`,
hasTrial: true,
hasTrial: false,
isEnabled: true,
trialDuration: 14,
};
@@ -44,7 +44,7 @@ class PricingListPage extends BaseListPage {
PricingBackend.addPricing(newPricing)
.then((res) => {
if (res.status === "ok") {
this.props.history.push({pathname: `/pricing/${newPricing.owner}/${newPricing.name}`, mode: "add"});
this.props.history.push({pathname: `/pricings/${newPricing.owner}/${newPricing.name}`, mode: "add"});
Setting.showMessage("success", i18next.t("general:Successfully added"));
} else {
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
@@ -85,7 +85,7 @@ class PricingListPage extends BaseListPage {
...this.getColumnSearchProps("name"),
render: (text, record, index) => {
return (
<Link to={`/pricing/${record.owner}/${text}`}>
<Link to={`/pricings/${record.owner}/${text}`}>
{text}
</Link>
);
@@ -120,7 +120,7 @@ class PricingListPage extends BaseListPage {
title: i18next.t("general:Display name"),
dataIndex: "displayName",
key: "displayName",
width: "170px",
// width: "170px",
sorter: true,
...this.getColumnSearchProps("displayName"),
},
@@ -146,7 +146,7 @@ class PricingListPage extends BaseListPage {
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/pricing/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/pricings/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
<PopconfirmModal
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
onConfirm={() => this.deletePricing(index)}

View File

@@ -151,7 +151,9 @@ class ProductBuyPage extends React.Component {
getPayButton(provider) {
let text = provider.type;
if (provider.type === "Alipay") {
if (provider.type === "Dummy") {
text = i18next.t("product:Dummy");
} else if (provider.type === "Alipay") {
text = i18next.t("product:Alipay");
} else if (provider.type === "WeChat Pay") {
text = i18next.t("product:WeChat Pay");

View File

@@ -54,9 +54,13 @@ class ProductEditPage extends React.Component {
getPaymentProviders() {
ProviderBackend.getProviders(this.props.account.owner)
.then((res) => {
this.setState({
providers: res.filter(provider => provider.category === "Payment"),
});
if (res.status === "ok") {
this.setState({
providers: res.data.filter(provider => provider.category === "Payment"),
});
} else {
Setting.showMessage("error", res.msg);
}
});
}
@@ -228,7 +232,7 @@ class ProductEditPage extends React.Component {
{Setting.getLabel(i18next.t("product:Payment providers"), i18next.t("product:Payment providers - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} mode="tags" style={{width: "100%"}} value={this.state.product.providers} onChange={(value => {this.updateProductField("providers", value);})}>
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.product.providers} onChange={(value => {this.updateProductField("providers", value);})}>
{
this.state.providers.map((provider, index) => <Option key={index} value={provider.name}>{provider.name}</Option>)
}

View File

@@ -49,10 +49,14 @@ class ProviderEditPage extends React.Component {
getProvider() {
ProviderBackend.getProvider(this.state.owner, this.state.providerName)
.then((provider) => {
this.setState({
provider: provider,
});
.then((res) => {
if (res.status === "ok") {
this.setState({
provider: res.data,
});
} else {
Setting.showMessage("error", res.msg);
}
});
}
@@ -305,7 +309,7 @@ class ProviderEditPage extends React.Component {
} else if (value === "SAML") {
this.updateProviderField("type", "Aliyun IDaaS");
} else if (value === "Payment") {
this.updateProviderField("type", "Alipay");
this.updateProviderField("type", "PayPal");
} else if (value === "Captcha") {
this.updateProviderField("type", "Default");
} else if (value === "AI") {
@@ -853,7 +857,7 @@ class ProviderEditPage extends React.Component {
) : null
}
{
this.state.provider.type === "WeChat Pay" ? (
(this.state.provider.type === "Alipay" || this.state.provider.type === "WeChat Pay") ? (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Cert"), i18next.t("general:Cert - Tooltip"))} :

View File

@@ -141,7 +141,7 @@ class RoleEditPage extends React.Component {
{Setting.getLabel(i18next.t("role:Sub users"), i18next.t("role:Sub users - Tooltip"))} :
</Col>
<Col span={22} >
<Select mode="tags" style={{width: "100%"}} value={this.state.role.users}
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.role.users}
onChange={(value => {this.updateRoleField("users", value);})}
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))}
/>
@@ -152,7 +152,7 @@ class RoleEditPage extends React.Component {
{Setting.getLabel(i18next.t("role:Sub roles"), i18next.t("role:Sub roles - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} mode="tags" style={{width: "100%"}} value={this.state.role.roles} onChange={(value => {this.updateRoleField("roles", value);})}
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.role.roles} onChange={(value => {this.updateRoleField("roles", value);})}
options={this.state.roles.filter(role => (role.owner !== this.state.role.owner || role.name !== this.state.role.name)).map((role) => Setting.getOption(`${role.owner}/${role.name}`, `${role.owner}/${role.name}`))
} />
</Col>

View File

@@ -163,6 +163,10 @@ export const OtherProviderInfo = {
},
},
Payment: {
"Dummy": {
logo: `${StaticBaseUrl}/img/payment_paypal.png`,
url: "",
},
"Alipay": {
logo: `${StaticBaseUrl}/img/payment_alipay.png`,
url: "https://www.alipay.com/",
@@ -679,7 +683,7 @@ export function getLanguageText(text) {
}
export function getLanguage() {
return i18next.language ?? Conf.DefaultLanguage;
return (i18next.language !== undefined && i18next.language !== null && i18next.language !== "" && i18next.language !== "null") ? i18next.language : Conf.DefaultLanguage;
}
export function setLanguage(language) {
@@ -848,6 +852,7 @@ export function getProviderTypeOptions(category) {
]);
} else if (category === "Payment") {
return ([
{id: "Dummy", name: "Dummy"},
{id: "Alipay", name: "Alipay"},
{id: "WeChat Pay", name: "WeChat Pay"},
{id: "PayPal", name: "PayPal"},

View File

@@ -156,7 +156,7 @@ class SubscriptionEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("subscription:Start Date"), i18next.t("subscription:Start Date - Tooltip"))}
{Setting.getLabel(i18next.t("subscription:Start date"), i18next.t("subscription:Start date - Tooltip"))}
</Col>
<Col span={22} >
<DatePicker value={dayjs(this.state.subscription.startDate)} onChange={value => {
@@ -166,7 +166,7 @@ class SubscriptionEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("subscription:End Date"), i18next.t("subscription:End Date - Tooltip"))}
{Setting.getLabel(i18next.t("subscription:End date"), i18next.t("subscription:End date - Tooltip"))}
</Col>
<Col span={22} >
<DatePicker value={dayjs(this.state.subscription.endDate)} onChange={value => {
@@ -176,7 +176,7 @@ class SubscriptionEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("subscription:Sub users"), i18next.t("subscription:Sub users - Tooltip"))} :
{Setting.getLabel(i18next.t("general:User"), i18next.t("general:User - Tooltip"))} :
</Col>
<Col span={22} >
<Select style={{width: "100%"}} value={this.state.subscription.user}
@@ -188,7 +188,7 @@ class SubscriptionEditPage extends React.Component {
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("subscription:Sub plan"), i18next.t("subscription:Sub plan - Tooltip"))} :
{Setting.getLabel(i18next.t("general:Plan"), i18next.t("general:Plan - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.subscription.plan} onChange={(value => {this.updateSubscriptionField("plan", value);})}
@@ -218,7 +218,7 @@ class SubscriptionEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Submitter"), i18next.t("general:Submitter - Tooltip"))} :
{Setting.getLabel(i18next.t("permission:Submitter"), i18next.t("permission:Submitter - Tooltip"))} :
</Col>
<Col span={22} >
<Input disabled={true} value={this.state.subscription.submitter} onChange={e => {
@@ -228,7 +228,7 @@ class SubscriptionEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Approver"), i18next.t("general:Approver - Tooltip"))} :
{Setting.getLabel(i18next.t("permission:Approver"), i18next.t("permission:Approver - Tooltip"))} :
</Col>
<Col span={22} >
<Input disabled={true} value={this.state.subscription.approver} onChange={e => {
@@ -238,7 +238,7 @@ class SubscriptionEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Approve time"), i18next.t("general:Approve time - Tooltip"))} :
{Setting.getLabel(i18next.t("permission:Approve time"), i18next.t("permission:Approve time - Tooltip"))} :
</Col>
<Col span={22} >
<Input disabled={true} value={Setting.getFormattedDate(this.state.subscription.approveTime)} onChange={e => {
@@ -265,8 +265,8 @@ class SubscriptionEditPage extends React.Component {
this.updateSubscriptionField("state", value);
})}
options={[
{value: "Approved", name: i18next.t("subscription:Approved")},
{value: "Pending", name: i18next.t("subscription:Pending")},
{value: "Approved", name: i18next.t("permission:Approved")},
{value: "Pending", name: i18next.t("permission:Pending")},
].map((item) => Setting.getOption(item.name, item.value))}
/>
</Col>
@@ -288,7 +288,7 @@ class SubscriptionEditPage extends React.Component {
if (willExist) {
this.props.history.push("/subscriptions");
} else {
this.props.history.push(`/subscription/${this.state.subscription.owner}/${this.state.subscription.name}`);
this.props.history.push(`/subscriptions/${this.state.subscription.owner}/${this.state.subscription.name}`);
}
} else {
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);

View File

@@ -32,16 +32,18 @@ class SubscriptionListPage extends BaseListPage {
owner: owner,
name: `subscription_${randomName}`,
createdTime: moment().format(),
displayName: `New Subscription - ${randomName}`,
startDate: moment().format(),
endDate: moment().add(defaultDuration, "d").format(),
displayName: `New Subscription - ${randomName}`,
tag: "",
users: [],
expireInDays: defaultDuration,
duration: defaultDuration,
description: "",
user: "",
plan: "",
isEnabled: true,
submitter: this.props.account.name,
approver: "",
approveTime: "",
state: "Pending",
approver: this.props.account.name,
approveTime: moment().format(),
state: "Approved",
};
}
@@ -50,7 +52,7 @@ class SubscriptionListPage extends BaseListPage {
SubscriptionBackend.addSubscription(newSubscription)
.then((res) => {
if (res.status === "ok") {
this.props.history.push({pathname: `/subscription/${newSubscription.owner}/${newSubscription.name}`, mode: "add"});
this.props.history.push({pathname: `/subscriptions/${newSubscription.owner}/${newSubscription.name}`, mode: "add"});
Setting.showMessage("success", i18next.t("general:Successfully added"));
} else {
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
@@ -91,7 +93,7 @@ class SubscriptionListPage extends BaseListPage {
...this.getColumnSearchProps("name"),
render: (text, record, index) => {
return (
<Link to={`/subscriptions/${text}`}>
<Link to={`/subscriptions/${record.owner}/${record.name}`}>
{text}
</Link>
);
@@ -138,18 +140,32 @@ class SubscriptionListPage extends BaseListPage {
...this.getColumnSearchProps("duration"),
},
{
title: i18next.t("subscription:Sub plane"),
title: i18next.t("general:Plan"),
dataIndex: "plan",
key: "plan",
width: "140px",
...this.getColumnSearchProps("plan"),
render: (text, record, index) => {
return (
<Link to={`/plans/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("subscription:Sub user"),
title: i18next.t("general:User"),
dataIndex: "user",
key: "user",
width: "140px",
...this.getColumnSearchProps("user"),
render: (text, record, index) => {
return (
<Link to={`/users/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:State"),
@@ -158,6 +174,16 @@ class SubscriptionListPage extends BaseListPage {
width: "120px",
sorter: true,
...this.getColumnSearchProps("state"),
render: (text, record, index) => {
switch (text) {
case "Approved":
return Setting.getTag("success", i18next.t("permission:Approved"));
case "Pending":
return Setting.getTag("error", i18next.t("permission:Pending"));
default:
return null;
}
},
},
{
title: i18next.t("general:Action"),
@@ -168,7 +194,7 @@ class SubscriptionListPage extends BaseListPage {
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/subscription/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/subscriptions/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
<PopconfirmModal
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
onConfirm={() => this.deleteSubscription(index)}

View File

@@ -252,7 +252,7 @@ class WebhookEditPage extends React.Component {
{Setting.getLabel(i18next.t("webhook:Events"), i18next.t("webhook:Events - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} mode="tags" style={{width: "100%"}}
<Select virtual={false} mode="multiple" style={{width: "100%"}}
value={this.state.webhook.events}
onChange={value => {
this.updateWebhookField("events", value);

View File

@@ -29,9 +29,6 @@ export const CaptchaPreview = (props) => {
provider.providerUrl = providerUrl;
if (clientSecret !== "***") {
provider.clientSecret = clientSecret;
// ProviderBackend.updateProvider(owner, providerName, provider).then(() => {
// setOpen(true);
// });
setVisible(true);
} else {
setVisible(true);

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "Anwendungen",
"Applications that require authentication": "Anwendungen, die eine Authentifizierung erfordern",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "Avatar",
"Avatar - Tooltip": "Öffentliches Avatarbild für den Benutzer",
"Back": "Back",
@@ -265,7 +261,10 @@
"Phone": "Telefon",
"Phone - Tooltip": "Telefonnummer",
"Phone or email": "Phone or email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Pläne",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "Vorschau",
"Preview - Tooltip": "Vorschau der konfigurierten Effekte",
"Pricings": "Preise",
@@ -278,6 +277,8 @@
"Records": "Datensätze",
"Request URI": "Anforderungs-URI",
"Resources": "Ressourcen",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "Rollen",
"Roles - Tooltip": "Rollen, denen der Benutzer angehört",
"Save": "Speichern",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "Es tut uns leid, aber Sie haben keine Berechtigung, auf diese Seite zuzugreifen, oder Sie sind nicht angemeldet.",
"State": "Bundesland / Staat",
"State - Tooltip": "Bundesland",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "Abonnements",
"Successfully added": "Erfolgreich hinzugefügt",
"Successfully deleted": "Erfolgreich gelöscht",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "pro Monat",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "Preis pro Monat",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "Preis pro Jahr",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "Rolle im aktuellen Plan enthalten"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "pro Monat"
},
"pricing": {
"Copy pricing page URL": "Preisseite URL kopieren",
@@ -547,8 +542,6 @@
"Has trial": "Testphase verfügbar",
"Has trial - Tooltip": "Verfügbarkeit der Testphase nach Auswahl eines Plans",
"New Pricing": "New Pricing",
"Sub plans": "Zusatzpläne",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "Testphase Dauer",
"Trial duration - Tooltip": "Dauer der Testphase",
"days trial available!": "Tage Testphase verfügbar!",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "Detail",
"Detail - Tooltip": "Detail des Produkts",
"Dummy": "Dummy",
"Edit Product": "Produkt bearbeiten",
"I have completed the payment": "Ich habe die Zahlung abgeschlossen",
"Image": "Bild",
@@ -772,22 +766,14 @@
"sign in now": "Jetzt anmelden"
},
"subscription": {
"Approved": "Approved",
"Duration": "Laufzeit",
"Duration - Tooltip": "Laufzeit des Abonnements",
"Edit Subscription": "Edit Subscription",
"End Date": "Enddatum",
"End Date - Tooltip": "Enddatum",
"End date": "Enddatum",
"End date - Tooltip": "Enddatum",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "Startdatum",
"Start Date - Tooltip": "Startdatum",
"Sub plan": "Abonnementplan",
"Sub plan - Tooltip": "Abonnementplan",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "Abonnenten",
"Sub users - Tooltip": "Abonnenten"
"Start date": "Startdatum",
"Start date - Tooltip": "Startdatum"
},
"syncer": {
"Affiliation table": "Zuordnungstabelle",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "Applications",
"Applications that require authentication": "Applications that require authentication",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "Avatar",
"Avatar - Tooltip": "Public avatar image for the user",
"Back": "Back",
@@ -265,7 +261,10 @@
"Phone": "Phone",
"Phone - Tooltip": "Phone number",
"Phone or email": "Phone or email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Plans",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "Preview",
"Preview - Tooltip": "Preview the configured effects",
"Pricings": "Pricings",
@@ -278,6 +277,8 @@
"Records": "Records",
"Request URI": "Request URI",
"Resources": "Resources",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "Roles",
"Roles - Tooltip": "Roles that the user belongs to",
"Save": "Save",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
"State": "State",
"State - Tooltip": "State",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "Subscriptions",
"Successfully added": "Successfully added",
"Successfully deleted": "Successfully deleted",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "per month",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "Price per month",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "Price per year",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "Role included in the current plane"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "per month"
},
"pricing": {
"Copy pricing page URL": "Copy pricing page URL",
@@ -547,8 +542,6 @@
"Has trial": "Has trial",
"Has trial - Tooltip": "Availability of the trial period after choosing a plan",
"New Pricing": "New Pricing",
"Sub plans": "Sub plans",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "Trial duration",
"Trial duration - Tooltip": "Trial duration period",
"days trial available!": "days trial available!",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "Detail",
"Detail - Tooltip": "Detail of product",
"Dummy": "Dummy",
"Edit Product": "Edit Product",
"I have completed the payment": "I have completed the payment",
"Image": "Image",
@@ -772,22 +766,14 @@
"sign in now": "sign in now"
},
"subscription": {
"Approved": "Approved",
"Duration": "Duration",
"Duration - Tooltip": "Subscription duration",
"Edit Subscription": "Edit Subscription",
"End Date": "End Date",
"End Date - Tooltip": "End Date",
"End date": "End date",
"End date - Tooltip": "End date",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "Start Date",
"Start Date - Tooltip": "Start Date",
"Sub plan": "Sub plan",
"Sub plan - Tooltip": "Sub plan",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "Sub users",
"Sub users - Tooltip": "Sub users"
"Start date": "Start date",
"Start date - Tooltip": "Start date"
},
"syncer": {
"Affiliation table": "Affiliation table",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "Aplicaciones",
"Applications that require authentication": "Aplicaciones que requieren autenticación",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "Avatar",
"Avatar - Tooltip": "Imagen de avatar pública para el usuario",
"Back": "Back",
@@ -265,7 +261,10 @@
"Phone": "Teléfono",
"Phone - Tooltip": "Número de teléfono",
"Phone or email": "Phone or email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Planes",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "Avance",
"Preview - Tooltip": "Vista previa de los efectos configurados",
"Pricings": "Precios",
@@ -278,6 +277,8 @@
"Records": "Registros",
"Request URI": "URI de solicitud",
"Resources": "Recursos",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "Roles",
"Roles - Tooltip": "Roles a los que pertenece el usuario",
"Save": "Guardar",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "Lo siento, no tiene permiso para acceder a esta página o su estado de inicio de sesión es inválido.",
"State": "Estado",
"State - Tooltip": "Estado",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "Suscripciones",
"Successfully added": "Éxito al agregar",
"Successfully deleted": "Éxito en la eliminación",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "por mes",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "Precio por mes",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "Precio por año",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "Rol incluido en el plan actual"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "por mes"
},
"pricing": {
"Copy pricing page URL": "Copiar URL de la página de precios",
@@ -547,8 +542,6 @@
"Has trial": "Tiene período de prueba",
"Has trial - Tooltip": "Disponibilidad del período de prueba después de elegir un plan",
"New Pricing": "New Pricing",
"Sub plans": "Planes adicionales",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "Duración del período de prueba",
"Trial duration - Tooltip": "Duración del período de prueba",
"days trial available!": "días de prueba disponibles",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "Detalle",
"Detail - Tooltip": "Detalle del producto",
"Dummy": "Dummy",
"Edit Product": "Editar Producto",
"I have completed the payment": "He completado el pago",
"Image": "Imagen",
@@ -772,22 +766,14 @@
"sign in now": "Inicie sesión ahora"
},
"subscription": {
"Approved": "Approved",
"Duration": "Duración",
"Duration - Tooltip": "Duración de la suscripción",
"Edit Subscription": "Edit Subscription",
"End Date": "Fecha de finalización",
"End Date - Tooltip": "Fecha de finalización",
"End date": "Fecha de finalización",
"End date - Tooltip": "Fecha de finalización",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "Fecha de inicio",
"Start Date - Tooltip": "Fecha de inicio",
"Sub plan": "Plan de suscripción",
"Sub plan - Tooltip": "Plan de suscripción",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "Usuarios de la suscripción",
"Sub users - Tooltip": "Usuarios de la suscripción"
"Start date": "Fecha de inicio",
"Start date - Tooltip": "Fecha de inicio"
},
"syncer": {
"Affiliation table": "Tabla de afiliación",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "Applications",
"Applications that require authentication": "Applications qui nécessitent une authentification",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "Avatar",
"Avatar - Tooltip": "Image d'avatar public pour l'utilisateur",
"Back": "Back",
@@ -265,7 +261,10 @@
"Phone": "Téléphone",
"Phone - Tooltip": "Numéro de téléphone",
"Phone or email": "Phone or email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Plans",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "Aperçu",
"Preview - Tooltip": "Prévisualisez les effets configurés",
"Pricings": "Tarifs",
@@ -278,6 +277,8 @@
"Records": "Dossiers",
"Request URI": "URI de demande",
"Resources": "Ressources",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "Rôles",
"Roles - Tooltip": "Les rôles auxquels l'utilisateur appartient",
"Save": "Enregistrer",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "Désolé, vous n'avez pas la permission d'accéder à cette page ou votre statut de connexion est invalide.",
"State": "État",
"State - Tooltip": "État",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "Abonnements",
"Successfully added": "Ajouté avec succès",
"Successfully deleted": "Supprimé avec succès",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "par mois",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "Prix par mois",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "Prix par an",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "Rôle inclus dans le plan actuel"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "par mois"
},
"pricing": {
"Copy pricing page URL": "Copier l'URL de la page tarifs",
@@ -547,8 +542,6 @@
"Has trial": "Essai gratuit disponible",
"Has trial - Tooltip": "Disponibilité de la période d'essai après avoir choisi un forfait",
"New Pricing": "New Pricing",
"Sub plans": "Forfaits supplémentaires",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "Durée de l'essai",
"Trial duration - Tooltip": "Durée de la période d'essai",
"days trial available!": "jours d'essai disponibles !",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "Détail",
"Detail - Tooltip": "Détail du produit",
"Dummy": "Dummy",
"Edit Product": "Modifier le produit",
"I have completed the payment": "J'ai effectué le paiement",
"Image": "Image",
@@ -772,22 +766,14 @@
"sign in now": "Connectez-vous maintenant"
},
"subscription": {
"Approved": "Approved",
"Duration": "Durée",
"Duration - Tooltip": "Durée de l'abonnement",
"Edit Subscription": "Edit Subscription",
"End Date": "Date de fin",
"End Date - Tooltip": "Date de fin",
"End date": "Date de fin",
"End date - Tooltip": "Date de fin",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "Date de début",
"Start Date - Tooltip": "Date de début",
"Sub plan": "Plan de l'abonnement",
"Sub plan - Tooltip": "Plan de l'abonnement",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "Utilisateurs de l'abonnement",
"Sub users - Tooltip": "Utilisateurs de l'abonnement"
"Start date": "Date de début",
"Start date - Tooltip": "Date de début"
},
"syncer": {
"Affiliation table": "Table d'affiliation",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "Aplikasi",
"Applications that require authentication": "Aplikasi yang memerlukan autentikasi",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "Avatar",
"Avatar - Tooltip": "Gambar avatar publik untuk pengguna",
"Back": "Back",
@@ -265,7 +261,10 @@
"Phone": "Telepon",
"Phone - Tooltip": "Nomor telepon",
"Phone or email": "Phone or email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Rencana",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "Tinjauan",
"Preview - Tooltip": "Mengawali pratinjau efek yang sudah dikonfigurasi",
"Pricings": "Harga",
@@ -278,6 +277,8 @@
"Records": "Catatan",
"Request URI": "Permintaan URI",
"Resources": "Sumber daya",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "Peran-peran",
"Roles - Tooltip": "Peran-peran yang diikuti oleh pengguna",
"Save": "Menyimpan",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "Maaf, Anda tidak memiliki izin untuk mengakses halaman ini atau status masuk tidak valid.",
"State": "Negara",
"State - Tooltip": "Negara",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "Langganan",
"Successfully added": "Berhasil ditambahkan",
"Successfully deleted": "Berhasil dihapus",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "per bulan",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "Harga per bulan",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "Harga per tahun",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "Peran yang termasuk dalam rencana saat ini"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "per bulan"
},
"pricing": {
"Copy pricing page URL": "Salin URL halaman harga",
@@ -547,8 +542,6 @@
"Has trial": "Mempunyai periode percobaan",
"Has trial - Tooltip": "Ketersediaan periode percobaan setelah memilih rencana",
"New Pricing": "New Pricing",
"Sub plans": "Rencana Tambahan",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "Durasi percobaan",
"Trial duration - Tooltip": "Durasi periode percobaan",
"days trial available!": "hari percobaan tersedia!",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "Rincian",
"Detail - Tooltip": "Detail produk",
"Dummy": "Dummy",
"Edit Product": "Edit Produk",
"I have completed the payment": "Saya telah menyelesaikan pembayaran",
"Image": "Gambar",
@@ -772,22 +766,14 @@
"sign in now": "Masuk sekarang"
},
"subscription": {
"Approved": "Approved",
"Duration": "Durasi",
"Duration - Tooltip": "Durasi langganan",
"Edit Subscription": "Edit Subscription",
"End Date": "Tanggal Berakhir",
"End Date - Tooltip": "Tanggal Berakhir",
"End date": "Tanggal Berakhir",
"End date - Tooltip": "Tanggal Berakhir",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "Tanggal Mulai",
"Start Date - Tooltip": "Tanggal Mulai",
"Sub plan": "Rencana Langganan",
"Sub plan - Tooltip": "Rencana Langganan",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "Pengguna Langganan",
"Sub users - Tooltip": "Pengguna Langganan"
"Start date": "Tanggal Mulai",
"Start date - Tooltip": "Tanggal Mulai"
},
"syncer": {
"Affiliation table": "Tabel afiliasi",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "アプリケーション",
"Applications that require authentication": "認証が必要なアプリケーション",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "アバター",
"Avatar - Tooltip": "ユーザーのパブリックアバター画像",
"Back": "Back",
@@ -265,7 +261,10 @@
"Phone": "電話",
"Phone - Tooltip": "電話番号",
"Phone or email": "Phone or email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "プラン",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "プレビュー",
"Preview - Tooltip": "構成されたエフェクトをプレビューする",
"Pricings": "価格設定",
@@ -278,6 +277,8 @@
"Records": "記録",
"Request URI": "リクエストURI",
"Resources": "リソース",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "役割",
"Roles - Tooltip": "ユーザーが所属する役割",
"Save": "保存",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "申し訳ありませんが、このページにアクセスする権限がありません、またはログイン状態が無効です。",
"State": "州",
"State - Tooltip": "状態",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "サブスクリプション",
"Successfully added": "正常に追加されました",
"Successfully deleted": "正常に削除されました",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "月毎",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "月額料金",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "年間料金",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "現在のプランに含まれるロール"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "月毎"
},
"pricing": {
"Copy pricing page URL": "価格ページのURLをコピー",
@@ -547,8 +542,6 @@
"Has trial": "トライアル期間あり",
"Has trial - Tooltip": "プラン選択後のトライアル期間の有無",
"New Pricing": "New Pricing",
"Sub plans": "追加プラン",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "トライアル期間の長さ",
"Trial duration - Tooltip": "トライアル期間の長さ",
"days trial available!": "日間のトライアルが利用可能です!",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "詳細",
"Detail - Tooltip": "製品の詳細",
"Dummy": "Dummy",
"Edit Product": "製品を編集",
"I have completed the payment": "私は支払いを完了しました",
"Image": "画像",
@@ -772,22 +766,14 @@
"sign in now": "今すぐサインインしてください"
},
"subscription": {
"Approved": "Approved",
"Duration": "期間",
"Duration - Tooltip": "購読の期間",
"Edit Subscription": "Edit Subscription",
"End Date": "終了日",
"End Date - Tooltip": "終了日",
"End date": "終了日",
"End date - Tooltip": "終了日",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "開始日",
"Start Date - Tooltip": "開始日",
"Sub plan": "購読プラン",
"Sub plan - Tooltip": "購読プラン",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "購読ユーザー",
"Sub users - Tooltip": "購読ユーザー"
"Start date": "開始日",
"Start date - Tooltip": "開始日"
},
"syncer": {
"Affiliation table": "所属テーブル",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "응용 프로그램",
"Applications that require authentication": "인증이 필요한 애플리케이션들",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "아바타",
"Avatar - Tooltip": "사용자를 위한 공개 아바타 이미지",
"Back": "Back",
@@ -265,7 +261,10 @@
"Phone": "전화기",
"Phone - Tooltip": "전화 번호",
"Phone or email": "Phone or email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "플랜",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "미리보기",
"Preview - Tooltip": "구성된 효과를 미리보기합니다",
"Pricings": "가격",
@@ -278,6 +277,8 @@
"Records": "기록",
"Request URI": "요청 URI",
"Resources": "자원",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "역할들",
"Roles - Tooltip": "사용자가 속한 역할들",
"Save": "저장하다",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "죄송합니다. 이 페이지에 접근할 권한이 없거나 로그인 상태가 유효하지 않습니다.",
"State": "주",
"State - Tooltip": "국가",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "구독",
"Successfully added": "성공적으로 추가되었습니다",
"Successfully deleted": "성공적으로 삭제되었습니다",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "월",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "월별 가격",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "연간 가격",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "현재 플랜에 포함된 역할"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "월"
},
"pricing": {
"Copy pricing page URL": "가격 페이지 URL 복사",
@@ -547,8 +542,6 @@
"Has trial": "무료 체험 가능",
"Has trial - Tooltip": "플랜 선택 후 체험 기간의 가용 여부",
"New Pricing": "New Pricing",
"Sub plans": "추가 플랜",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "체험 기간",
"Trial duration - Tooltip": "체험 기간의 기간",
"days trial available!": "일 무료 체험 가능!",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "세부사항",
"Detail - Tooltip": "제품의 세부사항",
"Dummy": "Dummy",
"Edit Product": "제품 편집",
"I have completed the payment": "저는 지불을 완료했습니다",
"Image": "이미지",
@@ -772,22 +766,14 @@
"sign in now": "지금 로그인하십시오"
},
"subscription": {
"Approved": "Approved",
"Duration": "기간",
"Duration - Tooltip": "구독 기간",
"Edit Subscription": "Edit Subscription",
"End Date": "종료일",
"End Date - Tooltip": "종료일",
"End date": "종료일",
"End date - Tooltip": "종료일",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "시작일",
"Start Date - Tooltip": "시작일",
"Sub plan": "구독 플랜",
"Sub plan - Tooltip": "구독 플랜",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "구독 사용자",
"Sub users - Tooltip": "구독 사용자"
"Start date": "시작일",
"Start date - Tooltip": "시작일"
},
"syncer": {
"Affiliation table": "소속 테이블",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "Aplicações",
"Applications that require authentication": "Aplicações que requerem autenticação",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "Avatar",
"Avatar - Tooltip": "Imagem de avatar pública do usuário",
"Back": "Voltar",
@@ -265,7 +261,10 @@
"Phone": "Telefone",
"Phone - Tooltip": "Número de telefone",
"Phone or email": "Telefone ou email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Kế hoạch",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "Visualizar",
"Preview - Tooltip": "Visualizar os efeitos configurados",
"Pricings": "Bảng giá",
@@ -278,6 +277,8 @@
"Records": "Registros",
"Request URI": "URI da solicitação",
"Resources": "Recursos",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "Funções",
"Roles - Tooltip": "Funções às quais o usuário pertence",
"Save": "Salvar",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "Desculpe, você não tem permissão para acessar esta página ou o status de login é inválido.",
"State": "Estado",
"State - Tooltip": "Estado",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "Đăng ký",
"Successfully added": "Adicionado com sucesso",
"Successfully deleted": "Excluído com sucesso",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "mỗi tháng",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "Giá mỗi tháng",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "Giá mỗi năm",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "Vai trò bao gồm trong kế hoạch hiện tại"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "mỗi tháng"
},
"pricing": {
"Copy pricing page URL": "Sao chép URL trang bảng giá",
@@ -547,8 +542,6 @@
"Has trial": "Có thời gian thử nghiệm",
"Has trial - Tooltip": "Khả dụng thời gian thử nghiệm sau khi chọn kế hoạch",
"New Pricing": "New Pricing",
"Sub plans": "Kế hoạch phụ",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "Thời gian thử nghiệm",
"Trial duration - Tooltip": "Thời gian thử nghiệm",
"days trial available!": "ngày dùng thử có sẵn!",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "Detalhe",
"Detail - Tooltip": "Detalhes do produto",
"Dummy": "Dummy",
"Edit Product": "Editar Produto",
"I have completed the payment": "Eu concluí o pagamento",
"Image": "Imagem",
@@ -772,22 +766,14 @@
"sign in now": "Faça login agora"
},
"subscription": {
"Approved": "Approved",
"Duration": "Thời lượng",
"Duration - Tooltip": "Thời lượng đăng ký",
"Edit Subscription": "Edit Subscription",
"End Date": "Ngày kết thúc",
"End Date - Tooltip": "Ngày kết thúc",
"End date": "Ngày kết thúc",
"End date - Tooltip": "Ngày kết thúc",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "Ngày bắt đầu",
"Start Date - Tooltip": "Ngày bắt đầu",
"Sub plan": "Kế hoạch đăng ký",
"Sub plan - Tooltip": "Kế hoạch đăng ký",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "Người dùng đăng ký",
"Sub users - Tooltip": "Người dùng đăng ký"
"Start date": "Ngày bắt đầu",
"Start date - Tooltip": "Ngày bắt đầu"
},
"syncer": {
"Affiliation table": "Tabela de Afiliação",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "Приложения",
"Applications that require authentication": "Приложения, которые требуют аутентификации",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "Аватар",
"Avatar - Tooltip": "Публичное изображение аватара пользователя",
"Back": "Back",
@@ -265,7 +261,10 @@
"Phone": "Телефон",
"Phone - Tooltip": "Номер телефона",
"Phone or email": "Phone or email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Планы",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "Предварительный просмотр",
"Preview - Tooltip": "Предварительный просмотр настроенных эффектов",
"Pricings": "Тарифы",
@@ -278,6 +277,8 @@
"Records": "Записи",
"Request URI": "Запрос URI",
"Resources": "Ресурсы",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "Роли",
"Roles - Tooltip": "Роли, к которым принадлежит пользователь",
"Save": "Сохранить",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "К сожалению, у вас нет разрешения на доступ к этой странице или ваш статус входа недействителен.",
"State": "Государство",
"State - Tooltip": "Государство",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "Подписки",
"Successfully added": "Успешно добавлено",
"Successfully deleted": "Успешно удалено",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "в месяц",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "Цена за месяц",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "Цена за год",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "Роль, включенная в текущий план"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "в месяц"
},
"pricing": {
"Copy pricing page URL": "Скопировать URL прайс-листа",
@@ -547,8 +542,6 @@
"Has trial": "Есть пробный период",
"Has trial - Tooltip": "Наличие пробного периода после выбора плана",
"New Pricing": "New Pricing",
"Sub plans": "Тарифные планы",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "Продолжительность пробного периода",
"Trial duration - Tooltip": "Продолжительность пробного периода",
"days trial available!": "дней пробного периода доступно!",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "Деталь",
"Detail - Tooltip": "Деталь продукта",
"Dummy": "Dummy",
"Edit Product": "Редактировать продукт",
"I have completed the payment": "Я произвел оплату",
"Image": "Изображение",
@@ -772,22 +766,14 @@
"sign in now": "войти сейчас"
},
"subscription": {
"Approved": "Approved",
"Duration": "Продолжительность",
"Duration - Tooltip": "Продолжительность подписки",
"Edit Subscription": "Edit Subscription",
"End Date": "Дата окончания",
"End Date - Tooltip": "Дата окончания",
"End date": "Дата окончания",
"End date - Tooltip": "Дата окончания",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "Дата начала",
"Start Date - Tooltip": "Дата начала",
"Sub plan": "План подписки",
"Sub plan - Tooltip": "План подписки",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "Пользователь подписки",
"Sub users - Tooltip": "Пользователь которому офомлена подписка"
"Start date": "Дата начала",
"Start date - Tooltip": "Дата начала"
},
"syncer": {
"Affiliation table": "Таблица принадлежности",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "Ứng dụng",
"Applications that require authentication": "Các ứng dụng yêu cầu xác thực",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "Ảnh đại diện",
"Avatar - Tooltip": "Ảnh đại diện công khai cho người dùng",
"Back": "Back",
@@ -265,7 +261,10 @@
"Phone": "Điện thoại",
"Phone - Tooltip": "Số điện thoại",
"Phone or email": "Phone or email",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Kế hoạch",
"Plans - Tooltip": "Plans - Tooltip",
"Preview": "Xem trước",
"Preview - Tooltip": "Xem trước các hiệu ứng đã cấu hình",
"Pricings": "Bảng giá",
@@ -278,6 +277,8 @@
"Records": "Hồ sơ",
"Request URI": "Yêu cầu URI",
"Resources": "Tài nguyên",
"Role": "Role",
"Role - Tooltip": "Role - Tooltip",
"Roles": "Vai trò",
"Roles - Tooltip": "Các vai trò mà người dùng thuộc về",
"Save": "Lưu",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "Xin lỗi, bạn không có quyền truy cập trang này hoặc trạng thái đăng nhập không hợp lệ.",
"State": "Nhà nước",
"State - Tooltip": "Trạng thái",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "Đăng ký",
"Successfully added": "Đã thêm thành công",
"Successfully deleted": "Đã xóa thành công",
@@ -529,15 +528,11 @@
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "mỗi tháng",
"Price per month": "Price per month",
"Price per month - Tooltip": "Price per month - Tooltip",
"Price per year": "Price per year",
"PricePerMonth": "Giá mỗi tháng",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "Giá mỗi năm",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "Vai trò bao gồm trong kế hoạch hiện tại"
"Price per year - Tooltip": "Price per year - Tooltip",
"per month": "mỗi tháng"
},
"pricing": {
"Copy pricing page URL": "Sao chép URL trang bảng giá",
@@ -547,8 +542,6 @@
"Has trial": "Có thời gian thử nghiệm",
"Has trial - Tooltip": "Khả dụng thời gian thử nghiệm sau khi chọn kế hoạch",
"New Pricing": "New Pricing",
"Sub plans": "Kế hoạch phụ",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"Trial duration": "Thời gian thử nghiệm",
"Trial duration - Tooltip": "Thời gian thử nghiệm",
"days trial available!": "ngày dùng thử có sẵn!",
@@ -561,6 +554,7 @@
"CNY": "CNY",
"Detail": "Chi tiết",
"Detail - Tooltip": "Chi tiết sản phẩm",
"Dummy": "Dummy",
"Edit Product": "Chỉnh sửa sản phẩm",
"I have completed the payment": "Tôi đã thanh toán hoàn tất",
"Image": "Ảnh",
@@ -772,22 +766,14 @@
"sign in now": "Đăng nhập ngay bây giờ"
},
"subscription": {
"Approved": "Approved",
"Duration": "Thời lượng",
"Duration - Tooltip": "Thời lượng đăng ký",
"Edit Subscription": "Edit Subscription",
"End Date": "Ngày kết thúc",
"End Date - Tooltip": "Ngày kết thúc",
"End date": "Ngày kết thúc",
"End date - Tooltip": "Ngày kết thúc",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "Ngày bắt đầu",
"Start Date - Tooltip": "Ngày bắt đầu",
"Sub plan": "Kế hoạch đăng ký",
"Sub plan - Tooltip": "Kế hoạch đăng ký",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "Người dùng đăng ký",
"Sub users - Tooltip": "Người dùng đăng ký"
"Start date": "Ngày bắt đầu",
"Start date - Tooltip": "Ngày bắt đầu"
},
"syncer": {
"Affiliation table": "Bảng liên kết",

View File

@@ -173,10 +173,6 @@
"Application - Tooltip": "Application - Tooltip",
"Applications": "应用",
"Applications that require authentication": "需要认证和鉴权的应用",
"Approve time": "Approve time",
"Approve time - Tooltip": "Approve time - Tooltip",
"Approver": "Approver",
"Approver - Tooltip": "Approver - Tooltip",
"Avatar": "头像",
"Avatar - Tooltip": "公开展示的用户头像",
"Back": "返回",
@@ -265,7 +261,10 @@
"Phone": "手机号",
"Phone - Tooltip": "手机号",
"Phone or email": "手机或邮箱",
"Plan": "计划",
"Plan - Tooltip": "订阅里的计划",
"Plans": "计划",
"Plans - Tooltip": "订阅里的计划",
"Preview": "预览",
"Preview - Tooltip": "可预览所配置的效果",
"Pricings": "定价",
@@ -278,6 +277,8 @@
"Records": "日志",
"Request URI": "请求URI",
"Resources": "资源",
"Role": "角色",
"Role - Tooltip": "所对应的角色",
"Roles": "角色",
"Roles - Tooltip": "用户所属的角色",
"Save": "保存",
@@ -295,8 +296,6 @@
"Sorry, you do not have permission to access this page or logged in status invalid.": "抱歉,您无权访问该页面或登录状态失效",
"State": "状态",
"State - Tooltip": "状态",
"Submitter": "Submitter",
"Submitter - Tooltip": "Submitter - Tooltip",
"Subscriptions": "订阅",
"Successfully added": "添加成功",
"Successfully deleted": "删除成功",
@@ -527,28 +526,22 @@
"Write": "写权限"
},
"plan": {
"Edit Plan": "Edit Plan",
"New Plan": "New Plan",
"PerMonth": "月",
"Price per month": "Price per month",
"Price per year": "Price per year",
"PricePerMonth": "每月价格",
"PricePerMonth - Tooltip": "PricePerMonth - Tooltip",
"PricePerYear": "每年价格",
"PricePerYear - Tooltip": "PricePerYear - Tooltip",
"Sub role": "Sub role",
"Sub roles - Tooltip": "当前计划中包含的角色"
"Edit Plan": "编辑计划",
"New Plan": "添加计划",
"Price per month": "价格/月",
"Price per month - Tooltip": "该订阅一个月的价格",
"Price per year": "价格/年",
"Price per year - Tooltip": "该订阅一年的价格",
"per month": "每月"
},
"pricing": {
"Copy pricing page URL": "复制定价页面链接",
"Edit Pricing": "Edit Pricing",
"Edit Pricing": "编辑定价",
"Free": "免费",
"Getting started": "开始使用",
"Has trial": "有试用期",
"Has trial - Tooltip": "选择计划后是否有试用期",
"New Pricing": "New Pricing",
"Sub plans": "附加计划",
"Sub plans - Tooltip": "Sub plans - Tooltip",
"New Pricing": "添加定价",
"Trial duration": "试用期时长",
"Trial duration - Tooltip": "试用期时长",
"days trial available!": "天试用期可用!",
@@ -561,6 +554,7 @@
"CNY": "人民币",
"Detail": "详情",
"Detail - Tooltip": "商品详情",
"Dummy": "虚拟",
"Edit Product": "编辑商品",
"I have completed the payment": "支付完成",
"Image": "图片",
@@ -772,22 +766,14 @@
"sign in now": "立即登录"
},
"subscription": {
"Approved": "Approved",
"Duration": "订阅时长",
"Duration - Tooltip": "订阅时长",
"Edit Subscription": "Edit Subscription",
"End Date": "结束日期",
"End Date - Tooltip": "结束日期",
"New Subscription": "New Subscription",
"Pending": "Pending",
"Start Date": "开始日期",
"Start Date - Tooltip": "开始日期",
"Sub plan": "订阅计划",
"Sub plan - Tooltip": "订阅计划",
"Sub plane": "Sub plane",
"Sub user": "Sub user",
"Sub users": "订阅用户",
"Sub users - Tooltip": "订阅用户"
"Edit Subscription": "编辑订阅",
"End date": "结束日期",
"End date - Tooltip": "结束日期",
"New Subscription": "添加订阅",
"Start date": "开始日期",
"Start date - Tooltip": "开始日期"
},
"syncer": {
"Affiliation table": "工作单位表",

View File

@@ -27,6 +27,7 @@ class PricingPage extends React.Component {
this.state = {
classes: props,
applications: null,
owner: props.owner ?? (props.match?.params?.owner ?? null),
pricingName: (props.pricingName ?? props.match?.params?.pricingName) ?? null,
pricing: props.pricing,
plans: null,
@@ -78,7 +79,7 @@ class PricingPage extends React.Component {
return;
}
PricingBackend.getPricing("built-in", pricingName)
PricingBackend.getPricing(this.state.owner, pricingName)
.then((result) => {
this.setState({
loading: false,

View File

@@ -44,7 +44,7 @@ class SingleCard extends React.Component {
<div style={{textAlign: "left"}} className="px-10 mt-5">
<span style={{fontWeight: 700, fontSize: "48px"}}>$ {plan.pricePerMonth}</span>
<span style={{fontSize: "18px", fontWeight: 600, color: "gray"}}> {i18next.t("plan:PerMonth")}</span>
<span style={{fontSize: "18px", fontWeight: 600, color: "gray"}}> {i18next.t("plan:per month")}</span>
</div>
<br />