Files
pedwfrontend/components/admin/tabs/storage.js
T

382 lines
23 KiB
JavaScript

// components/admin/tabs/StorageTab.js
import { useState } from "react";
import Link from "next/link";
import { bytesToSize } from "../../../components/utils";
import { consoleLogger } from "../../../actions/core/logger";
import { formatBlobDates } from "../utils/adminHelper";
export default function StorageTab({ data, repCompleteCount }) {
const [showRepJson, setShowRepJson] = useState(true);
const [showTmpFile, setShowTmpFile] = useState(true);
const [listData, setListData] = useState(data);
const toggleAll = () => {
const newState = !(showRepJson || showTmpFile);
setShowRepJson(newState);
setShowTmpFile(newState);
};
const deleteRepItem = (containerID, caseID, repfile) => {
fetch("/api/admin/deleteblobrep", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
container: containerID,
casefolderID: caseID,
repfile
})
})
.then((response) => {
if (!response.ok) {
throw new Error("Unable to delete representation");
}
return response.json();
})
.then((data) => {
return data;
})
.then(() => {
fetch("/api/admin/getrepsblobproxy", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ container: containerID })
})
.then((response) => {
if (!response.ok) {
throw new Error(
"Unable to refresh representations"
);
}
return response.json();
})
.then((data) => {
setMyRepresentations(data);
setMyRepresentationsDetails(data);
})
.catch((error) => {
consoleLogger(error);
return null;
})
.then(() => {
setCurrentView({
"viewName": "My Representations",
"viewKey": "myRepresentations"
});
});
})
.catch((error) => {
consoleLogger(error);
});
};
return (
<div>
<h1>Storage Account Contents</h1>
{repCompleteCount > 0 && (
<p>Number of Orphaned Reps: {repCompleteCount}</p>
)}
{/* Toggle buttons */}
<div style={{ marginBottom: "0.2rem" }}>
<button
className="govuk-button govuk-button--secondary"
onClick={() => setShowRepJson(!showRepJson)}
>
{showRepJson ? "Hide Reps" : "Show Reps"}
</button>
<button
className="govuk-button govuk-button--secondary"
onClick={() => setShowTmpFile(!showTmpFile)}
style={{ marginLeft: "0.5rem" }}
>
{showTmpFile ? "Hide Temp Appeal" : "Show Temp Appeal"}
</button>
<button
className="govuk-button govuk-button--secondary"
onClick={toggleAll}
style={{ marginLeft: "0.5rem" }}
>
Show/Hide All
</button>
</div>
{/* Render users & containers */}
{listData.map((user) => (
<div key={user.id} className="govuk-grid-row">
{user.containers.map((c) => (
<div key={c.container} className="card">
<div className="card-body">
<h3>
{c.container} -{" "}
<Link
href={`/auth/signin2?email=${user.email}`}
>
{user.email}
</Link>
</h3>
{/* folders */}
{c.folders.map((folder) => (
<div
key={folder.folderPath}
style={
showRepJson && folder.hasRepJson
? { display: "block" }
: showTmpFile &&
folder.hasTmpFile
? { display: "block" }
: { display: "none" }
}
>
<h4>{folder.folderPath || "Root"}</h4>
{/* Buttons for TMP + Rep actions go here (same logic as before) */}
{folder.hasTmpFile && (
<>
<button
onClick={async () => {
if (
!confirm(
"Do you want to remove this unsubmitted appeal " +
folder.folderPath +
"?\n"
)
) {
return;
}
try {
const response =
await fetch(
"/api/admin/deleteblobcase",
{
method: "POST",
headers:
{
"Content-Type":
"application/json"
},
body: JSON.stringify(
{
container:
c.container,
casefolderID:
folder.folderPath
}
)
}
);
if (!response.ok) {
throw new Error(
"Unable to delete case"
);
}
alert(
"Temp case Deleted!"
);
window.location.reload();
} catch (error) {
consoleLogger(error);
}
}}
>
Delete this TMP appeal
</button>
</>
)}
{folder.hasRepJson && (
<div>
{" "}
<button
title={
"Do you want to delete rep"
}
className=" cardModuleRemoveCase govuk-link govuk-link--no-underline govuk-link--inverse "
onClick={() => {
confirm(
"Do you want tyo delete rep " +
folder.repJsonBlob.name.split(
"/"
)[0] +
"?\n"
) &&
(deleteRepItem(
c.container,
folder.repJsonBlob.name.split(
"/"
)[0],
folder.repJsonBlob.name.split(
"/"
)[1]
),
alert(
"Rep Deleted!"
),
window.location.reload());
}}
>
Delete Rep
</button>
{folder.repComplete && (
<button
onClick={async () => {
const response =
await fetch(
"/api/admin/editRepJson",
{
method: "POST",
headers:
{
"Content-Type":
"application/json"
},
body: JSON.stringify(
{
container:
c.container,
blobName:
folder
.repJsonBlob
.name
}
)
}
);
const result =
await response.json();
if (response.ok) {
(alert(
"repComplete removed!"
),
window.location.reload());
// Optionally refresh the page or update UI state here
} else {
alert(
"Error: " +
result.error
);
}
}}
>
Remove repComplete
</button>
)}
{folder.repComplete && (
<button
onClick={async () => {
if (
!confirm(
"Do you want resend the rep queue message " +
folder.repJsonBlob.name.split(
"/"
)[0] +
" --- " +
folder.repJsonBlob.name.split(
"/"
)[1]
)
) {
return;
}
try {
const response =
await fetch(
"/api/admin/createrepcompletemessage",
{
method: "POST",
headers:
{
"Content-Type":
"application/json"
},
body: JSON.stringify(
{
container:
c.container,
tempcaseref:
folder.repJsonBlob.name.split(
"/"
)[0],
repid: folder.repJsonBlob.name.split(
"/"
)[1]
}
)
}
);
if (!response.ok) {
throw new Error(
"Unable to recreate representation queue message"
);
}
alert(
"rep queue message sent!"
);
window.location.reload();
} catch (error) {
consoleLogger(
error
);
}
}}
>
Recreate Queue Message
</button>
)}
</div>
)}
<ul>
{folder.blobs.map((blob) => (
<li key={blob.name}>
<Link
scroll={false}
href={`/api/file/downloadblob?container=${
c.container
}&casefolderID=${
folder.folderPath
}&blobname=${blob.name.substring(
blob.name.lastIndexOf(
"/"
) + 1
)}&hash=${
blob.hashedfilepath
}`}
className="govuk-body govuk-!-font-size-14 govuk-link"
>
{blob.name} (
{bytesToSize(
blob.contentLength ||
blob.size
)}
)
</Link>{" "}
{blob.lastModified && (
<span className="govuk-!-font-size-14">
{/* {
blob.displayDate
} */}
{formatBlobDates(
blob
)}
</span>
)}
</li>
))}
</ul>
</div>
))}
</div>
</div>
))}
</div>
))}
</div>
);
}