Skip to content

Commit

Permalink
Update UI to use the exports API
Browse files Browse the repository at this point in the history
  • Loading branch information
haoming29 committed Apr 3, 2024
1 parent bc6e5ea commit c53c48b
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 31 deletions.
9 changes: 8 additions & 1 deletion origin/origin_ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,27 @@ import (
"net/http"

"github.com/gin-gonic/gin"
"github.com/pelicanplatform/pelican/param"
"github.com/pelicanplatform/pelican/server_structs"
"github.com/pelicanplatform/pelican/server_utils"
"github.com/pelicanplatform/pelican/web_ui"
"github.com/sirupsen/logrus"
)

type exportsRes struct {
Type string `json:"type"` // either "posix" or "s3"
Exports *[]server_utils.OriginExports `json:"exports"`
}

func handleExports(ctx *gin.Context) {
storageType := param.Origin_StorageType.GetString()
exports, err := server_utils.GetOriginExports()
if err != nil {
logrus.Errorf("Failed to get the origin exports: %v", err)
ctx.JSON(http.StatusInternalServerError, server_structs.SimpleApiResp{Status: server_structs.RespFailed, Msg: "Server encountered error when getting the origin exports: " + err.Error()})
return
}
ctx.JSON(http.StatusOK, exports)
ctx.JSON(http.StatusOK, exportsRes{Type: storageType, Exports: exports})
}

func RegisterOriginWebAPI(engine *gin.Engine) {
Expand Down
18 changes: 14 additions & 4 deletions web_ui/frontend/app/api/docs/pelican-swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,18 @@ definitions:
capabilities:
type: object
$ref: "#/definitions/OriginExportCapabilities"
OriginExportRes:
type: object
properties:
type:
type: string
example: "posix"
description: "The storage type of the origin server. Is either \"posix\" or \"s3\""
exports:
type: array
items:
$ref: "#/definitions/OriginExport"
minItems: 0

tags:
- name: auth
Expand Down Expand Up @@ -1583,10 +1595,8 @@ paths:
"200":
description: OK
schema:
type: array
items:
$ref: "#/definitions/OriginExport"
minItems: 0
type: object
$ref: "#/definitions/OriginExportRes"
"401":
description: Authentication required to perform this action
schema:
Expand Down
53 changes: 27 additions & 26 deletions web_ui/frontend/components/DataExportTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@ import {Table, TableCell, TableBody, TableContainer, TableHead, TableRow, Paper,
import React, {FunctionComponent, ReactElement, useEffect, useMemo, useRef, useState} from "react";
import {Skeleton} from "@mui/material";



interface Record {
[key: string]: string | number | boolean | null
interface Capabilities {
PublicReads: boolean;
Reads: boolean;
Writes: boolean;
Listings: boolean;
DirectReads: boolean;
}

interface ExportEntry {
storage_prefix: string;
federation_prefix: string;
capabilities: Capabilities;
}

interface ExportData extends Record {
"Type": string
"Local Path": string
"Namespace Prefix": string
interface ExportRes {
type: string;
exports: ExportEntry[];
}

export const TableCellOverflow: FunctionComponent<any> = ({ children, ...props }) => {
Expand Down Expand Up @@ -39,23 +46,23 @@ export const TableCellOverflow: FunctionComponent<any> = ({ children, ...props }
)
}

export const RecordTable = ({ data }: { data: Record[] }): ReactElement => {
export const RecordTable = ({ data }: { data: ExportRes }): ReactElement => {
return (
<TableContainer>
<Table sx={{tableLayout: "fixed"}}>
<TableHead>
<TableRow>
{Object.keys(data[0]).map((key, index) => (
<TableCell key={index} sx={{width: index == 0 ? "20%" : "40%"}}>{key}</TableCell>
))}
<TableCell sx={{width: "20%"}}>Type</TableCell>
<TableCell sx={{width: "40%"}}>Local Path</TableCell>
<TableCell sx={{width: "40%"}}>Federation Path</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map((record, index) => (
<TableRow key={index}>
{Object.values(record).map((value, index) => (
<TableCellOverflow key={index} sx={{width: index == 0 ? "20%" : "40%"}}>{value == null ? "NULL" : value}</TableCellOverflow>
))}
{data?.exports.map((record, index) => (
<TableRow key={record?.federation_prefix}>
<TableCellOverflow key={record.federation_prefix} sx={{width: "20%"}}>{data.type == null ? "NULL" : data.type.toUpperCase()}</TableCellOverflow>
<TableCellOverflow key={record.federation_prefix} sx={{width: "40%"}}>{record?.storage_prefix == null ? "NULL" : record?.storage_prefix}</TableCellOverflow>
<TableCellOverflow key={record.federation_prefix} sx={{width: "40%"}}>{record?.federation_prefix == null ? "NULL" : record?.federation_prefix}</TableCellOverflow>
</TableRow>
))}
</TableBody>
Expand All @@ -67,21 +74,15 @@ export const RecordTable = ({ data }: { data: Record[] }): ReactElement => {

export const DataExportTable = () => {

const [data, setData] = useState<ExportData[] | undefined>(undefined);
const [data, setData] = useState<ExportRes | undefined>(undefined);
const [error, setError] = useState<string | undefined>(undefined);


const getData = async () => {
let response = await fetch("/api/v1.0/config")
let response = await fetch("/api/v1.0/origin_ui/exports")
if (response.ok) {
const responseData = await response.json()

setData([{
"Type": "POSIX",
"Local Path": ["", undefined].includes(responseData?.Xrootd?.Mount?.Value) ? "NULL" : responseData?.Xrootd?.Mount?.Value,
"Namespace Prefix": ["", undefined].includes(responseData?.Origin?.NamespacePrefix?.Value) ? "NULL" : responseData?.Origin?.NamespacePrefix?.Value
}])

setData(responseData)
} else {
setError("Failed to fetch config, response status: " + response.status)
}
Expand Down

0 comments on commit c53c48b

Please sign in to comment.