Skip to content

Commit 44a7a26

Browse files
Make commit author configurable
1 parent 75aa9a5 commit 44a7a26

File tree

5 files changed

+113
-11
lines changed

5 files changed

+113
-11
lines changed

web/main/authorStorage.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Store from "electron-store";
2+
3+
export type StoredAuthor = {
4+
name: string;
5+
email: string;
6+
};
7+
8+
const store = new Store<{ commitAuthor?: StoredAuthor }>({
9+
name: "commit-author",
10+
});
11+
12+
const AUTHOR_KEY = "commitAuthor";
13+
14+
export function getStoredAuthor(): StoredAuthor | null {
15+
return store.get(AUTHOR_KEY) ?? null;
16+
}
17+
18+
export function setStoredAuthor(author: StoredAuthor): void {
19+
store.set(AUTHOR_KEY, author);
20+
}

web/main/background.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { startServer } from "./doltServer";
1919
import { createWindow } from "./helpers/createWindow";
2020
import { initMenu } from "./helpers/menu";
2121
import { registerAgentIpcHandlers, cleanupAgent } from "./agent";
22+
import { getStoredAuthor, setStoredAuthor, StoredAuthor } from "./authorStorage";
2223
import {
2324
getErrorMessage,
2425
removeDoltServerFolder,
@@ -247,6 +248,13 @@ ipcMain.handle("get-headers", (event, arg) => {
247248
return headers;
248249
});
249250

251+
ipcMain.handle("get-commit-author", () => getStoredAuthor());
252+
253+
ipcMain.handle(
254+
"set-commit-author",
255+
(_, author: StoredAuthor) => setStoredAuthor(author),
256+
);
257+
250258
ipcMain.handle("api-config", async () => {
251259
const cfg = {
252260
graphqlApiUrl: process.env.GRAPHQLAPI_URL,

web/main/preload.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ const handler = {
108108
onLoginStarted: (callback: (requestId: string) => void) => {
109109
ipcRenderer.on("login-started", (_event, requestId) => callback(requestId));
110110
},
111+
// Commit author storage
112+
getCommitAuthor: async (): Promise<{
113+
name: string;
114+
email: string;
115+
} | null> => ipcRenderer.invoke("get-commit-author"),
116+
setCommitAuthor: async (author: { name: string; email: string }) =>
117+
ipcRenderer.invoke("set-commit-author", author),
118+
111119
startMcpServer: (config: McpServerConfig) =>
112120
ipcRenderer.send("start-mcp-server", config),
113121
stopMcpServer: () => ipcRenderer.send("stop-mcp-server"),

web/renderer/components/StatusWithOptions/CommitModal.tsx

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import HeaderUserCheckbox from "@components/HeaderUserCheckbox";
2-
import { FormModal, Textarea } from "@dolthub/react-components";
1+
import { FormInput, FormModal, Textarea } from "@dolthub/react-components";
2+
import { useEffectAsync } from "@dolthub/react-hooks";
33
import { Maybe } from "@dolthub/web-utils";
44
import { StatusFragment } from "@gen/graphql-types";
55
import useSqlBuilder from "@hooks/useSqlBuilder";
@@ -16,20 +16,50 @@ type Props = ModalProps & {
1616
status: StatusFragment[];
1717
};
1818

19+
const isElectron = process.env.NEXT_PUBLIC_FOR_ELECTRON === "true";
20+
1921
export default function CommitModal(props: Props) {
2022
const router = useRouter();
2123
const defaultMsg = getDefaultCommitMsg(props.params.refName, props.status);
2224
const [msg, setMsg] = useState(defaultMsg);
25+
const [authorName, setAuthorName] = useState("");
26+
const [authorEmail, setAuthorEmail] = useState("");
2327
const userHeaders = useUserHeaders();
24-
const [addCommitAuthor, setAddCommitAuthor] = useState(!!userHeaders);
2528
const { getCallProcedure } = useSqlBuilder();
2629

27-
const onSubmit = (e: SyntheticEvent) => {
30+
const headerName = userHeaders?.user;
31+
const headerEmail = userHeaders?.email;
32+
const hasHeaders = !!headerName || !!headerEmail;
33+
34+
// Load stored author for Electron, or populate from headers
35+
useEffectAsync(async () => {
36+
if (hasHeaders) {
37+
setAuthorName(headerName ?? "");
38+
setAuthorEmail(headerEmail ?? "");
39+
return;
40+
}
41+
if (isElectron) {
42+
const stored = await window.ipc.getCommitAuthor();
43+
if (stored) {
44+
setAuthorName(stored.name);
45+
setAuthorEmail(stored.email);
46+
}
47+
}
48+
}, [userHeaders]);
49+
50+
const onSubmit = async (e: SyntheticEvent) => {
2851
e.preventDefault();
52+
// Persist author on desktop when not using headers
53+
if (isElectron && !hasHeaders && authorName && authorEmail) {
54+
await window.ipc.setCommitAuthor({
55+
name: authorName,
56+
email: authorEmail,
57+
});
58+
}
2959
const q = getCallProcedure("DOLT_COMMIT", [
3060
"-Am",
3161
msg,
32-
...getAuthorArgs(userHeaders?.user, userHeaders?.email),
62+
...getAuthorArgs(authorName, authorEmail),
3363
]);
3464
const { href, as } = sqlQuery({ ...props.params, q });
3565
router.push(href, as).catch(console.error);
@@ -64,12 +94,40 @@ export default function CommitModal(props: Props) {
6494
required
6595
light
6696
/>
67-
<HeaderUserCheckbox
68-
shouldAddAuthor={addCommitAuthor}
69-
setShouldAddAuthor={setAddCommitAuthor}
70-
userHeaders={userHeaders}
71-
kind="commit"
72-
/>
97+
<div className={css.authorFields}>
98+
<FormInput
99+
value={authorName}
100+
label="Author Name"
101+
onChangeString={setAuthorName}
102+
placeholder="Author Name"
103+
disabled={hasHeaders}
104+
light
105+
/>
106+
<FormInput
107+
value={authorEmail}
108+
label="Author Email"
109+
onChangeString={setAuthorEmail}
110+
placeholder="author@example.com"
111+
disabled={hasHeaders}
112+
light
113+
/>
114+
{hasHeaders && (
115+
<p className={css.authorNote}>
116+
Author is set from request headers and cannot be edited.
117+
</p>
118+
)}
119+
{!hasHeaders && !isElectron && (
120+
<p className={css.authorNote}>
121+
Optional. If not provided, the SQL user will be used as the commit
122+
author.
123+
</p>
124+
)}
125+
{!hasHeaders && isElectron && (
126+
<p className={css.authorNote}>
127+
Optional. Author will be saved for future commits.
128+
</p>
129+
)}
130+
</div>
73131
</div>
74132
</FormModal>
75133
);

web/renderer/components/StatusWithOptions/index.module.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@
3131
}
3232
}
3333

34+
.authorFields {
35+
@apply mt-3 flex flex-col gap-2;
36+
}
37+
38+
.authorNote {
39+
@apply text-sm text-stone-500 mt-1;
40+
}
41+
3442
.checkboxContainer {
3543
@apply flex items-start text-sm;
3644
}

0 commit comments

Comments
 (0)