Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/candidate-9.2.x'
Browse files Browse the repository at this point in the history
Signed-off-by: Gordon Smith <[email protected]>
  • Loading branch information
GordonSmith committed Sep 7, 2023
2 parents e9e7cce + 5c0b67f commit 0d14493
Show file tree
Hide file tree
Showing 32 changed files with 1,425 additions and 390 deletions.
2 changes: 1 addition & 1 deletion common/thorhelper/roxiehelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2766,7 +2766,7 @@ StringBuffer & expandLogicalFilename(StringBuffer & logicalName, const char * fn
CDfsLogicalFileName dlfn;
dlfn.setAllowWild(true);
dlfn.setAllowTrailingEmptyScope(true);
dlfn.set(fname);
dlfn.set(fname+1);
logicalName.append(dlfn.get(ignoreForeignPrefix));
}
else if (resolveLocally)
Expand Down
89 changes: 56 additions & 33 deletions esp/src/src-react/components/DFUWorkunits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import * as Utility from "src/Utility";
import { QuerySortItem } from "src/store/Store";
import nlsHPCC from "src/nlsHPCC";
import { useConfirm } from "../hooks/confirm";
import { useFluentPagedGrid } from "../hooks/grid";
import { useMyAccount } from "../hooks/user";
import { HolyGrail } from "../layouts/HolyGrail";
import { pushParams } from "../util/history";
import { FluentPagedGrid, FluentPagedFooter, useCopyButtons, useFluentStoreState } from "./controls/Grid";
import { Filter } from "./forms/Filter";
import { Fields } from "./forms/Fields";
import { ShortVerticalDivider } from "./Common";
Expand Down Expand Up @@ -56,6 +56,7 @@ interface DFUWorkunitsProps {
filter?: { [id: string]: any };
sort?: QuerySortItem;
store?: any;
page?: number;
}

const emptyFilter = {};
Expand All @@ -64,14 +65,21 @@ const defaultSort = { attribute: "Wuid", descending: true };
export const DFUWorkunits: React.FunctionComponent<DFUWorkunitsProps> = ({
filter = emptyFilter,
sort = defaultSort,
store
store,
page
}) => {

const hasFilter = React.useMemo(() => Object.keys(filter).length > 0, [filter]);

const [showFilter, setShowFilter] = React.useState(false);
const { currentUser } = useMyAccount();
const [uiState, setUIState] = React.useState({ ...defaultUIState });
const {
selection, setSelection,
pageNum, setPageNum,
pageSize, setPageSize,
total, setTotal,
refreshTable } = useFluentStoreState({ page });

// Grid ---
const gridStore = React.useMemo(() => {
Expand All @@ -82,13 +90,8 @@ export const DFUWorkunits: React.FunctionComponent<DFUWorkunitsProps> = ({
return formatQuery(filter);
}, [filter]);

const { Grid, GridPagination, selection, refreshTable, copyButtons } = useFluentPagedGrid({
persistID: "dfuworkunits",
store: gridStore,
query,
sort,
filename: "dfuworkunits",
columns: {
const columns = React.useMemo(() => {
return {
col1: selector({
width: 27,
selectorType: "checkbox"
Expand All @@ -97,76 +100,76 @@ export const DFUWorkunits: React.FunctionComponent<DFUWorkunitsProps> = ({
headerIcon: "LockSolid",
width: 18,
sortable: false,
formatter: React.useCallback(function (_protected) {
formatter: (_protected) => {
if (_protected === true) {
return <Icon iconName="LockSolid" />;
}
return "";
}, [])
}
},
ID: {
label: nlsHPCC.ID,
width: 130,
formatter: React.useCallback(function (ID, idx) {
formatter: (ID, idx) => {
const wu = ESPDFUWorkunit.Get(ID);
return <>
<Image src={wu.getStateImage()} styles={{ root: { minWidth: "16px" } }} />
&nbsp;
<Link href={`#/dfuworkunits/${ID}`}>{ID}</Link>
</>;
}, [])
}
},
Command: {
label: nlsHPCC.Type,
width: 110,
formatter: React.useCallback(function (command) {
formatter: (command) => {
if (command in FileSpray.CommandMessages) {
return FileSpray.CommandMessages[command];
}
return "Unknown";
}, [])
}
},
User: { label: nlsHPCC.Owner, width: 90 },
JobName: { label: nlsHPCC.JobName, width: 220 },
ClusterName: { label: nlsHPCC.Cluster, width: 70 },
StateMessage: { label: nlsHPCC.State, width: 70 },
PCTDone: {
label: nlsHPCC.PctComplete, width: 80, sortable: true,
formatter: React.useCallback(function (value, row) {
formatter: (value, row) => {
return Utility.valueCleanUp(row.PercentDone);
}, [])
}
},
TimeStarted: { label: nlsHPCC.TimeStarted, width: 100, sortable: true },
TimeStopped: { label: nlsHPCC.TimeStopped, width: 100, sortable: true },
KbPerSec: {
label: nlsHPCC.TransferRate, width: 90,
formatter: React.useCallback(function (value, row) {
formatter: (value, row) => {
return Utility.convertedSize(row.KbPerSec * 1024) + " / sec";
}, [])
}
},
KbPerSecAve: { // KbPerSecAve seems to never be different than KbPerSec, see HPCC-29894
label: nlsHPCC.TransferRateAvg, width: 90,
formatter: React.useCallback(function (value, row) {
formatter: (value, row) => {
return Utility.convertedSize(row.KbPerSecAve * 1024) + " / sec";
}, [])
}
}
}
});
};
}, []);

const [DeleteConfirm, setShowDeleteConfirm] = useConfirm({
title: nlsHPCC.Delete,
message: nlsHPCC.DeleteSelectedWorkunits,
items: selection.map(s => s.Wuid),
onSubmit: React.useCallback(() => {
FileSpray.DFUWorkunitsAction(selection, nlsHPCC.Delete).then(() => refreshTable(true));
FileSpray.DFUWorkunitsAction(selection, nlsHPCC.Delete).then(() => refreshTable.call(true));
}, [refreshTable, selection])
});

// Command Bar ---
const buttons = React.useMemo((): ICommandBarItemProps[] => [
{
key: "refresh", text: nlsHPCC.Refresh, iconProps: { iconName: "Refresh" },
onClick: () => refreshTable()
onClick: () => refreshTable.call()
},
{ key: "divider_1", itemType: ContextualMenuItemType.Divider, onRender: () => <ShortVerticalDivider /> },
{
Expand All @@ -193,11 +196,11 @@ export const DFUWorkunits: React.FunctionComponent<DFUWorkunitsProps> = ({
{ key: "divider_3", itemType: ContextualMenuItemType.Divider, onRender: () => <ShortVerticalDivider /> },
{
key: "protect", text: nlsHPCC.Protect, disabled: !uiState.hasNotProtected,
onClick: () => { FileSpray.DFUWorkunitsAction(selection, "Protect").then(() => refreshTable()); }
onClick: () => { FileSpray.DFUWorkunitsAction(selection, "Protect").then(() => refreshTable.call()); }
},
{
key: "unprotect", text: nlsHPCC.Unprotect, disabled: !uiState.hasProtected,
onClick: () => { FileSpray.DFUWorkunitsAction(selection, "Unprotect").then(() => refreshTable()); }
onClick: () => { FileSpray.DFUWorkunitsAction(selection, "Unprotect").then(() => refreshTable.call()); }
},
{ key: "divider_4", itemType: ContextualMenuItemType.Divider, onRender: () => <ShortVerticalDivider /> },
{
Expand All @@ -207,18 +210,20 @@ export const DFUWorkunits: React.FunctionComponent<DFUWorkunitsProps> = ({
}
},
{
key: "mine", text: nlsHPCC.Mine, disabled: !currentUser?.username, iconProps: { iconName: "Contact" }, canCheck: true, checked: filter.Owner === currentUser.username,
key: "mine", text: nlsHPCC.Mine, disabled: !currentUser?.username, iconProps: { iconName: "Contact" }, canCheck: true, checked: filter["Owner"] === currentUser.username,
onClick: () => {
if (filter.Owner === currentUser.username) {
filter.Owner = "";
if (filter["Owner"] === currentUser.username) {
filter["Owner"] = "";
} else {
filter.Owner = currentUser.username;
filter["Owner"] = currentUser.username;
}
pushParams(filter);
}
},
], [currentUser, filter, hasFilter, refreshTable, selection, setShowDeleteConfirm, store, uiState.hasNotProtected, uiState.hasProtected, uiState.hasSelection]);

const copyButtons = useCopyButtons(columns, selection, "dfuworkunits");

// Filter ---
const filterFields: Fields = {};
for (const field in FilterFields) {
Expand Down Expand Up @@ -252,14 +257,32 @@ export const DFUWorkunits: React.FunctionComponent<DFUWorkunitsProps> = ({
<SizeMe monitorHeight>{({ size }) =>
<div style={{ width: "100%", height: "100%" }}>
<div style={{ position: "absolute", width: "100%", height: `${size.height}px` }}>
<Grid height={`${size.height}px`} />
<FluentPagedGrid
store={gridStore}
query={query}
sort={sort}
pageNum={pageNum}
pageSize={pageSize}
total={total}
columns={columns}
height={`${size.height}px`}
setSelection={setSelection}
setTotal={setTotal}
refresh={refreshTable}
></FluentPagedGrid>
</div>
</div>
}</SizeMe>
<Filter showFilter={showFilter} setShowFilter={setShowFilter} filterFields={filterFields} onApply={pushParams} />
<DeleteConfirm />
</>
}
footer={<GridPagination />}
footer={<FluentPagedFooter
persistID={"dfuworkunits"}
pageNum={pageNum}
setPageNum={setPageNum}
setPageSize={setPageSize}
total={total}
></FluentPagedFooter>}
/>;
};
56 changes: 38 additions & 18 deletions esp/src/src-react/components/EventScheduler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { CreateEventScheduleStore, EventScheduleStore } from "src/WsWorkunits";
import nlsHPCC from "src/nlsHPCC";
import * as WsWorkunits from "src/WsWorkunits";
import { useConfirm } from "../hooks/confirm";
import { useFluentPagedGrid } from "../hooks/grid";
import { HolyGrail } from "../layouts/HolyGrail";
import { FluentPagedGrid, FluentPagedFooter, useCopyButtons, useFluentStoreState } from "./controls/Grid";
import { pushParams } from "../util/history";
import { Fields } from "./forms/Fields";
import { Filter } from "./forms/Filter";
Expand Down Expand Up @@ -54,6 +54,12 @@ export const EventScheduler: React.FunctionComponent<EventSchedulerProps> = ({
const [showFilter, setShowFilter] = React.useState(false);
const [showPushEvent, setShowPushEvent] = React.useState(false);
const { currentUser } = useMyAccount();
const {
selection, setSelection,
pageNum, setPageNum,
pageSize, setPageSize,
total, setTotal,
refreshTable } = useFluentStoreState({ page });

// Grid ---
const query = React.useMemo(() => {
Expand All @@ -64,40 +70,36 @@ export const EventScheduler: React.FunctionComponent<EventSchedulerProps> = ({
return store ? store : CreateEventScheduleStore({});
}, [store]);

const { Grid, GridPagination, selection, refreshTable } = useFluentPagedGrid({
persistID: "events",
store: gridStore,
query,
sort,
pageNum: page,
filename: "events",
columns: {
const columns = React.useMemo(() => {
return {
col1: {
width: 16,
selectorType: "checkbox"
},
Wuid: {
label: nlsHPCC.Workunit, width: 120,
formatter: React.useCallback(function (Wuid, row) {
formatter: (Wuid, row) => {
return <Link href={`#/workunits/${Wuid}`}>{Wuid}</Link>;
}, [])
}
},
Cluster: { label: nlsHPCC.Cluster, width: 100 },
JobName: { label: nlsHPCC.JobName, width: 160 },
EventName: { label: nlsHPCC.EventName, width: 120 },
EventText: { label: nlsHPCC.EventText, width: 120 },
Owner: { label: nlsHPCC.Owner, width: 80 },
State: { label: nlsHPCC.State, width: 60 }
}
});
};
}, []);

const copyButtons = useCopyButtons(columns, selection, "events");

const [DescheduleConfirm, setShowDescheduleConfirm] = useConfirm({
title: nlsHPCC.Deschedule,
message: nlsHPCC.DescheduleSelectedWorkunits,
items: selection.map(s => s.Wuid),
onSubmit: () => {
WsWorkunits.WUAction(selection, "Deschedule").then(function (response) {
refreshTable(true);
refreshTable.call(true);
}).catch(err => logger.error(err));
}
});
Expand All @@ -112,7 +114,7 @@ export const EventScheduler: React.FunctionComponent<EventSchedulerProps> = ({
const buttons = React.useMemo((): ICommandBarItemProps[] => [
{
key: "refresh", text: nlsHPCC.Refresh, iconProps: { iconName: "Refresh" },
onClick: () => refreshTable()
onClick: () => refreshTable.call()
},
{ key: "divider_1", itemType: ContextualMenuItemType.Divider, onRender: () => <ShortVerticalDivider /> },
{
Expand Down Expand Up @@ -155,13 +157,25 @@ export const EventScheduler: React.FunctionComponent<EventSchedulerProps> = ({
], [currentUser, filter, hasFilter, refreshTable, selection, setShowDescheduleConfirm, store]);

return <HolyGrail
header={<CommandBar items={buttons} />}
header={<CommandBar items={buttons} farItems={copyButtons} />}
main={
<>
<SizeMe monitorHeight>{({ size }) =>
<div style={{ width: "100%", height: "100%" }}>
<div style={{ position: "absolute", width: "100%", height: `${size.height}px` }}>
<Grid height={`${size.height}px`} />
<FluentPagedGrid
store={gridStore}
query={query}
sort={sort}
pageNum={pageNum}
pageSize={pageSize}
total={total}
columns={columns}
height={`${size.height}px`}
setSelection={setSelection}
setTotal={setTotal}
refresh={refreshTable}
></FluentPagedGrid>
</div>
</div>
}</SizeMe>
Expand All @@ -170,7 +184,13 @@ export const EventScheduler: React.FunctionComponent<EventSchedulerProps> = ({
<PushEventForm showForm={showPushEvent} setShowForm={setShowPushEvent} />
</>
}
footer={<GridPagination />}
footer={<FluentPagedFooter
persistID={"events"}
pageNum={pageNum}
setPageNum={setPageNum}
setPageSize={setPageSize}
total={total}
></FluentPagedFooter>}
footerStyles={{}}
/>;
};
Loading

0 comments on commit 0d14493

Please sign in to comment.