@cartanova/qgrid-cli 2.11.0 → 2.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/web-dist/client/assets/index-C96h3feE.js +32 -0
- package/bundle/web-dist/client/assets/logs-DBM6U0QD.js +1 -0
- package/bundle/web-dist/client/assets/monit-BBjXa7vB.js +1 -0
- package/bundle/web-dist/client/assets/plus-BsQdY7PS.js +1 -0
- package/bundle/web-dist/client/assets/refresh-cw-D9IUmT23.js +1 -0
- package/bundle/web-dist/client/assets/request-model-Bpp_rkK8.js +1 -0
- package/bundle/web-dist/client/assets/routes-Crz_PQzi.js +5 -0
- package/bundle/web-dist/client/assets/{services.generated-CefiDXEv.js → services.generated-B5lc3aIC.js} +1 -1
- package/bundle/web-dist/client/assets/settings-Cdwm3OBB.js +1 -0
- package/bundle/web-dist/client/assets/show-DBUhALT1.js +2 -0
- package/bundle/web-dist/client/assets/tokens-CVQAVJTo.js +1 -0
- package/bundle/web-dist/client/assets/use-oauth-login-flow-BfxYI4Oh.js +1 -0
- package/bundle/web-dist/client/assets/use-update-token-mutation-qKBC2sn7.js +1 -0
- package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +9 -0
- package/bundle/web-dist/client/assets/vendor-tanstack-DRPs09ai.js +1 -0
- package/bundle/web-dist/client/index.html +4 -4
- package/bundle/web-dist/server/assets/{lazyRouteComponent-D8iTIHyn.js → lazyRouteComponent-AKiHfZWp.js} +2 -2
- package/bundle/web-dist/server/assets/logs-B7QmGJq3.js +513 -0
- package/bundle/web-dist/server/assets/{monit-B2hqorPe.js → monit-DFt7x3bh.js} +117 -375
- package/bundle/web-dist/server/assets/plus-DaYQRpBt.js +19 -0
- package/bundle/web-dist/server/assets/{react-dom-BIYQzBqG.js → react-dom-Cv23mm1K.js} +1 -1
- package/bundle/web-dist/server/assets/refresh-cw-BpXNsAy-.js +23 -0
- package/bundle/web-dist/server/assets/{request-model-I6OdODSH.js → request-model-eHE6YbaF.js} +6 -15
- package/bundle/web-dist/server/assets/{routes-B95YlUv2.js → routes-_Y-PJfgO.js} +203 -679
- package/bundle/web-dist/server/assets/{services.generated-DQATJ6qf.js → services.generated-CMJ8AHbO.js} +3796 -4012
- package/bundle/web-dist/server/assets/settings-JwJKxn2e.js +461 -0
- package/bundle/web-dist/server/assets/{show-Bxaj3rhH.js → show-BEv6z1v_.js} +368 -1270
- package/bundle/web-dist/server/assets/tokens-CNT4mI-f.js +560 -0
- package/bundle/web-dist/server/assets/{use-oauth-login-flow-CKDHgc3U.js → use-oauth-login-flow-jkAkT3X6.js} +16 -50
- package/bundle/web-dist/server/assets/{use-update-token-mutation-BEbgOzaa.js → use-update-token-mutation-Sm6kh02m.js} +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +1130 -2626
- package/package.json +1 -1
- package/bundle/web-dist/client/assets/index-BA7uQ-6c.js +0 -31
- package/bundle/web-dist/client/assets/logs-C47OJGEI.js +0 -1
- package/bundle/web-dist/client/assets/monit-BS9no0dU.js +0 -4
- package/bundle/web-dist/client/assets/plus-sdACTfH0.js +0 -1
- package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +0 -1
- package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +0 -1
- package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +0 -5
- package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +0 -1
- package/bundle/web-dist/client/assets/show-u8Np69q3.js +0 -2
- package/bundle/web-dist/client/assets/tokens-QvP410NW.js +0 -1
- package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +0 -1
- package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +0 -1
- package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +0 -244
- package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +0 -1
- package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +0 -825
- package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +0 -28
- package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +0 -44
- package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +0 -830
- package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +0 -1038
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
import { $ as __toESM, M as require_jsx_runtime, N as require_react, j as useQueryClient, n as QgridService, o as TokenService } from "./services.generated-CMJ8AHbO.js";
|
|
2
|
+
import { i as o, n as useOAuthLoginFlow, r as OAuthCodeEntry } from "./use-oauth-login-flow-jkAkT3X6.js";
|
|
3
|
+
import { u as lucideKeyRound } from "../entry-server.generated.js";
|
|
4
|
+
import { t as useUpdateTokenMutation } from "./use-update-token-mutation-Sm6kh02m.js";
|
|
5
|
+
import { t as lucidePlus } from "./plus-DaYQRpBt.js";
|
|
6
|
+
//#region src/components/qgrid/DeviceCodeEntry.tsx
|
|
7
|
+
var import_react = /* @__PURE__ */ __toESM(require_react(), 1);
|
|
8
|
+
var import_jsx_runtime = require_jsx_runtime();
|
|
9
|
+
function formatRemaining(ms) {
|
|
10
|
+
const totalSec = Math.max(Math.ceil(ms / 1e3), 0);
|
|
11
|
+
const m = Math.floor(totalSec / 60);
|
|
12
|
+
const s = totalSec % 60;
|
|
13
|
+
return `${m}:${String(s).padStart(2, "0")}`;
|
|
14
|
+
}
|
|
15
|
+
/** 만료 시각까지 1초마다 갱신되는 남은 시간. */
|
|
16
|
+
function Countdown({ expiresAt }) {
|
|
17
|
+
const [now, setNow] = (0, import_react.useState)(() => Date.now());
|
|
18
|
+
(0, import_react.useEffect)(() => {
|
|
19
|
+
const id = window.setInterval(() => setNow(Date.now()), 1e3);
|
|
20
|
+
return () => clearInterval(id);
|
|
21
|
+
}, []);
|
|
22
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
23
|
+
className: "tabular-nums",
|
|
24
|
+
children: formatRemaining(expiresAt - now)
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Grok device-code 로그인 단계. 사용자 코드와 인증 링크를 보여 주고, 폴링 상태를 표시한다.
|
|
29
|
+
* 폴링 자체는 `useOAuthLoginFlow().startDevice` 가 소유한다.
|
|
30
|
+
*/
|
|
31
|
+
function DeviceCodeEntry({ flow, onRestart }) {
|
|
32
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
33
|
+
className: "space-y-2",
|
|
34
|
+
children: [
|
|
35
|
+
flow.status === "starting" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
36
|
+
className: "flex items-center gap-1.5 text-[12px] text-sand-600",
|
|
37
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "w-3.5 h-3.5 border-2 border-sand-400 border-t-transparent rounded-full animate-spin" }), "Requesting device code..."]
|
|
38
|
+
}),
|
|
39
|
+
flow.status === "waiting" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
40
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
41
|
+
className: "text-[12px] text-sand-600 leading-relaxed",
|
|
42
|
+
children: "아래 링크를 열어 xAI 계정으로 로그인한 뒤 이 코드를 입력하세요. 승인되면 토큰이 자동으로 추가됩니다."
|
|
43
|
+
}),
|
|
44
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
45
|
+
className: "rounded-md border border-sand-200 bg-sand-50 px-3 py-3 text-center",
|
|
46
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
47
|
+
className: "text-[10px] uppercase tracking-wider text-sand-500 font-medium",
|
|
48
|
+
children: "Device code"
|
|
49
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
50
|
+
className: "mt-1 font-mono text-lg tracking-widest text-sand-900 select-all",
|
|
51
|
+
children: flow.userCode
|
|
52
|
+
})]
|
|
53
|
+
}),
|
|
54
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
|
|
55
|
+
href: flow.verificationUriComplete ?? flow.verificationUri,
|
|
56
|
+
target: "_blank",
|
|
57
|
+
rel: "noopener noreferrer",
|
|
58
|
+
className: "block w-full py-2.5 text-sm font-medium rounded-md bg-sand-900 text-white text-center hover:bg-sand-800 transition-colors duration-150",
|
|
59
|
+
children: "Open xAI to approve"
|
|
60
|
+
}),
|
|
61
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
62
|
+
className: "flex items-center justify-between text-[11px] text-sand-500",
|
|
63
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
64
|
+
className: "flex items-center gap-1.5",
|
|
65
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "w-2.5 h-2.5 border-2 border-sand-400 border-t-transparent rounded-full animate-spin" }), flow.slowDown ? "Waiting for approval (polling slowed down)..." : "Waiting for approval..."]
|
|
66
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: ["expires in ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Countdown, { expiresAt: flow.expiresAt })] })]
|
|
67
|
+
})
|
|
68
|
+
] }),
|
|
69
|
+
flow.status === "added" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
70
|
+
className: "text-[12px] text-sage-600",
|
|
71
|
+
children: [
|
|
72
|
+
"Token \"",
|
|
73
|
+
flow.name,
|
|
74
|
+
"\" added."
|
|
75
|
+
]
|
|
76
|
+
}),
|
|
77
|
+
flow.status === "expired" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
78
|
+
className: "text-[11px] text-red-500",
|
|
79
|
+
children: "Device code가 만료되었습니다 — 로그인을 다시 시작하세요."
|
|
80
|
+
}),
|
|
81
|
+
flow.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
82
|
+
className: "text-[11px] text-red-500",
|
|
83
|
+
children: flow.message
|
|
84
|
+
}),
|
|
85
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
86
|
+
type: "button",
|
|
87
|
+
className: "w-full py-1.5 text-[12px] text-sand-500 hover:text-sand-700 transition-colors duration-150",
|
|
88
|
+
onClick: onRestart,
|
|
89
|
+
children: "처음부터 다시 시작"
|
|
90
|
+
})
|
|
91
|
+
]
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/components/qgrid/AddTokenModal.tsx
|
|
96
|
+
function Spinner({ light }) {
|
|
97
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
98
|
+
className: "flex items-center gap-1.5",
|
|
99
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `w-3.5 h-3.5 border-2 border-t-transparent rounded-full animate-spin ${light ? "border-white" : "border-sand-400"}` }), "Waiting for login..."]
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function OrDivider() {
|
|
103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
104
|
+
className: "flex items-center gap-3",
|
|
105
|
+
children: [
|
|
106
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex-1 h-px bg-sand-200" }),
|
|
107
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
108
|
+
className: "text-[10px] text-sand-400 uppercase",
|
|
109
|
+
children: "or"
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex-1 h-px bg-sand-200" })
|
|
112
|
+
]
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/** Provider 선택 버튼들. 상태는 상위(`useOAuthLoginFlow`)가 소유한다. */
|
|
116
|
+
function AddTokenProviderOptions({ disabled, loadingProvider, onStart, onStartGrokDevice }) {
|
|
117
|
+
const secondary = "w-full py-2.5 text-sm font-medium rounded-md border border-sand-300 text-sand-700 hover:bg-sand-100 disabled:opacity-50 transition-colors duration-150 flex items-center justify-center gap-2";
|
|
118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
119
|
+
className: "space-y-2",
|
|
120
|
+
children: [
|
|
121
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
122
|
+
type: "button",
|
|
123
|
+
className: "w-full py-2.5 text-sm font-medium rounded-md bg-sand-900 text-white hover:bg-sand-800 disabled:opacity-50 transition-colors duration-150 flex items-center justify-center gap-2",
|
|
124
|
+
disabled,
|
|
125
|
+
onClick: () => onStart("openai"),
|
|
126
|
+
children: loadingProvider === "openai" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { light: true }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideKeyRound, { className: "size-4" }), "Login with OpenAI"] })
|
|
127
|
+
}),
|
|
128
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(OrDivider, {}),
|
|
129
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
130
|
+
type: "button",
|
|
131
|
+
className: secondary,
|
|
132
|
+
disabled,
|
|
133
|
+
onClick: () => onStart("anthropic"),
|
|
134
|
+
children: loadingProvider === "anthropic" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { light: false }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideKeyRound, { className: "size-4" }), "Login with Claude"] })
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(OrDivider, {}),
|
|
137
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
138
|
+
type: "button",
|
|
139
|
+
className: secondary,
|
|
140
|
+
disabled,
|
|
141
|
+
onClick: onStartGrokDevice,
|
|
142
|
+
children: loadingProvider === "grok" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { light: false }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideKeyRound, { className: "size-4" }), "Login with xAI"] })
|
|
143
|
+
})
|
|
144
|
+
]
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function AddTokenModal() {
|
|
148
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
149
|
+
const [name, setName] = (0, import_react.useState)("");
|
|
150
|
+
const oauth = useOAuthLoginFlow();
|
|
151
|
+
const close = () => {
|
|
152
|
+
setOpen(false);
|
|
153
|
+
setName("");
|
|
154
|
+
oauth.reset();
|
|
155
|
+
};
|
|
156
|
+
const submitPastedCode = async (pastedCode) => {
|
|
157
|
+
if (await oauth.submitCode(pastedCode)) close();
|
|
158
|
+
};
|
|
159
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
160
|
+
type: "button",
|
|
161
|
+
className: "px-3.5 py-1.5 text-[12px] font-medium rounded-lg bg-sienna-500 text-white hover:bg-sienna-600 disabled:opacity-50 transition-all duration-150 active:scale-[0.97] flex items-center gap-1.5 shadow-sm",
|
|
162
|
+
onClick: () => setOpen(true),
|
|
163
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucidePlus, { className: "size-3.5" }), "Add Token"]
|
|
164
|
+
}), open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
165
|
+
className: "fixed inset-0 z-50 flex items-start justify-center pt-[15vh]",
|
|
166
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
167
|
+
className: "absolute inset-0 bg-sand-900/8 backdrop-blur-sm",
|
|
168
|
+
onClick: close,
|
|
169
|
+
onKeyDown: () => {}
|
|
170
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
171
|
+
className: "relative panel shadow-xl w-full max-w-md mx-4",
|
|
172
|
+
children: [
|
|
173
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
174
|
+
className: "px-5 py-4 border-b border-sand-100/50",
|
|
175
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", {
|
|
176
|
+
className: "text-base font-medium text-sand-900",
|
|
177
|
+
children: "Add Token"
|
|
178
|
+
})
|
|
179
|
+
}),
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
181
|
+
className: "px-5 py-4 space-y-4",
|
|
182
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", {
|
|
183
|
+
htmlFor: "token-name",
|
|
184
|
+
className: "text-[10px] uppercase tracking-wider text-sand-500 font-medium",
|
|
185
|
+
children: "Name *"
|
|
186
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(o, {
|
|
187
|
+
value: name,
|
|
188
|
+
onChange: (e) => setName(e.target.value),
|
|
189
|
+
placeholder: "e.g. your-token-name",
|
|
190
|
+
className: "mt-1 w-full border border-sand-200 rounded-md px-3 py-2 text-sm text-sand-900 bg-white placeholder:text-sand-300 focus:outline-none focus:border-sienna-300"
|
|
191
|
+
})] }), oauth.codeEntryProvider ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OAuthCodeEntry, {
|
|
192
|
+
provider: oauth.codeEntryProvider,
|
|
193
|
+
isPending: oauth.completeMutation.isPending,
|
|
194
|
+
isError: oauth.completeMutation.isError,
|
|
195
|
+
onSubmit: (code) => void submitPastedCode(code),
|
|
196
|
+
onRestart: oauth.reset
|
|
197
|
+
}) : oauth.deviceFlow ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DeviceCodeEntry, {
|
|
198
|
+
flow: oauth.deviceFlow,
|
|
199
|
+
onRestart: oauth.reset
|
|
200
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddTokenProviderOptions, {
|
|
201
|
+
disabled: !name.trim() || oauth.loadingProvider !== null,
|
|
202
|
+
loadingProvider: oauth.loadingProvider,
|
|
203
|
+
onStart: (provider) => void oauth.start(provider, name),
|
|
204
|
+
onStartGrokDevice: () => void oauth.startDevice(name, close)
|
|
205
|
+
})]
|
|
206
|
+
}),
|
|
207
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
208
|
+
className: "px-5 py-3 border-t border-sand-100/50 flex items-center justify-end gap-2",
|
|
209
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
210
|
+
type: "button",
|
|
211
|
+
className: "px-3 py-1 text-xs font-medium rounded-md border border-sand-200 text-sand-600 hover:bg-sand-100 transition-colors duration-150",
|
|
212
|
+
onClick: close,
|
|
213
|
+
children: "Cancel"
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
]
|
|
217
|
+
})]
|
|
218
|
+
})] });
|
|
219
|
+
}
|
|
220
|
+
//#endregion
|
|
221
|
+
//#region ~icons/lucide/pencil.jsx
|
|
222
|
+
var lucidePencil = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
|
|
223
|
+
viewBox: "0 0 24 24",
|
|
224
|
+
width: "1.2em",
|
|
225
|
+
height: "1.2em",
|
|
226
|
+
...props,
|
|
227
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
|
|
228
|
+
fill: "none",
|
|
229
|
+
stroke: "currentColor",
|
|
230
|
+
strokeLinecap: "round",
|
|
231
|
+
strokeLinejoin: "round",
|
|
232
|
+
strokeWidth: 2,
|
|
233
|
+
d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497zM15 5l4 4"
|
|
234
|
+
})
|
|
235
|
+
});
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region ~icons/lucide/trash-2.jsx
|
|
238
|
+
var lucideTrash2 = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
|
|
239
|
+
viewBox: "0 0 24 24",
|
|
240
|
+
width: "1.2em",
|
|
241
|
+
height: "1.2em",
|
|
242
|
+
...props,
|
|
243
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
|
|
244
|
+
fill: "none",
|
|
245
|
+
stroke: "currentColor",
|
|
246
|
+
strokeLinecap: "round",
|
|
247
|
+
strokeLinejoin: "round",
|
|
248
|
+
strokeWidth: 2,
|
|
249
|
+
d: "M10 11v6m4-6v6m5-11v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
|
|
250
|
+
})
|
|
251
|
+
});
|
|
252
|
+
//#endregion
|
|
253
|
+
//#region src/lib/token-label.ts
|
|
254
|
+
function maskAccessToken(credentials) {
|
|
255
|
+
const token = credentials.accessToken;
|
|
256
|
+
if (!token) return "—";
|
|
257
|
+
return token.length <= 12 ? token : `${token.slice(0, 8)}...${token.slice(-4)}`;
|
|
258
|
+
}
|
|
259
|
+
//#endregion
|
|
260
|
+
//#region src/components/qgrid/TokenTable.tsx
|
|
261
|
+
function getExpiresAt(token) {
|
|
262
|
+
const c = token.credentials;
|
|
263
|
+
if ("accessTokenExpiresAt" in c) return c.accessTokenExpiresAt;
|
|
264
|
+
if ("authMode" in c) {
|
|
265
|
+
const ms = Date.parse(c.expiresAt);
|
|
266
|
+
return Number.isNaN(ms) ? null : ms;
|
|
267
|
+
}
|
|
268
|
+
return c.expiresAt;
|
|
269
|
+
}
|
|
270
|
+
function formatExpiry(expiresAt) {
|
|
271
|
+
if (!expiresAt) return {
|
|
272
|
+
text: "",
|
|
273
|
+
color: ""
|
|
274
|
+
};
|
|
275
|
+
const diff = expiresAt - Date.now();
|
|
276
|
+
if (diff <= 0) return {
|
|
277
|
+
text: "expired",
|
|
278
|
+
color: "text-red-500"
|
|
279
|
+
};
|
|
280
|
+
const h = Math.floor(diff / 36e5);
|
|
281
|
+
const m = Math.floor(diff % 36e5 / 6e4);
|
|
282
|
+
const text = h > 0 ? `${h}h ${m}m` : `${m}m`;
|
|
283
|
+
if (diff < 36e5) return {
|
|
284
|
+
text,
|
|
285
|
+
color: "text-amber-500"
|
|
286
|
+
};
|
|
287
|
+
return {
|
|
288
|
+
text,
|
|
289
|
+
color: "text-sand-400"
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
function TokenTable({ data, isLoading }) {
|
|
293
|
+
const [deleteTarget, setDeleteTarget] = (0, import_react.useState)(null);
|
|
294
|
+
const [editTarget, setEditTarget] = (0, import_react.useState)(null);
|
|
295
|
+
const [editName, setEditName] = (0, import_react.useState)("");
|
|
296
|
+
const queryClient = useQueryClient();
|
|
297
|
+
const removeMutation = QgridService.useRemoveTokenMutation();
|
|
298
|
+
const updateMutation = useUpdateTokenMutation();
|
|
299
|
+
const toggleMutation = QgridService.useToggleTokenMutation();
|
|
300
|
+
const invalidate = () => Promise.all([queryClient.invalidateQueries({ queryKey: ["Token"] }), queryClient.invalidateQueries({ queryKey: ["Qgrid"] })]);
|
|
301
|
+
const handleToggle = async (token) => {
|
|
302
|
+
await toggleMutation.mutateAsync({ id: token.id });
|
|
303
|
+
await invalidate();
|
|
304
|
+
};
|
|
305
|
+
const handleDelete = async () => {
|
|
306
|
+
if (!deleteTarget) return;
|
|
307
|
+
await removeMutation.mutateAsync({ id: deleteTarget.id });
|
|
308
|
+
await invalidate();
|
|
309
|
+
setDeleteTarget(null);
|
|
310
|
+
};
|
|
311
|
+
const openEdit = (token) => {
|
|
312
|
+
setEditTarget(token);
|
|
313
|
+
setEditName(token.name ?? "");
|
|
314
|
+
};
|
|
315
|
+
const handleUpdate = async () => {
|
|
316
|
+
if (!editTarget) return;
|
|
317
|
+
await updateMutation.mutateAsync({
|
|
318
|
+
id: editTarget.id,
|
|
319
|
+
name: editName.trim()
|
|
320
|
+
});
|
|
321
|
+
await invalidate();
|
|
322
|
+
setEditTarget(null);
|
|
323
|
+
};
|
|
324
|
+
if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
325
|
+
className: "space-y-2",
|
|
326
|
+
children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-12 bg-sand-100 rounded-md animate-pulse" }, `skeleton-${i}`))
|
|
327
|
+
});
|
|
328
|
+
const tokens = data ?? [];
|
|
329
|
+
if (tokens.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
330
|
+
className: "text-sand-400 text-center py-16 text-sm",
|
|
331
|
+
children: [
|
|
332
|
+
"No tokens registered. Click ",
|
|
333
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", {
|
|
334
|
+
className: "text-sand-600",
|
|
335
|
+
children: "Add Token"
|
|
336
|
+
}),
|
|
337
|
+
" to get started."
|
|
338
|
+
]
|
|
339
|
+
});
|
|
340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
341
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
342
|
+
className: "panel overflow-hidden",
|
|
343
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
344
|
+
className: "overflow-x-auto",
|
|
345
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", {
|
|
346
|
+
className: "w-full min-w-[640px] text-[13px]",
|
|
347
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", {
|
|
348
|
+
className: "panel-header",
|
|
349
|
+
children: [
|
|
350
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
|
|
351
|
+
className: "text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
|
|
352
|
+
children: "Provider"
|
|
353
|
+
}),
|
|
354
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
|
|
355
|
+
className: "text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
|
|
356
|
+
children: "Name"
|
|
357
|
+
}),
|
|
358
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
|
|
359
|
+
className: "text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
|
|
360
|
+
children: "Token"
|
|
361
|
+
}),
|
|
362
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
|
|
363
|
+
className: "text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
|
|
364
|
+
children: "Status"
|
|
365
|
+
}),
|
|
366
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
|
|
367
|
+
className: "text-left px-5 py-2.5 text-[10px] uppercase tracking-wider text-sand-400 font-medium",
|
|
368
|
+
children: "Expires"
|
|
369
|
+
}),
|
|
370
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: "w-20 px-3 py-2.5" })
|
|
371
|
+
]
|
|
372
|
+
}) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", {
|
|
373
|
+
className: "divide-y divide-sand-100/80",
|
|
374
|
+
children: tokens.map((token) => {
|
|
375
|
+
const expiry = formatExpiry(getExpiresAt(token));
|
|
376
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", {
|
|
377
|
+
className: `transition-colors duration-150 hover:bg-sand-100/60 ${token.active ? "" : "opacity-50"}`,
|
|
378
|
+
children: [
|
|
379
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
380
|
+
className: "px-5 py-3",
|
|
381
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
382
|
+
className: "text-xs font-medium text-sand-500 uppercase",
|
|
383
|
+
children: token.provider
|
|
384
|
+
})
|
|
385
|
+
}),
|
|
386
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
387
|
+
className: "px-5 py-3",
|
|
388
|
+
children: token.name ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
389
|
+
className: "text-sm text-sand-700",
|
|
390
|
+
children: token.name
|
|
391
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
392
|
+
className: "text-[11px] text-sand-400",
|
|
393
|
+
children: "—"
|
|
394
|
+
})
|
|
395
|
+
}),
|
|
396
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
397
|
+
className: "px-5 py-3",
|
|
398
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
|
|
399
|
+
className: "text-[13px] font-mono text-sand-800",
|
|
400
|
+
children: maskAccessToken(token.credentials)
|
|
401
|
+
})
|
|
402
|
+
}),
|
|
403
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
404
|
+
className: "px-5 py-3",
|
|
405
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
406
|
+
type: "button",
|
|
407
|
+
className: `relative inline-flex h-5 w-9 items-center rounded-full transition-colors duration-200 ${token.active ? "bg-sage-400" : "bg-sand-300"}`,
|
|
408
|
+
onClick: () => handleToggle(token),
|
|
409
|
+
disabled: toggleMutation.isPending || !token.active && token.reauth_required,
|
|
410
|
+
title: !token.active && token.reauth_required ? "재로그인이 필요한 토큰입니다" : void 0,
|
|
411
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `inline-block h-3.5 w-3.5 rounded-full bg-white transition-transform duration-200 ${token.active ? "translate-x-4.5" : "translate-x-0.5"}` })
|
|
412
|
+
})
|
|
413
|
+
}),
|
|
414
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
415
|
+
className: "px-5 py-3",
|
|
416
|
+
children: expiry.text && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
417
|
+
className: `text-xs ${expiry.color}`,
|
|
418
|
+
children: expiry.text
|
|
419
|
+
})
|
|
420
|
+
}),
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
|
|
422
|
+
className: "px-3 py-3",
|
|
423
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
424
|
+
className: "flex items-center gap-1",
|
|
425
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
426
|
+
type: "button",
|
|
427
|
+
className: "p-1 rounded text-sand-400 hover:text-sienna-500 transition-colors duration-150",
|
|
428
|
+
onClick: () => openEdit(token),
|
|
429
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucidePencil, { className: "size-4" })
|
|
430
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
431
|
+
type: "button",
|
|
432
|
+
className: "p-1 rounded text-sand-400 hover:text-red-500 transition-colors duration-150",
|
|
433
|
+
onClick: () => setDeleteTarget(token),
|
|
434
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(lucideTrash2, { className: "size-4" })
|
|
435
|
+
})]
|
|
436
|
+
})
|
|
437
|
+
})
|
|
438
|
+
]
|
|
439
|
+
}, token.id);
|
|
440
|
+
})
|
|
441
|
+
})]
|
|
442
|
+
})
|
|
443
|
+
})
|
|
444
|
+
}),
|
|
445
|
+
editTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
446
|
+
className: "fixed inset-0 z-50 flex items-start justify-center pt-[15vh]",
|
|
447
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
448
|
+
className: "absolute inset-0 bg-sand-900/8 backdrop-blur-sm",
|
|
449
|
+
onClick: () => setEditTarget(null),
|
|
450
|
+
onKeyDown: () => {}
|
|
451
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
452
|
+
className: "relative panel shadow-xl w-full max-w-sm mx-4",
|
|
453
|
+
children: [
|
|
454
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
455
|
+
className: "px-5 py-4 border-b border-sand-100/60",
|
|
456
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
|
|
457
|
+
className: "text-base font-medium text-sand-900",
|
|
458
|
+
children: "Edit Token"
|
|
459
|
+
})
|
|
460
|
+
}),
|
|
461
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
462
|
+
className: "px-5 py-4 space-y-3",
|
|
463
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", {
|
|
464
|
+
htmlFor: "token-name",
|
|
465
|
+
className: "text-[10px] uppercase tracking-wider text-sand-500 font-medium",
|
|
466
|
+
children: "Name"
|
|
467
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(o, {
|
|
468
|
+
value: editName,
|
|
469
|
+
onChange: (e) => setEditName(e.target.value),
|
|
470
|
+
placeholder: "e.g. prod, dev, team-a",
|
|
471
|
+
className: "mt-1 w-full border border-sand-200 rounded-md px-3 py-2 text-sm text-sand-900 bg-white placeholder:text-sand-300 focus:outline-none focus:border-sienna-300"
|
|
472
|
+
})] })
|
|
473
|
+
}),
|
|
474
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
475
|
+
className: "px-5 py-3 border-t border-sand-100/60 flex items-center justify-end gap-2",
|
|
476
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
477
|
+
type: "button",
|
|
478
|
+
className: "px-3 py-1 text-xs font-medium rounded-md border border-sand-200 text-sand-600 hover:bg-sand-100 transition-colors duration-150",
|
|
479
|
+
onClick: () => setEditTarget(null),
|
|
480
|
+
children: "Cancel"
|
|
481
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
482
|
+
type: "button",
|
|
483
|
+
className: "px-3 py-1 text-xs font-medium rounded-md bg-sienna-400 text-white hover:bg-sienna-500 disabled:opacity-50 transition-colors duration-150",
|
|
484
|
+
disabled: updateMutation.isPending,
|
|
485
|
+
onClick: handleUpdate,
|
|
486
|
+
children: updateMutation.isPending ? "Saving..." : "Save"
|
|
487
|
+
})]
|
|
488
|
+
})
|
|
489
|
+
]
|
|
490
|
+
})]
|
|
491
|
+
}),
|
|
492
|
+
deleteTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
493
|
+
className: "fixed inset-0 z-50 flex items-start justify-center pt-[15vh]",
|
|
494
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
495
|
+
className: "absolute inset-0 bg-sand-900/8 backdrop-blur-sm",
|
|
496
|
+
onClick: () => setDeleteTarget(null),
|
|
497
|
+
onKeyDown: () => {}
|
|
498
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
499
|
+
className: "relative panel shadow-xl w-full max-w-sm mx-4",
|
|
500
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
501
|
+
className: "px-5 py-4",
|
|
502
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
|
|
503
|
+
className: "text-base font-medium text-sand-900",
|
|
504
|
+
children: "Remove Token"
|
|
505
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
506
|
+
className: "text-sm text-sand-700 mt-2",
|
|
507
|
+
children: [
|
|
508
|
+
"Are you sure you want to remove",
|
|
509
|
+
" ",
|
|
510
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
|
|
511
|
+
className: "text-[13px] font-mono text-sand-800",
|
|
512
|
+
children: maskAccessToken(deleteTarget.credentials)
|
|
513
|
+
}),
|
|
514
|
+
deleteTarget.name && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
515
|
+
className: "text-sand-500",
|
|
516
|
+
children: [
|
|
517
|
+
" (",
|
|
518
|
+
deleteTarget.name,
|
|
519
|
+
")"
|
|
520
|
+
]
|
|
521
|
+
}),
|
|
522
|
+
"?"
|
|
523
|
+
]
|
|
524
|
+
})]
|
|
525
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
526
|
+
className: "px-5 py-3 border-t border-sand-100/60 flex items-center justify-end gap-2",
|
|
527
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
528
|
+
type: "button",
|
|
529
|
+
className: "px-3 py-1 text-xs font-medium rounded-md border border-sand-200 text-sand-600 hover:bg-sand-100 transition-colors duration-150",
|
|
530
|
+
onClick: () => setDeleteTarget(null),
|
|
531
|
+
children: "Cancel"
|
|
532
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
533
|
+
type: "button",
|
|
534
|
+
className: "px-3 py-1 text-xs font-medium rounded-md bg-red-500 text-white hover:bg-red-600 disabled:opacity-50 transition-colors duration-150",
|
|
535
|
+
disabled: removeMutation.isPending,
|
|
536
|
+
onClick: handleDelete,
|
|
537
|
+
children: removeMutation.isPending ? "Removing..." : "Remove"
|
|
538
|
+
})]
|
|
539
|
+
})]
|
|
540
|
+
})]
|
|
541
|
+
})
|
|
542
|
+
] });
|
|
543
|
+
}
|
|
544
|
+
//#endregion
|
|
545
|
+
//#region src/routes/tokens.tsx?tsr-split=component
|
|
546
|
+
function TokensPage() {
|
|
547
|
+
const { data, isLoading } = TokenService.useTokens("A");
|
|
548
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
549
|
+
className: "max-w-6xl mx-auto space-y-4",
|
|
550
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
551
|
+
className: "flex items-center justify-end",
|
|
552
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddTokenModal, {})
|
|
553
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TokenTable, {
|
|
554
|
+
data: data?.rows,
|
|
555
|
+
isLoading
|
|
556
|
+
})]
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
//#endregion
|
|
560
|
+
export { TokensPage as component };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as __toESM, M as require_jsx_runtime, N as require_react, j as useQueryClient, n as QgridService, o as TokenService } from "./services.generated-CMJ8AHbO.js";
|
|
2
2
|
import { t as clsx } from "./clsx-D_N5PN_2.js";
|
|
3
3
|
//#region ../../node_modules/.pnpm/tailwind-merge@3.5.0/node_modules/tailwind-merge/dist/bundle-mjs.mjs
|
|
4
4
|
/**
|
|
@@ -2023,8 +2023,6 @@ var o = import_react.forwardRef(({ className: o, type: s, onValueChange: c, onCh
|
|
|
2023
2023
|
o.displayName = "Input";
|
|
2024
2024
|
//#endregion
|
|
2025
2025
|
//#region src/components/qgrid/OAuthCodeEntry.tsx
|
|
2026
|
-
var import_jsx_dev_runtime = require_jsx_dev_runtime();
|
|
2027
|
-
var _jsxFileName = "/home/runner/work/qgrid/qgrid/packages/web/src/components/qgrid/OAuthCodeEntry.tsx";
|
|
2028
2026
|
var HELP_TEXT = {
|
|
2029
2027
|
openai: "새 탭에서 OpenAI 로그인을 완료한 뒤 연결 실패 화면이 나타나면, 주소창의 전체 URL을 아래에 붙여넣으세요.",
|
|
2030
2028
|
anthropic: "새 탭에서 Claude 로그인을 완료하면 코드가 표시됩니다. 코드 전체를 아래에 붙여넣으세요.",
|
|
@@ -2041,58 +2039,34 @@ var PLACEHOLDER = {
|
|
|
2041
2039
|
*/
|
|
2042
2040
|
function OAuthCodeEntry({ provider, isPending, isError, onSubmit, onRestart }) {
|
|
2043
2041
|
const [pastedCode, setPastedCode] = (0, import_react.useState)("");
|
|
2044
|
-
return /* @__PURE__ */ (0,
|
|
2042
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
2045
2043
|
className: "space-y-2",
|
|
2046
2044
|
children: [
|
|
2047
|
-
/* @__PURE__ */ (0,
|
|
2045
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
2048
2046
|
className: "text-[12px] text-sand-600 leading-relaxed",
|
|
2049
2047
|
children: HELP_TEXT[provider]
|
|
2050
|
-
},
|
|
2051
|
-
|
|
2052
|
-
lineNumber: 41,
|
|
2053
|
-
columnNumber: 7
|
|
2054
|
-
}, this),
|
|
2055
|
-
/* @__PURE__ */ (0, import_jsx_dev_runtime.jsxDEV)(o, {
|
|
2048
|
+
}),
|
|
2049
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(o, {
|
|
2056
2050
|
value: pastedCode,
|
|
2057
2051
|
onChange: (e) => setPastedCode(e.target.value),
|
|
2058
2052
|
placeholder: PLACEHOLDER[provider],
|
|
2059
2053
|
className: "w-full border border-sand-200 rounded-md px-3 py-2 text-sm font-mono text-sand-900 bg-white placeholder:text-sand-300 focus:outline-none focus:border-sienna-300"
|
|
2060
|
-
},
|
|
2061
|
-
|
|
2062
|
-
lineNumber: 42,
|
|
2063
|
-
columnNumber: 7
|
|
2064
|
-
}, this),
|
|
2065
|
-
isError && /* @__PURE__ */ (void 0)("p", {
|
|
2054
|
+
}),
|
|
2055
|
+
isError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
2066
2056
|
className: "text-[11px] text-red-500",
|
|
2067
2057
|
children: "인증 결과 확인에 실패했습니다 — 전체 값을 다시 붙여넣거나 로그인을 다시 시작하세요."
|
|
2068
|
-
},
|
|
2069
|
-
|
|
2070
|
-
lineNumber: 49,
|
|
2071
|
-
columnNumber: 9
|
|
2072
|
-
}, this),
|
|
2073
|
-
/* @__PURE__ */ (0, import_jsx_dev_runtime.jsxDEV)("button", {
|
|
2058
|
+
}),
|
|
2059
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
2074
2060
|
type: "button",
|
|
2075
2061
|
className: "w-full py-2.5 text-sm font-medium rounded-md bg-sand-900 text-white hover:bg-sand-800 disabled:opacity-50 transition-colors duration-150 flex items-center justify-center gap-2",
|
|
2076
2062
|
disabled: !pastedCode.trim() || isPending,
|
|
2077
2063
|
onClick: () => onSubmit(pastedCode),
|
|
2078
|
-
children: isPending ? /* @__PURE__ */ (0,
|
|
2064
|
+
children: isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
2079
2065
|
className: "flex items-center gap-1.5",
|
|
2080
|
-
children: [/* @__PURE__ */ (0,
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
}, this), "Verifying..."]
|
|
2085
|
-
}, void 0, true, {
|
|
2086
|
-
fileName: _jsxFileName,
|
|
2087
|
-
lineNumber: 60,
|
|
2088
|
-
columnNumber: 11
|
|
2089
|
-
}, this) : "Complete login"
|
|
2090
|
-
}, void 0, false, {
|
|
2091
|
-
fileName: _jsxFileName,
|
|
2092
|
-
lineNumber: 53,
|
|
2093
|
-
columnNumber: 7
|
|
2094
|
-
}, this),
|
|
2095
|
-
/* @__PURE__ */ (0, import_jsx_dev_runtime.jsxDEV)("button", {
|
|
2066
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "w-3.5 h-3.5 border-2 border-white border-t-transparent rounded-full animate-spin" }), "Verifying..."]
|
|
2067
|
+
}) : "Complete login"
|
|
2068
|
+
}),
|
|
2069
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
2096
2070
|
type: "button",
|
|
2097
2071
|
className: "w-full py-1.5 text-[12px] text-sand-500 hover:text-sand-700 transition-colors duration-150",
|
|
2098
2072
|
onClick: () => {
|
|
@@ -2100,17 +2074,9 @@ function OAuthCodeEntry({ provider, isPending, isError, onSubmit, onRestart }) {
|
|
|
2100
2074
|
onRestart();
|
|
2101
2075
|
},
|
|
2102
2076
|
children: "처음부터 다시 시작"
|
|
2103
|
-
}
|
|
2104
|
-
fileName: _jsxFileName,
|
|
2105
|
-
lineNumber: 68,
|
|
2106
|
-
columnNumber: 7
|
|
2107
|
-
}, this)
|
|
2077
|
+
})
|
|
2108
2078
|
]
|
|
2109
|
-
}
|
|
2110
|
-
fileName: _jsxFileName,
|
|
2111
|
-
lineNumber: 40,
|
|
2112
|
-
columnNumber: 5
|
|
2113
|
-
}, this);
|
|
2079
|
+
});
|
|
2114
2080
|
}
|
|
2115
2081
|
//#endregion
|
|
2116
2082
|
//#region src/components/qgrid/use-oauth-login-flow.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { O as useMutation, n as QgridService } from "./services.generated-CMJ8AHbO.js";
|
|
2
2
|
//#region src/services/token/use-update-token-mutation.ts
|
|
3
3
|
function useUpdateTokenMutation() {
|
|
4
4
|
return useMutation({ mutationFn: ({ id, name, quotaThreshold, weight, keepaliveEnabled }) => QgridService.updateToken(id, name, quotaThreshold, weight, keepaliveEnabled) });
|