mirror of
https://github.com/garethgeorge/backrest.git
synced 2026-08-27 19:36:29 +00:00
fix: UI refresh timing bugs
This commit is contained in:
@@ -40,7 +40,7 @@ export const ActivityBar = () => {
|
||||
return () => {
|
||||
unsubscribeFromOperations(callback);
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
const details = activeOperations.map((op) => {
|
||||
return {
|
||||
|
||||
@@ -71,7 +71,7 @@ export const OperationList = ({
|
||||
setBackups(backups);
|
||||
},
|
||||
100,
|
||||
{ leading: true, trailing: true }
|
||||
{ trailing: true }
|
||||
)
|
||||
);
|
||||
|
||||
@@ -108,11 +108,11 @@ export const OperationList = ({
|
||||
itemLayout="horizontal"
|
||||
size="small"
|
||||
dataSource={operations}
|
||||
renderItem={(op) => {
|
||||
renderItem={(op, index) => {
|
||||
return (
|
||||
<OperationRow
|
||||
alertApi={alertApi!}
|
||||
key={op.id}
|
||||
key={op.id + "-" + index}
|
||||
operation={op}
|
||||
showPlan={showPlan || false}
|
||||
/>
|
||||
|
||||
@@ -329,7 +329,7 @@ export const OperationRow = ({
|
||||
children.push(body);
|
||||
|
||||
return (
|
||||
<List.Item>
|
||||
<List.Item key={operation.id}>
|
||||
<List.Item.Meta title={title} avatar={avatar} description={children} />
|
||||
</List.Item>
|
||||
);
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
BackupInfoCollector,
|
||||
getOperations,
|
||||
subscribeToOperations,
|
||||
unsubscribeFromOperations,
|
||||
} from "../state/oplog";
|
||||
import { MAX_OPERATION_HISTORY } from "../constants";
|
||||
import { GetOperationsRequest, OpSelector } from "../../gen/ts/v1/service_pb";
|
||||
@@ -36,38 +37,42 @@ const StatsPanel = ({ repoId }: { repoId: string }) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const refreshOperations = _.debounce(() => {
|
||||
const backupCollector = new BackupInfoCollector((op) => {
|
||||
return (
|
||||
op.status === OperationStatus.STATUS_SUCCESS &&
|
||||
op.op.case === "operationStats" &&
|
||||
!!op.op.value.stats
|
||||
);
|
||||
});
|
||||
|
||||
getOperations(
|
||||
new GetOperationsRequest({
|
||||
selector: new OpSelector({
|
||||
repoId: repoId,
|
||||
}),
|
||||
lastN: BigInt(MAX_OPERATION_HISTORY),
|
||||
})
|
||||
)
|
||||
.then((ops) => {
|
||||
backupCollector.bulkAddOperations(ops);
|
||||
|
||||
const operations = backupCollector
|
||||
.getAll()
|
||||
.flatMap((b) => b.operations);
|
||||
operations.sort((a, b) => {
|
||||
return Number(b.unixTimeEndMs - a.unixTimeEndMs);
|
||||
});
|
||||
setOperations(operations);
|
||||
})
|
||||
.catch((e) => {
|
||||
alertApi!.error("Failed to fetch operations: " + e.message);
|
||||
const refreshOperations = _.debounce(
|
||||
() => {
|
||||
const backupCollector = new BackupInfoCollector((op) => {
|
||||
return (
|
||||
op.status === OperationStatus.STATUS_SUCCESS &&
|
||||
op.op.case === "operationStats" &&
|
||||
!!op.op.value.stats
|
||||
);
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
getOperations(
|
||||
new GetOperationsRequest({
|
||||
selector: new OpSelector({
|
||||
repoId: repoId,
|
||||
}),
|
||||
lastN: BigInt(MAX_OPERATION_HISTORY),
|
||||
})
|
||||
)
|
||||
.then((ops) => {
|
||||
backupCollector.bulkAddOperations(ops);
|
||||
|
||||
const operations = backupCollector
|
||||
.getAll()
|
||||
.flatMap((b) => b.operations);
|
||||
operations.sort((a, b) => {
|
||||
return Number(b.unixTimeEndMs - a.unixTimeEndMs);
|
||||
});
|
||||
setOperations(() => operations);
|
||||
})
|
||||
.catch((e) => {
|
||||
alertApi!.error("Failed to fetch operations: " + e.message);
|
||||
});
|
||||
},
|
||||
100,
|
||||
{ trailing: true }
|
||||
);
|
||||
|
||||
refreshOperations();
|
||||
|
||||
@@ -82,7 +87,9 @@ const StatsPanel = ({ repoId }: { repoId: string }) => {
|
||||
|
||||
subscribeToOperations(handler);
|
||||
|
||||
return () => {}; // cleanup
|
||||
return () => {
|
||||
unsubscribeFromOperations(handler);
|
||||
};
|
||||
}, [repoId]);
|
||||
|
||||
if (operations.length === 0) {
|
||||
@@ -108,9 +115,6 @@ const StatsPanel = ({ repoId }: { repoId: string }) => {
|
||||
};
|
||||
});
|
||||
|
||||
const minTime = Math.min(...dataset.map((d) => d.time));
|
||||
const maxTime = Math.max(...dataset.map((d) => d.time));
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row>
|
||||
|
||||
@@ -45,6 +45,7 @@ export const subscribeToOperations = (
|
||||
callback: (event: OperationEvent) => void,
|
||||
) => {
|
||||
subscribers.push(callback);
|
||||
console.log("subscribed to operations, subscriber count: ", subscribers.length);
|
||||
};
|
||||
|
||||
export const unsubscribeFromOperations = (
|
||||
@@ -55,6 +56,7 @@ export const unsubscribeFromOperations = (
|
||||
subscribers[index] = subscribers[subscribers.length - 1];
|
||||
subscribers.pop();
|
||||
}
|
||||
console.log("unsubscribed from operations, subscriber count: ", subscribers.length);
|
||||
};
|
||||
|
||||
export const getStatusForSelector = async (sel: OpSelector) => {
|
||||
|
||||
@@ -64,28 +64,30 @@ export const GettingStartedGuide = () => {
|
||||
configured either at the plan or repo level.
|
||||
</li>
|
||||
</ul>
|
||||
<Divider orientation="left">Config View</Divider>
|
||||
{isDevBuild && (
|
||||
<Collapse
|
||||
size="small"
|
||||
items={[
|
||||
{
|
||||
key: "1",
|
||||
label: "Config JSON hidden for security",
|
||||
children: config ? (
|
||||
<Typography>
|
||||
<pre>
|
||||
{config.toJsonString({
|
||||
prettySpaces: 2,
|
||||
})}
|
||||
</pre>
|
||||
</Typography>
|
||||
) : (
|
||||
<Spin />
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<>
|
||||
<Divider orientation="left">Config View</Divider>
|
||||
<Collapse
|
||||
size="small"
|
||||
items={[
|
||||
{
|
||||
key: "1",
|
||||
label: "Config JSON hidden for security",
|
||||
children: config ? (
|
||||
<Typography>
|
||||
<pre>
|
||||
{config.toJsonString({
|
||||
prettySpaces: 2,
|
||||
})}
|
||||
</pre>
|
||||
</Typography>
|
||||
) : (
|
||||
<Spin />
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Typography.Text>
|
||||
</>
|
||||
|
||||
@@ -17,12 +17,12 @@ export const LoginModal = () => {
|
||||
new LoginRequest({
|
||||
username: "default",
|
||||
password: "password",
|
||||
}),
|
||||
})
|
||||
)
|
||||
.then((loginResponse) => {
|
||||
alertApi.success(
|
||||
"No users configured yet, logged in with default credentials",
|
||||
5,
|
||||
5
|
||||
);
|
||||
setAuthToken(loginResponse.token);
|
||||
setTimeout(() => {
|
||||
@@ -30,7 +30,7 @@ export const LoginModal = () => {
|
||||
}, 500);
|
||||
})
|
||||
.catch((e) => {});
|
||||
});
|
||||
}, []);
|
||||
|
||||
const onFinish = async (values: any) => {
|
||||
const loginReq = new LoginRequest({
|
||||
|
||||
Reference in New Issue
Block a user