diff --git a/origin/origin_ui.go b/origin/origin_ui.go index e661ac495..c1109843b 100644 --- a/origin/origin_ui.go +++ b/origin/origin_ui.go @@ -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) { diff --git a/web_ui/frontend/app/api/docs/pelican-swagger.yaml b/web_ui/frontend/app/api/docs/pelican-swagger.yaml index d2204eea9..18b4cad31 100644 --- a/web_ui/frontend/app/api/docs/pelican-swagger.yaml +++ b/web_ui/frontend/app/api/docs/pelican-swagger.yaml @@ -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 @@ -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: diff --git a/web_ui/frontend/components/DataExportTable.tsx b/web_ui/frontend/components/DataExportTable.tsx index 9b9a2f32c..b5ef9ff03 100644 --- a/web_ui/frontend/components/DataExportTable.tsx +++ b/web_ui/frontend/components/DataExportTable.tsx @@ -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 = ({ children, ...props }) => { @@ -39,23 +46,23 @@ export const TableCellOverflow: FunctionComponent = ({ children, ...props } ) } -export const RecordTable = ({ data }: { data: Record[] }): ReactElement => { +export const RecordTable = ({ data }: { data: ExportRes }): ReactElement => { return ( - {Object.keys(data[0]).map((key, index) => ( - {key} - ))} + Type + Local Path + Federation Path - {data.map((record, index) => ( - - {Object.values(record).map((value, index) => ( - {value == null ? "NULL" : value} - ))} + {data?.exports.map((record, index) => ( + + {data.type == null ? "NULL" : data.type.toUpperCase()} + {record?.storage_prefix == null ? "NULL" : record?.storage_prefix} + {record?.federation_prefix == null ? "NULL" : record?.federation_prefix} ))} @@ -67,21 +74,15 @@ export const RecordTable = ({ data }: { data: Record[] }): ReactElement => { export const DataExportTable = () => { - const [data, setData] = useState(undefined); + const [data, setData] = useState(undefined); const [error, setError] = useState(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) }