github.com/minio/console@v1.4.1/web-app/src/screens/Console/Buckets/ListBuckets/Objects/ObjectDetails/FileVersionItem.tsx (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2022 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  
    17  import React from "react";
    18  import { DateTime } from "luxon";
    19  import styled from "styled-components";
    20  import get from "lodash/get";
    21  import { displayFileIconName } from "../ListObjects/utils";
    22  import {
    23    DownloadIcon,
    24    PreviewIcon,
    25    RecoverIcon,
    26    ShareIcon,
    27    IconButton,
    28    Tooltip,
    29    Grid,
    30    Checkbox,
    31  } from "mds";
    32  import { niceBytes } from "../../../../../../common/utils";
    33  import SpecificVersionPill from "./SpecificVersionPill";
    34  import { BucketObject } from "api/consoleApi";
    35  
    36  interface IFileVersionItem {
    37    fileName: string;
    38    versionInfo: BucketObject;
    39    index: number;
    40    isSelected?: boolean;
    41    checkable: boolean;
    42    isChecked: boolean;
    43    onCheck: (versionID: string) => void;
    44    onShare: (versionInfo: BucketObject) => void;
    45    onDownload: (versionInfo: BucketObject) => void;
    46    onRestore: (versionInfo: BucketObject) => void;
    47    onPreview: (versionInfo: BucketObject) => void;
    48    globalClick: (versionInfo: BucketObject) => void;
    49    key: any;
    50    style: any;
    51  }
    52  
    53  const FileVersionStyled = styled.div(({ theme }) => {
    54    return {
    55      "&:before": {
    56        content: "' '",
    57        display: "block",
    58        position: "absolute",
    59        width: "2px",
    60        height: "calc(100% + 2px)",
    61        backgroundColor: get(theme, "borderColor", "#F8F8F8"),
    62        left: "24px",
    63      },
    64      "& .mainFileVersionItem": {
    65        borderBottom: `${get(theme, "borderColor", "#F8F8F8")} 1px solid`,
    66        padding: "1rem 0",
    67        margin: "0 0.5rem 0 2.5rem",
    68        cursor: "pointer",
    69        "&.deleted": {
    70          color: "#868686",
    71        },
    72      },
    73      "& .intermediateLayer": {
    74        margin: "0 1.5rem 0 1.5rem",
    75        "&:hover, &.selected": {
    76          backgroundColor: get(theme, "boxBackground", "#F8F8F8"),
    77          "& > div": {
    78            borderBottomColor: get(theme, "boxBackground", "#F8F8F8"),
    79          },
    80        },
    81      },
    82      "& .versionContainer": {
    83        fontSize: 16,
    84        fontWeight: "bold",
    85        display: "flex",
    86        alignItems: "center",
    87        "& svg.min-icon": {
    88          width: 18,
    89          height: 18,
    90          minWidth: 18,
    91          minHeight: 18,
    92          marginRight: 10,
    93        },
    94      },
    95      "& .buttonContainer": {
    96        textAlign: "right",
    97        "& button": {
    98          marginLeft: "1.5rem",
    99        },
   100      },
   101      "& .versionID": {
   102        fontSize: "12px",
   103        margin: "2px 0",
   104        whiteSpace: "nowrap",
   105        textOverflow: "ellipsis",
   106        maxWidth: "95%",
   107        overflow: "hidden",
   108      },
   109      "& .versionData": {
   110        marginRight: "10px",
   111        fontSize: 12,
   112        color: "#868686",
   113      },
   114      "@media (max-width: 600px)": {
   115        "& .buttonContainer": {
   116          "& button": {
   117            marginLeft: "5px",
   118          },
   119        },
   120      },
   121      "@media (max-width: 799px)": {
   122        "&:before": {
   123          display: "none",
   124        },
   125        "& .mainFileVersionItem": {
   126          padding: "5px 0px",
   127          margin: 0,
   128        },
   129        "& .intermediateLayer": {
   130          margin: 0,
   131          "&:hover, &.selected": {
   132            backgroundColor: "transparent",
   133            "& > div": {
   134              borderBottomColor: get(theme, "boxBackground", "#F8F8F8"),
   135            },
   136          },
   137        },
   138        "& .versionContainer": {
   139          fontSize: 14,
   140          "& svg.min-icon": {
   141            display: "none",
   142          },
   143        },
   144        "& .versionData": {
   145          textOverflow: "ellipsis",
   146          maxWidth: "95%",
   147          overflow: "hidden",
   148          whiteSpace: "nowrap",
   149        },
   150        "& .collapsableInfo": {
   151          display: "flex",
   152          flexDirection: "column",
   153        },
   154        "& .versionItem": {
   155          display: "none",
   156        },
   157      },
   158    };
   159  });
   160  
   161  const FileVersionItem = ({
   162    fileName,
   163    versionInfo,
   164    isSelected,
   165    checkable,
   166    isChecked,
   167    onCheck,
   168    onShare,
   169    onDownload,
   170    onRestore,
   171    onPreview,
   172    globalClick,
   173    index,
   174    key,
   175    style,
   176  }: IFileVersionItem) => {
   177    const disableButtons = versionInfo.is_delete_marker;
   178  
   179    const versionItemButtons = [
   180      {
   181        icon: <PreviewIcon />,
   182        action: onPreview,
   183        tooltip: "Preview",
   184      },
   185      {
   186        icon: <DownloadIcon />,
   187        action: onDownload,
   188        tooltip: "Download this version",
   189      },
   190      {
   191        icon: <ShareIcon />,
   192        action: onShare,
   193        tooltip: "Share this version",
   194      },
   195      {
   196        icon: <RecoverIcon />,
   197        action: onRestore,
   198        tooltip: "Restore this version",
   199      },
   200    ];
   201  
   202    let pill: "deleted" | "current" | "null" | null = null;
   203  
   204    if (versionInfo.is_delete_marker) {
   205      pill = "deleted";
   206    } else if (versionInfo.is_latest) {
   207      pill = "current";
   208    } else if (versionInfo.version_id === "null") {
   209      pill = "null";
   210    }
   211  
   212    let lastModified = DateTime.now();
   213  
   214    if (versionInfo.last_modified) {
   215      lastModified = DateTime.fromISO(
   216        versionInfo.last_modified,
   217      ) as DateTime<true>;
   218    }
   219  
   220    return (
   221      <FileVersionStyled>
   222        <Grid
   223          container
   224          className={"ctrItem"}
   225          onClick={() => {
   226            globalClick(versionInfo);
   227          }}
   228          key={key}
   229          style={style}
   230        >
   231          <Grid
   232            item
   233            xs={12}
   234            className={`${"intermediateLayer"} ${isSelected ? "selected" : ""}`}
   235          >
   236            <Grid
   237              item
   238              xs
   239              className={`mainFileVersionItem ${
   240                versionInfo.is_delete_marker ? "deleted" : ""
   241              }`}
   242            >
   243              <Grid item xs={12}>
   244                <Grid container>
   245                  <Grid item xs md={4} className={"versionContainer"}>
   246                    {checkable && (
   247                      <Checkbox
   248                        checked={isChecked}
   249                        id={`select-${versionInfo.version_id}`}
   250                        name={`select-${versionInfo.version_id}`}
   251                        onChange={(e) => {
   252                          e.stopPropagation();
   253                          onCheck(versionInfo.version_id || "");
   254                        }}
   255                        value={versionInfo.version_id || ""}
   256                        disabled={versionInfo.is_delete_marker}
   257                        sx={{
   258                          width: "initial",
   259                        }}
   260                      />
   261                    )}
   262                    {displayFileIconName(fileName, true)} v{index.toString()}
   263                    <span className={"versionItem"}>
   264                      {pill && <SpecificVersionPill type={pill} />}
   265                    </span>
   266                  </Grid>
   267                  <Grid item xs={10} md={8} className={"buttonContainer"}>
   268                    {versionItemButtons.map((button, index) => {
   269                      return (
   270                        <Tooltip
   271                          tooltip={button.tooltip}
   272                          key={`version-action-${
   273                            button.tooltip
   274                          }-${index.toString()}`}
   275                        >
   276                          <IconButton
   277                            size={"small"}
   278                            id={`version-action-${
   279                              button.tooltip
   280                            }-${index.toString()}`}
   281                            className={`${"spacing"} ${
   282                              disableButtons ? "buttonDisabled" : ""
   283                            }`}
   284                            disabled={disableButtons}
   285                            onClick={(e) => {
   286                              e.stopPropagation();
   287                              if (!disableButtons) {
   288                                button.action(versionInfo);
   289                              } else {
   290                                e.preventDefault();
   291                              }
   292                            }}
   293                            sx={{
   294                              backgroundColor: "#F8F8F8",
   295                              borderRadius: "100%",
   296                              width: "28px",
   297                              height: "28px",
   298                              padding: "5px",
   299                              "& .min-icon": {
   300                                width: "14px",
   301                                height: "14px",
   302                              },
   303                            }}
   304                          >
   305                            {button.icon}
   306                          </IconButton>
   307                        </Tooltip>
   308                      );
   309                    })}
   310                  </Grid>
   311                </Grid>
   312              </Grid>
   313              <Grid item xs={12} className={"versionID"}>
   314                {versionInfo.version_id !== "null" ? versionInfo.version_id : "-"}
   315              </Grid>
   316              <Grid item xs={12} className={"collapsableInfo"}>
   317                <span className={"versionData"}>
   318                  <strong>Last modified:</strong>{" "}
   319                  {lastModified.toFormat("ccc, LLL dd yyyy HH:mm:ss (ZZZZ)")}
   320                </span>
   321                <span className={"versionData"}>
   322                  <strong>Size:</strong> {niceBytes(`${versionInfo.size || "0"}`)}
   323                </span>
   324              </Grid>
   325            </Grid>
   326          </Grid>
   327        </Grid>
   328      </FileVersionStyled>
   329    );
   330  };
   331  
   332  export default FileVersionItem;