123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- import React from "react";
- import {Link} from "react-router-dom";
- import {Button, Col, List, Row, Table, Tooltip} from "antd";
- import moment from "moment";
- import * as Setting from "./Setting";
- import * as ProductBackend from "./backend/ProductBackend";
- import i18next from "i18next";
- import BaseListPage from "./BaseListPage";
- import {EditOutlined} from "@ant-design/icons";
- import PopconfirmModal from "./common/modal/PopconfirmModal";
- class ProductListPage extends BaseListPage {
- newProduct() {
- const randomName = Setting.getRandomName();
- return {
- owner: "admin",
- name: `product_${randomName}`,
- createdTime: moment().format(),
- displayName: `New Product - ${randomName}`,
- image: `${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`,
- tag: "Casdoor Summit 2022",
- currency: "USD",
- price: 300,
- quantity: 99,
- sold: 10,
- providers: [],
- state: "Published",
- };
- }
- addProduct() {
- const newProduct = this.newProduct();
- ProductBackend.addProduct(newProduct)
- .then((res) => {
- if (res.status === "ok") {
- this.props.history.push({pathname: `/products/${newProduct.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}`);
- });
- }
- deleteProduct(i) {
- ProductBackend.deleteProduct(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}`);
- });
- }
- renderTable(products) {
- const columns = [
- {
- title: i18next.t("general:Name"),
- dataIndex: "name",
- key: "name",
- width: "140px",
- fixed: "left",
- sorter: true,
- ...this.getColumnSearchProps("name"),
- render: (text, record, index) => {
- return (
- <Link to={`/products/${text}`}>
- {text}
- </Link>
- );
- },
- },
- {
- 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("general:Display name"),
- dataIndex: "displayName",
- key: "displayName",
- width: "170px",
- sorter: true,
- ...this.getColumnSearchProps("displayName"),
- },
- {
- title: i18next.t("product:Image"),
- dataIndex: "image",
- key: "image",
- width: "170px",
- render: (text, record, index) => {
- return (
- <a target="_blank" rel="noreferrer" href={text}>
- <img src={text} alt={text} width={150} />
- </a>
- );
- },
- },
- {
- title: i18next.t("user:Tag"),
- dataIndex: "tag",
- key: "tag",
- width: "160px",
- sorter: true,
- ...this.getColumnSearchProps("tag"),
- },
- {
- title: i18next.t("payment:Currency"),
- dataIndex: "currency",
- key: "currency",
- width: "120px",
- sorter: true,
- ...this.getColumnSearchProps("currency"),
- },
- {
- title: i18next.t("product:Price"),
- dataIndex: "price",
- key: "price",
- width: "120px",
- sorter: true,
- ...this.getColumnSearchProps("price"),
- },
- {
- title: i18next.t("product:Quantity"),
- dataIndex: "quantity",
- key: "quantity",
- width: "120px",
- sorter: true,
- ...this.getColumnSearchProps("quantity"),
- },
- {
- title: i18next.t("product:Sold"),
- dataIndex: "sold",
- key: "sold",
- width: "120px",
- sorter: true,
- ...this.getColumnSearchProps("sold"),
- },
- {
- title: i18next.t("general:State"),
- dataIndex: "state",
- key: "state",
- width: "120px",
- sorter: true,
- ...this.getColumnSearchProps("state"),
- },
- {
- title: i18next.t("product:Payment providers"),
- dataIndex: "providers",
- key: "providers",
- width: "500px",
- ...this.getColumnSearchProps("providers"),
- render: (text, record, index) => {
- const providers = text;
- if (providers.length === 0) {
- return `(${i18next.t("general:empty")})`;
- }
- const half = Math.floor((providers.length + 1) / 2);
- const getList = (providers) => {
- return (
- <List
- size="small"
- locale={{emptyText: " "}}
- dataSource={providers}
- renderItem={(providerName, i) => {
- return (
- <List.Item>
- <div style={{display: "inline"}}>
- <Tooltip placement="topLeft" title="Edit">
- <Button style={{marginRight: "5px"}} icon={<EditOutlined />} size="small" onClick={() => Setting.goToLinkSoft(this, `/providers/${providerName}`)} />
- </Tooltip>
- <Link to={`/providers/${providerName}`}>
- {providerName}
- </Link>
- </div>
- </List.Item>
- );
- }}
- />
- );
- };
- return (
- <div>
- <Row>
- <Col span={12}>
- {
- getList(providers.slice(0, half))
- }
- </Col>
- <Col span={12}>
- {
- getList(providers.slice(half))
- }
- </Col>
- </Row>
- </div>
- );
- },
- },
- {
- title: i18next.t("general:Action"),
- dataIndex: "",
- key: "op",
- width: "230px",
- fixed: (Setting.isMobile()) ? "false" : "right",
- render: (text, record, index) => {
- return (
- <div>
- <Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} onClick={() => this.props.history.push(`/products/${record.name}/buy`)}>{i18next.t("product:Buy")}</Button>
- <Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/products/${record.name}`)}>{i18next.t("general:Edit")}</Button>
- <PopconfirmModal
- title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
- onConfirm={() => this.deleteProduct(index)}
- >
- </PopconfirmModal>
- </div>
- );
- },
- },
- ];
- 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 (
- <div>
- <Table scroll={{x: "max-content"}} columns={columns} dataSource={products} rowKey="name" size="middle" bordered pagination={paginationProps}
- title={() => (
- <div>
- {i18next.t("general:Products")}
- <Button type="primary" size="small" onClick={this.addProduct.bind(this)}>{i18next.t("general:Add")}</Button>
- </div>
- )}
- loading={this.state.loading}
- onChange={this.handleTableChange}
- />
- </div>
- );
- }
- 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});
- ProductBackend.getProducts("", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
- .then((res) => {
- if (res.status === "ok") {
- this.setState({
- loading: false,
- data: res.data,
- pagination: {
- ...params.pagination,
- total: res.data2,
- },
- searchText: params.searchText,
- searchedColumn: params.searchedColumn,
- });
- } else {
- if (Setting.isResponseDenied(res)) {
- this.setState({
- loading: false,
- isAuthorized: false,
- });
- }
- }
- });
- };
- }
- export default ProductListPage;
|