From 12acb24dbc6ff15190bbd05b45a00eec14804e81 Mon Sep 17 00:00:00 2001 From: DacongDA Date: Sat, 2 Mar 2024 10:41:16 +0800 Subject: [PATCH] feat: add transaction pages (#2761) --- controllers/transaction.go | 167 +++++++++++++ object/ormer.go | 5 + routers/router.go | 6 + web/src/ManagementPage.js | 5 + web/src/TransactionEditPage.js | 324 +++++++++++++++++++++++++ web/src/TransactionListPage.js | 333 ++++++++++++++++++++++++++ web/src/backend/TransactionBackend.js | 71 ++++++ web/src/locales/ar/data.json | 8 + web/src/locales/de/data.json | 8 + web/src/locales/en/data.json | 8 + web/src/locales/es/data.json | 8 + web/src/locales/fa/data.json | 8 + web/src/locales/fi/data.json | 8 + web/src/locales/fr/data.json | 8 + web/src/locales/he/data.json | 8 + web/src/locales/id/data.json | 8 + web/src/locales/it/data.json | 8 + web/src/locales/ja/data.json | 8 + web/src/locales/kk/data.json | 8 + web/src/locales/ko/data.json | 8 + web/src/locales/ms/data.json | 8 + web/src/locales/nl/data.json | 8 + web/src/locales/pl/data.json | 8 + web/src/locales/pt/data.json | 8 + web/src/locales/ru/data.json | 8 + web/src/locales/sv/data.json | 8 + web/src/locales/tr/data.json | 8 + web/src/locales/uk/data.json | 8 + web/src/locales/vi/data.json | 8 + web/src/locales/zh/data.json | 8 + 30 files changed, 1095 insertions(+) create mode 100644 controllers/transaction.go create mode 100644 web/src/TransactionEditPage.js create mode 100644 web/src/TransactionListPage.js create mode 100644 web/src/backend/TransactionBackend.js diff --git a/controllers/transaction.go b/controllers/transaction.go new file mode 100644 index 00000000..d72d2f04 --- /dev/null +++ b/controllers/transaction.go @@ -0,0 +1,167 @@ +// Copyright 2024 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 controllers + +import ( + "encoding/json" + + "github.com/beego/beego/utils/pagination" + "github.com/casdoor/casdoor/object" + "github.com/casdoor/casdoor/util" +) + +// GetTransactions +// @Title GetTransactions +// @Tag Transaction API +// @Description get transactions +// @Param owner query string true "The owner of transactions" +// @Success 200 {array} object.Transaction The Response object +// @router /get-transactions [get] +func (c *ApiController) GetTransactions() { + owner := c.Input().Get("owner") + limit := c.Input().Get("pageSize") + page := c.Input().Get("p") + field := c.Input().Get("field") + value := c.Input().Get("value") + sortField := c.Input().Get("sortField") + sortOrder := c.Input().Get("sortOrder") + + if limit == "" || page == "" { + transactions, err := object.GetTransactions(owner) + if err != nil { + c.ResponseError(err.Error()) + return + } + + c.ResponseOk(transactions) + } else { + limit := util.ParseInt(limit) + count, err := object.GetTransactionCount(owner, field, value) + if err != nil { + c.ResponseError(err.Error()) + return + } + + paginator := pagination.SetPaginator(c.Ctx, limit, count) + transactions, err := object.GetPaginationTransactions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder) + if err != nil { + c.ResponseError(err.Error()) + return + } + + c.ResponseOk(transactions, paginator.Nums()) + } +} + +// GetUserTransactions +// @Title GetUserTransaction +// @Tag Transaction API +// @Description get transactions for a user +// @Param owner query string true "The owner of transactions" +// @Param organization query string true "The organization of the user" +// @Param user query string true "The username of the user" +// @Success 200 {array} object.Transaction The Response object +// @router /get-user-transactions [get] +func (c *ApiController) GetUserTransactions() { + owner := c.Input().Get("owner") + user := c.Input().Get("user") + + transactions, err := object.GetUserTransactions(owner, user) + if err != nil { + c.ResponseError(err.Error()) + return + } + + c.ResponseOk(transactions) +} + +// GetTransaction +// @Title GetTransaction +// @Tag Transaction API +// @Description get transaction +// @Param id query string true "The id ( owner/name ) of the transaction" +// @Success 200 {object} object.Transaction The Response object +// @router /get-transaction [get] +func (c *ApiController) GetTransaction() { + id := c.Input().Get("id") + + transaction, err := object.GetTransaction(id) + if err != nil { + c.ResponseError(err.Error()) + return + } + + c.ResponseOk(transaction) +} + +// UpdateTransaction +// @Title UpdateTransaction +// @Tag Transaction API +// @Description update transaction +// @Param id query string true "The id ( owner/name ) of the transaction" +// @Param body body object.Transaction true "The details of the transaction" +// @Success 200 {object} controllers.Response The Response object +// @router /update-transaction [post] +func (c *ApiController) UpdateTransaction() { + id := c.Input().Get("id") + + var transaction object.Transaction + err := json.Unmarshal(c.Ctx.Input.RequestBody, &transaction) + if err != nil { + c.ResponseError(err.Error()) + return + } + + c.Data["json"] = wrapActionResponse(object.UpdateTransaction(id, &transaction)) + c.ServeJSON() +} + +// AddTransaction +// @Title AddTransaction +// @Tag Transaction API +// @Description add transaction +// @Param body body object.Transaction true "The details of the transaction" +// @Success 200 {object} controllers.Response The Response object +// @router /add-transaction [post] +func (c *ApiController) AddTransaction() { + var transaction object.Transaction + err := json.Unmarshal(c.Ctx.Input.RequestBody, &transaction) + if err != nil { + c.ResponseError(err.Error()) + return + } + + c.Data["json"] = wrapActionResponse(object.AddTransaction(&transaction)) + c.ServeJSON() +} + +// DeleteTransaction +// @Title DeleteTransaction +// @Tag Transaction API +// @Description delete transaction +// @Param body body object.Transaction true "The details of the transaction" +// @Success 200 {object} controllers.Response The Response object +// @router /delete-transaction [post] +func (c *ApiController) DeleteTransaction() { + var transaction object.Transaction + err := json.Unmarshal(c.Ctx.Input.RequestBody, &transaction) + if err != nil { + c.ResponseError(err.Error()) + return + } + + c.Data["json"] = wrapActionResponse(object.DeleteTransaction(&transaction)) + c.ServeJSON() +} diff --git a/object/ormer.go b/object/ormer.go index ce7c8674..c46963d2 100644 --- a/object/ormer.go +++ b/object/ormer.go @@ -388,6 +388,11 @@ func (a *Ormer) createTable() { panic(err) } + err = a.Engine.Sync2(new(Transaction)) + if err != nil { + panic(err) + } + err = a.Engine.Sync2(new(Syncer)) if err != nil { panic(err) diff --git a/routers/router.go b/routers/router.go index 35be85e3..643cfeea 100644 --- a/routers/router.go +++ b/routers/router.go @@ -221,6 +221,12 @@ func initAPI() { beego.Router("/api/add-subscription", &controllers.ApiController{}, "POST:AddSubscription") beego.Router("/api/delete-subscription", &controllers.ApiController{}, "POST:DeleteSubscription") + beego.Router("/api/get-transactions", &controllers.ApiController{}, "GET:GetTransactions") + beego.Router("/api/get-transaction", &controllers.ApiController{}, "GET:GetTransaction") + beego.Router("/api/update-transaction", &controllers.ApiController{}, "POST:UpdateTransaction") + beego.Router("/api/add-transaction", &controllers.ApiController{}, "POST:AddTransaction") + beego.Router("/api/delete-transaction", &controllers.ApiController{}, "POST:DeleteTransaction") + beego.Router("/api/get-system-info", &controllers.ApiController{}, "GET:GetSystemInfo") beego.Router("/api/get-version-info", &controllers.ApiController{}, "GET:GetVersionInfo") beego.Router("/api/health", &controllers.ApiController{}, "GET:Health") diff --git a/web/src/ManagementPage.js b/web/src/ManagementPage.js index 86f936f3..72bbc581 100644 --- a/web/src/ManagementPage.js +++ b/web/src/ManagementPage.js @@ -90,6 +90,8 @@ import AccountAvatar from "./account/AccountAvatar"; import {Content, Header} from "antd/es/layout/layout"; import * as AuthBackend from "./auth/AuthBackend"; import {clearWeb3AuthToken} from "./auth/Web3Auth"; +import TransactionListPage from "./TransactionListPage"; +import TransactionEditPage from "./TransactionEditPage"; function ManagementPage(props) { @@ -279,6 +281,7 @@ function ManagementPage(props) { Setting.getItem({i18next.t("general:Plans")}, "/plans"), Setting.getItem({i18next.t("general:Pricings")}, "/pricings"), Setting.getItem({i18next.t("general:Subscriptions")}, "/subscriptions"), + Setting.getItem({i18next.t("general:Transactions")}, "/transactions"), ])); if (Setting.isAdminUser(props.account)) { @@ -365,6 +368,8 @@ function ManagementPage(props) { renderLoginIfNotLoggedIn()} /> renderLoginIfNotLoggedIn()} /> renderLoginIfNotLoggedIn()} /> + renderLoginIfNotLoggedIn()} /> + renderLoginIfNotLoggedIn()} /> renderLoginIfNotLoggedIn()} /> renderLoginIfNotLoggedIn()} /> renderLoginIfNotLoggedIn()} /> diff --git a/web/src/TransactionEditPage.js b/web/src/TransactionEditPage.js new file mode 100644 index 00000000..20f7a99a --- /dev/null +++ b/web/src/TransactionEditPage.js @@ -0,0 +1,324 @@ +// Copyright 2024 The Casdoor Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import React from "react"; +import * as TransactionBackend from "./backend/TransactionBackend"; +import * as Setting from "./Setting"; +import * as ApplicationBackend from "./backend/ApplicationBackend"; +import {Button, Card, Col, Input, Row} from "antd"; +import i18next from "i18next"; + +class TransactionEditPage extends React.Component { + constructor(props) { + super(props); + this.state = { + classes: props, + organizationName: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName, + transactionName: props.match.params.transactionName, + application: null, + transaction: null, + providers: [], + mode: props.location.mode !== undefined ? props.location.mode : "edit", + }; + } + + UNSAFE_componentWillMount() { + this.getTransaction(); + } + + getTransaction() { + TransactionBackend.getTransaction(this.state.organizationName, this.state.transactionName) + .then((res) => { + if (res.data === null) { + this.props.history.push("/404"); + return; + } + + this.setState({ + transaction: res.data, + }); + + Setting.scrollToDiv("invoice-area"); + }); + } + + submitTransactionEdit(exitAfterSave) { + const transaction = Setting.deepCopy(this.state.transaction); + TransactionBackend.updateTransaction(this.state.transaction.owner, this.state.transactionName, transaction) + .then((res) => { + if (res.status === "ok") { + Setting.showMessage("success", i18next.t("general:Successfully saved")); + this.setState({ + transactionName: this.state.transaction.name, + }); + + if (exitAfterSave) { + this.props.history.push("/transactions"); + } else { + this.props.history.push(`/transactions/${this.state.organizationName}/${this.state.transaction.name}`); + } + } else { + Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`); + this.updatePaymentField("name", this.state.transactionName); + } + }) + .catch(error => { + Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`); + }); + } + + deleteTransaction() { + TransactionBackend.deleteTransaction(this.state.transaction) + .then((res) => { + if (res.status === "ok") { + this.props.history.push("/transactions"); + } else { + Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`); + } + }) + .catch(error => { + Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`); + }); + } + + parseTransactionField(key, value) { + if ([""].includes(key)) { + value = Setting.myParseInt(value); + } + return value; + } + + getApplication() { + ApplicationBackend.getApplication("admin", this.state.applicationName) + .then((res) => { + if (res.data === null) { + this.props.history.push("/404"); + return; + } + + if (res.status === "error") { + Setting.showMessage("error", res.msg); + return; + } + + const application = res.data; + if (application.grantTypes === null || application.grantTypes === undefined || application.grantTypes.length === 0) { + application.grantTypes = ["authorization_code"]; + } + + if (application.tags === null || application.tags === undefined) { + application.tags = []; + } + + this.setState({ + application: application, + }); + + this.getCerts(application.organization); + + this.getSamlMetadata(application.enableSamlPostBinding); + }); + } + + renderTransaction() { + return ( + + {this.state.mode === "add" ? i18next.t("transaction:New Transaction") : i18next.t("transaction:Edit Transaction")}     + + + {this.state.mode === "add" ? : null} + + } style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner"> + + + {Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} : + + + { + // this.updatePaymentField('organization', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} : + + + { + // this.updatePaymentField('name', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} : + + + { + this.updatePaymentField("displayName", e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("general:Provider"), i18next.t("general:Provider - Tooltip"))} : + + + { + // this.updatePaymentField('provider', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("provider:Category"), i18next.t("provider:Category - Tooltip"))} : + + + { + this.updatePaymentField("displayName", e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("provider:Type"), i18next.t("payment:Type - Tooltip"))} : + + + { + // this.updatePaymentField('type', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("payment:Product"), i18next.t("payment:Product - Tooltip"))} : + + + { + // this.updatePaymentField('productName', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("product:Detail"), i18next.t("product:Detail - Tooltip"))} : + + + { + // this.updatePaymentField('currency', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("user:Tag"), i18next.t("transaction:Tag - Tooltip"))} : + + + { + // this.updatePaymentField('currency', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("payment:Currency"), i18next.t("payment:Currency - Tooltip"))} : + + + { + // this.updatePaymentField('currency', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("transaction:Amount"), i18next.t("transaction:Amount - Tooltip"))} : + + + { + // this.updatePaymentField('amount', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("product:Return URL"), i18next.t("product:Return URL - Tooltip"))} : + + + { + // this.updatePaymentField('amount', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("general:User"), i18next.t("general:User - Tooltip"))} : + + + { + // this.updatePaymentField('amount', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("general:Application"), i18next.t("general:Application - Tooltip"))} : + + + { + // this.updatePaymentField('amount', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("general:Payment"), i18next.t("general:Payment - Tooltip"))} : + + + { + // this.updatePaymentField('amount', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("general:State"), i18next.t("general:State - Tooltip"))} : + + + { + // this.updatePaymentField('state', e.target.value); + }} /> + + + + ); + } + + render() { + return ( +
+ { + this.state.transaction !== null ? this.renderTransaction() : null + } +
+ + + {this.state.mode === "add" ? : null} +
+
+ ); + } +} + +export default TransactionEditPage; diff --git a/web/src/TransactionListPage.js b/web/src/TransactionListPage.js new file mode 100644 index 00000000..6ef026c1 --- /dev/null +++ b/web/src/TransactionListPage.js @@ -0,0 +1,333 @@ +// Copyright 2024 The Casdoor Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import BaseListPage from "./BaseListPage"; +import i18next from "i18next"; +import {Link} from "react-router-dom"; +import * as Setting from "./Setting"; +import * as Provider from "./auth/Provider"; +import {Button, Table} from "antd"; +import PopconfirmModal from "./common/modal/PopconfirmModal"; +import React from "react"; +import * as TransactionBackend from "./backend/TransactionBackend"; +import moment from "moment/moment"; + +class TransactionListPage extends BaseListPage { + newTransaction() { + const randomName = Setting.getRandomName(); + const organizationName = Setting.getRequestOrganization(this.props.account); + return { + owner: organizationName, + name: `transaction_${randomName}`, + createdTime: moment().format(), + displayName: `New Transaction - ${randomName}`, + provider: "provider_pay_paypal", + category: "", + type: "PayPal", + productName: "computer-1", + productDisplayName: "A notebook computer", + detail: "This is a computer with excellent CPU, memory and disk", + tag: "Promotion-1", + currency: "USD", + amount: 0, + returnUrl: "https://door.casdoor.com/transactions", + user: "admin", + application: "", + payment: "payment_bhn1ra", + state: "Paid", + }; + } + + deleteTransaction(i) { + TransactionBackend.deleteTransaction(this.state.data[i]) + .then((res) => { + if (res.status === "ok") { + Setting.showMessage("success", i18next.t("general:Successfully deleted")); + this.setState({ + data: Setting.deleteRow(this.state.data, i), + pagination: {total: this.state.pagination.total - 1}, + }); + } else { + Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`); + } + }) + .catch(error => { + Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`); + }); + } + + addTransaction() { + const newTransaction = this.newTransaction(); + TransactionBackend.addTransaction(newTransaction) + .then((res) => { + if (res.status === "ok") { + this.props.history.push({pathname: `/transactions/${newTransaction.owner}/${newTransaction.name}`, mode: "add"}); + Setting.showMessage("success", i18next.t("general:Successfully added")); + } else { + Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`); + } + } + ) + .catch(error => { + Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`); + }); + } + + renderTable(transactions) { + const columns = [ + { + title: i18next.t("general:Name"), + dataIndex: "name", + key: "name", + width: "180px", + fixed: "left", + sorter: true, + ...this.getColumnSearchProps("name"), + render: (text, record, index) => { + return ( + + {text} + + ); + }, + }, + { + title: i18next.t("general:Organization"), + dataIndex: "owner", + key: "owner", + width: "120px", + fixed: "left", + sorter: true, + ...this.getColumnSearchProps("owner"), + render: (text, record, index) => { + return ( + + {text} + + ); + }, + }, + { + title: i18next.t("general:Provider"), + dataIndex: "provider", + key: "provider", + width: "150px", + sorter: true, + ...this.getColumnSearchProps("provider"), + render: (text, record, index) => { + return ( + + {text} + + ); + }, + }, + { + title: i18next.t("general:User"), + dataIndex: "user", + key: "user", + width: "120px", + sorter: true, + ...this.getColumnSearchProps("user"), + render: (text, record, index) => { + return ( + + {text} + + ); + }, + }, + + { + title: i18next.t("general:Created time"), + dataIndex: "createdTime", + key: "createdTime", + width: "160px", + sorter: true, + render: (text, record, index) => { + return Setting.getFormattedDate(text); + }, + }, + { + title: i18next.t("provider:Type"), + dataIndex: "type", + key: "type", + width: "140px", + align: "center", + filterMultiple: false, + filters: Setting.getProviderTypeOptions("Payment").map((o) => {return {text: o.id, value: o.name};}), + sorter: true, + render: (text, record, index) => { + record.category = "Payment"; + return Provider.getProviderLogoWidget(record); + }, + }, + { + title: i18next.t("payment:Product"), + dataIndex: "productDisplayName", + key: "productDisplayName", + // width: '160px', + sorter: true, + ...this.getColumnSearchProps("productDisplayName"), + render: (text, record, index) => { + return ( + + {text} + + ); + }, + }, + { + title: i18next.t("payment:Currency"), + dataIndex: "currency", + key: "currency", + width: "120px", + sorter: true, + ...this.getColumnSearchProps("currency"), + }, + { + title: i18next.t("transaction:Amount"), + dataIndex: "amount", + key: "amount", + width: "120px", + sorter: true, + ...this.getColumnSearchProps("amount"), + }, + { + title: i18next.t("general:User"), + dataIndex: "user", + key: "user", + width: "120px", + sorter: true, + ...this.getColumnSearchProps("user"), + }, + { + title: i18next.t("general:Application"), + dataIndex: "application", + key: "application", + width: "120px", + sorter: true, + ...this.getColumnSearchProps("application"), + render: (text, record, index) => { + return ( + + {text} + + ); + }, + }, + { + title: i18next.t("general:Payment"), + dataIndex: "payment", + key: "payment", + width: "120px", + sorter: true, + ...this.getColumnSearchProps("payment"), + render: (text, record, index) => { + return ( + + {text} + + ); + }, + }, + { + title: i18next.t("general:State"), + dataIndex: "state", + key: "state", + width: "120px", + sorter: true, + ...this.getColumnSearchProps("state"), + }, + { + title: i18next.t("general:Action"), + dataIndex: "", + key: "op", + width: "240px", + fixed: (Setting.isMobile()) ? "false" : "right", + render: (text, record, index) => { + return ( +
+ + this.deleteTransaction(index)} + > + +
+ ); + }, + }, + ]; + + const paginationProps = { + total: this.state.pagination.total, + showQuickJumper: true, + showSizeChanger: true, + showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total), + }; + + return ( +
+ `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps} + title={() => ( +
+ {i18next.t("general:Transactions")}     + +
+ )} + loading={this.state.loading} + onChange={this.handleTableChange} + /> + + ); + } + + fetch = (params = {}) => { + let field = params.searchedColumn, value = params.searchText; + const sortField = params.sortField, sortOrder = params.sortOrder; + if (params.type !== undefined && params.type !== null) { + field = "type"; + value = params.type; + } + this.setState({loading: true}); + TransactionBackend.getTransactions(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder) + .then((res) => { + this.setState({ + loading: false, + }); + if (res.status === "ok") { + this.setState({ + data: res.data, + pagination: { + ...params.pagination, + total: res.data2, + }, + searchText: params.searchText, + searchedColumn: params.searchedColumn, + }); + } else { + if (Setting.isResponseDenied(res)) { + this.setState({ + isAuthorized: false, + }); + } else { + Setting.showMessage("error", res.msg); + } + } + }); + }; +} + +export default TransactionListPage; diff --git a/web/src/backend/TransactionBackend.js b/web/src/backend/TransactionBackend.js new file mode 100644 index 00000000..f329f832 --- /dev/null +++ b/web/src/backend/TransactionBackend.js @@ -0,0 +1,71 @@ +// Copyright 2024 The Casdoor Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import * as Setting from "../Setting"; + +export function getTransactions(owner, page = "", pageSize = "", field = "", value = "", sortField = "", sortOrder = "") { + return fetch(`${Setting.ServerUrl}/api/get-transactions?owner=${owner}&p=${page}&pageSize=${pageSize}&field=${field}&value=${value}&sortField=${sortField}&sortOrder=${sortOrder}`, { + method: "GET", + credentials: "include", + headers: { + "Accept-Language": Setting.getAcceptLanguage(), + }, + }).then(res => res.json()); +} + +export function getTransaction(owner, name) { + return fetch(`${Setting.ServerUrl}/api/get-transaction?id=${owner}/${encodeURIComponent(name)}`, { + method: "GET", + credentials: "include", + headers: { + "Accept-Language": Setting.getAcceptLanguage(), + }, + }).then(res => res.json()); +} + +export function updateTransaction(owner, name, transaction) { + const newTransaction = Setting.deepCopy(transaction); + return fetch(`${Setting.ServerUrl}/api/update-transaction?id=${owner}/${encodeURIComponent(name)}`, { + method: "POST", + credentials: "include", + body: JSON.stringify(newTransaction), + headers: { + "Accept-Language": Setting.getAcceptLanguage(), + }, + }).then(res => res.json()); +} + +export function addTransaction(transaction) { + const newTransaction = Setting.deepCopy(transaction); + return fetch(`${Setting.ServerUrl}/api/add-transaction`, { + method: "POST", + credentials: "include", + body: JSON.stringify(newTransaction), + headers: { + "Accept-Language": Setting.getAcceptLanguage(), + }, + }).then(res => res.json()); +} + +export function deleteTransaction(transaction) { + const newTransaction = Setting.deepCopy(transaction); + return fetch(`${Setting.ServerUrl}/api/delete-transaction`, { + method: "POST", + credentials: "include", + body: JSON.stringify(newTransaction), + headers: { + "Accept-Language": Setting.getAcceptLanguage(), + }, + }).then(res => res.json()); +} diff --git a/web/src/locales/ar/data.json b/web/src/locales/ar/data.json index 6e6a6d8c..e1061cee 100644 --- a/web/src/locales/ar/data.json +++ b/web/src/locales/ar/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/de/data.json b/web/src/locales/de/data.json index 9d60453c..e1bf300e 100644 --- a/web/src/locales/de/data.json +++ b/web/src/locales/de/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "Dies ist eine schreibgeschützte Demo-Seite!", "Timestamp": "Timestamp", "Tokens": "Token", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token-Typ", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "Drittanbieter-Logins", "3rd-party logins - Tooltip": "Drittanbieter-Anmeldungen, die mit dem Benutzer verknüpft sind", diff --git a/web/src/locales/en/data.json b/web/src/locales/en/data.json index 2ba069ff..11725ef5 100644 --- a/web/src/locales/en/data.json +++ b/web/src/locales/en/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/es/data.json b/web/src/locales/es/data.json index b48a12ec..09cbf7f1 100644 --- a/web/src/locales/es/data.json +++ b/web/src/locales/es/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "¡Este es un sitio de demostración solo de lectura!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "Dirección URL", @@ -1031,6 +1032,13 @@ "Token type": "Tipo de token", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "Inicio de sesión de terceros", "3rd-party logins - Tooltip": "Accesos sociales ligados por el usuario", diff --git a/web/src/locales/fa/data.json b/web/src/locales/fa/data.json index 0a28216b..8be6a421 100644 --- a/web/src/locales/fa/data.json +++ b/web/src/locales/fa/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/fi/data.json b/web/src/locales/fi/data.json index c573b082..fc6b20d7 100644 --- a/web/src/locales/fi/data.json +++ b/web/src/locales/fi/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/fr/data.json b/web/src/locales/fr/data.json index c9c0991e..1630f9d2 100644 --- a/web/src/locales/fr/data.json +++ b/web/src/locales/fr/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "Ceci est un site de démonstration en lecture seule !", "Timestamp": "Timestamp", "Tokens": "Jetons", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Infobulle", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Type de jeton", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "Services de connexions tiers", "3rd-party logins - Tooltip": "Service de connexions tiers liés au compte", diff --git a/web/src/locales/he/data.json b/web/src/locales/he/data.json index c573b082..fc6b20d7 100644 --- a/web/src/locales/he/data.json +++ b/web/src/locales/he/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/id/data.json b/web/src/locales/id/data.json index 7ee27017..5a0e1366 100644 --- a/web/src/locales/id/data.json +++ b/web/src/locales/id/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "Ini adalah situs demo hanya untuk dibaca saja!", "Timestamp": "Timestamp", "Tokens": "Token-token", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Jenis token", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "Masuk pihak ketiga", "3rd-party logins - Tooltip": "Masuk sosial yang terhubung oleh pengguna", diff --git a/web/src/locales/it/data.json b/web/src/locales/it/data.json index bdeffc64..80467964 100644 --- a/web/src/locales/it/data.json +++ b/web/src/locales/it/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/ja/data.json b/web/src/locales/ja/data.json index 7887489b..81f22492 100644 --- a/web/src/locales/ja/data.json +++ b/web/src/locales/ja/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "これは読み取り専用のデモサイトです!", "Timestamp": "Timestamp", "Tokens": "トークン", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "トークンタイプ", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "サードパーティログイン", "3rd-party logins - Tooltip": "ユーザーによってリンクされたソーシャルログイン", diff --git a/web/src/locales/kk/data.json b/web/src/locales/kk/data.json index c573b082..fc6b20d7 100644 --- a/web/src/locales/kk/data.json +++ b/web/src/locales/kk/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/ko/data.json b/web/src/locales/ko/data.json index 29053760..3950cc4e 100644 --- a/web/src/locales/ko/data.json +++ b/web/src/locales/ko/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "이것은 읽기 전용 데모 사이트입니다!", "Timestamp": "Timestamp", "Tokens": "토큰", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "토큰 유형", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "제3자 로그인", "3rd-party logins - Tooltip": "사용자가 연결한 소셜 로그인", diff --git a/web/src/locales/ms/data.json b/web/src/locales/ms/data.json index c573b082..fc6b20d7 100644 --- a/web/src/locales/ms/data.json +++ b/web/src/locales/ms/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/nl/data.json b/web/src/locales/nl/data.json index c573b082..fc6b20d7 100644 --- a/web/src/locales/nl/data.json +++ b/web/src/locales/nl/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/pl/data.json b/web/src/locales/pl/data.json index c573b082..fc6b20d7 100644 --- a/web/src/locales/pl/data.json +++ b/web/src/locales/pl/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/pt/data.json b/web/src/locales/pt/data.json index bba0da0b..bfdf1289 100644 --- a/web/src/locales/pt/data.json +++ b/web/src/locales/pt/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "Este é um site de demonstração apenas para leitura!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Tipo", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Tipo de Token", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "Logins de terceiros", "3rd-party logins - Tooltip": "Logins sociais vinculados pelo usuário", diff --git a/web/src/locales/ru/data.json b/web/src/locales/ru/data.json index 69da8a80..708552d9 100644 --- a/web/src/locales/ru/data.json +++ b/web/src/locales/ru/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "Это демонстрационный сайт только для чтения!", "Timestamp": "Timestamp", "Tokens": "Токены", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Тип токена", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "Авторизация сторонних участников", "3rd-party logins - Tooltip": "Социальные логины, связанные пользователем", diff --git a/web/src/locales/sv/data.json b/web/src/locales/sv/data.json index c573b082..fc6b20d7 100644 --- a/web/src/locales/sv/data.json +++ b/web/src/locales/sv/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/tr/data.json b/web/src/locales/tr/data.json index 208ddab6..2d35d3e4 100644 --- a/web/src/locales/tr/data.json +++ b/web/src/locales/tr/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "Bu site sadece görüntüleme amaçlıdır!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/uk/data.json b/web/src/locales/uk/data.json index c573b082..fc6b20d7 100644 --- a/web/src/locales/uk/data.json +++ b/web/src/locales/uk/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "This is a read-only demo site!", "Timestamp": "Timestamp", "Tokens": "Tokens", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Token type", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "3rd-party logins", "3rd-party logins - Tooltip": "Social logins linked by the user", diff --git a/web/src/locales/vi/data.json b/web/src/locales/vi/data.json index 01b5319d..7a1854f3 100644 --- a/web/src/locales/vi/data.json +++ b/web/src/locales/vi/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "Đây là trang web giới thiệu chỉ có chức năng đọc!", "Timestamp": "Timestamp", "Tokens": "Mã thông báo", + "Transactions": "Transactions", "Type": "Type", "Type - Tooltip": "Type - Tooltip", "URL": "URL", @@ -1031,6 +1032,13 @@ "Token type": "Loại mã thông báo", "Token type - Tooltip": "Token type - Tooltip" }, + "transaction": { + "Amount": "Amount", + "Amount - Tooltip": "The amount of traded products", + "Edit Transaction": "Edit Transaction", + "New Transaction": "New Transaction", + "Tag - Tooltip": "The tag of the transaction" + }, "user": { "3rd-party logins": "Đăng nhập bên thứ ba", "3rd-party logins - Tooltip": "Đăng nhập xã hội liên kết bởi người dùng", diff --git a/web/src/locales/zh/data.json b/web/src/locales/zh/data.json index 2dc07df6..eeaed6f0 100644 --- a/web/src/locales/zh/data.json +++ b/web/src/locales/zh/data.json @@ -367,6 +367,7 @@ "This is a read-only demo site!": "这是一个只读演示站点!", "Timestamp": "时间", "Tokens": "令牌", + "Transactions": "交易", "Type": "类型", "Type - Tooltip": "类型", "URL": "链接", @@ -1031,6 +1032,13 @@ "Token type": "令牌类型", "Token type - Tooltip": "令牌类型" }, + "transaction": { + "Amount": "数量", + "Amount - Tooltip": "交易产品的数量", + "Edit Transaction": "编辑交易", + "New Transaction": "添加交易", + "Tag - Tooltip": "交易的标签" + }, "user": { "3rd-party logins": "第三方登录", "3rd-party logins - Tooltip": "用户所绑定的社会化登录",