epiq 1.2.3 → 1.3.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/dist/gui/main.js +617 -198
- package/dist/index.js +53 -52
- package/dist/mcp.js +42 -41
- package/package.json +1 -1
- package/readme.md +2 -3
package/dist/gui/main.js
CHANGED
|
@@ -1328,7 +1328,7 @@ var require_react_dom_development = __commonJS({
|
|
|
1328
1328
|
return dispatcher;
|
|
1329
1329
|
}
|
|
1330
1330
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
1331
|
-
var
|
|
1331
|
+
var React17 = require_react(), Internals = {
|
|
1332
1332
|
d: {
|
|
1333
1333
|
f: noop,
|
|
1334
1334
|
r: function() {
|
|
@@ -1346,7 +1346,7 @@ var require_react_dom_development = __commonJS({
|
|
|
1346
1346
|
},
|
|
1347
1347
|
p: 0,
|
|
1348
1348
|
findDOMNode: null
|
|
1349
|
-
}, REACT_PORTAL_TYPE = Symbol.for("react.portal"), ReactSharedInternals =
|
|
1349
|
+
}, REACT_PORTAL_TYPE = Symbol.for("react.portal"), ReactSharedInternals = React17.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
|
|
1350
1350
|
"function" === typeof Map && null != Map.prototype && "function" === typeof Map.prototype.forEach && "function" === typeof Set && null != Set.prototype && "function" === typeof Set.prototype.clear && "function" === typeof Set.prototype.forEach || console.error(
|
|
1351
1351
|
"React depends on Map and Set built-in types. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"
|
|
1352
1352
|
);
|
|
@@ -2881,7 +2881,7 @@ var require_react_dom_client_development = __commonJS({
|
|
|
2881
2881
|
"number" === type && getActiveElement(node.ownerDocument) === node || node.defaultValue === "" + value || (node.defaultValue = "" + value);
|
|
2882
2882
|
}
|
|
2883
2883
|
function validateOptionProps(element, props) {
|
|
2884
|
-
null == props.value && ("object" === typeof props.children && null !== props.children ?
|
|
2884
|
+
null == props.value && ("object" === typeof props.children && null !== props.children ? React17.Children.forEach(props.children, function(child) {
|
|
2885
2885
|
null == child || "string" === typeof child || "number" === typeof child || "bigint" === typeof child || didWarnInvalidChild || (didWarnInvalidChild = true, console.error(
|
|
2886
2886
|
"Cannot infer the option value of complex children. Pass a `value` prop or use a plain string as children to <option>."
|
|
2887
2887
|
));
|
|
@@ -18513,14 +18513,14 @@ var require_react_dom_client_development = __commonJS({
|
|
|
18513
18513
|
));
|
|
18514
18514
|
}
|
|
18515
18515
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
18516
|
-
var Scheduler = require_scheduler(),
|
|
18516
|
+
var Scheduler = require_scheduler(), React17 = require_react(), ReactDOM = require_react_dom(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy");
|
|
18517
18517
|
Symbol.for("react.scope");
|
|
18518
18518
|
var REACT_ACTIVITY_TYPE = Symbol.for("react.activity");
|
|
18519
18519
|
Symbol.for("react.legacy_hidden");
|
|
18520
18520
|
Symbol.for("react.tracing_marker");
|
|
18521
18521
|
var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
|
|
18522
18522
|
Symbol.for("react.view_transition");
|
|
18523
|
-
var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals =
|
|
18523
|
+
var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React17.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, ReactDOMSharedInternals = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, NotPending = Object.freeze({
|
|
18524
18524
|
pending: false,
|
|
18525
18525
|
data: null,
|
|
18526
18526
|
method: null,
|
|
@@ -21308,7 +21308,7 @@ var require_react_dom_client_development = __commonJS({
|
|
|
21308
21308
|
}
|
|
21309
21309
|
};
|
|
21310
21310
|
(function() {
|
|
21311
|
-
var isomorphicReactPackageVersion =
|
|
21311
|
+
var isomorphicReactPackageVersion = React17.version;
|
|
21312
21312
|
if ("19.2.6" !== isomorphicReactPackageVersion)
|
|
21313
21313
|
throw Error(
|
|
21314
21314
|
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' + (isomorphicReactPackageVersion + "\n - react-dom: 19.2.6\nLearn more: https://react.dev/warnings/version-mismatch")
|
|
@@ -21662,18 +21662,18 @@ var require_react_jsx_runtime_development = __commonJS({
|
|
|
21662
21662
|
function isValidElement2(object) {
|
|
21663
21663
|
return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
|
|
21664
21664
|
}
|
|
21665
|
-
var
|
|
21665
|
+
var React17 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React17.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
|
|
21666
21666
|
return null;
|
|
21667
21667
|
};
|
|
21668
|
-
|
|
21668
|
+
React17 = {
|
|
21669
21669
|
react_stack_bottom_frame: function(callStackForError) {
|
|
21670
21670
|
return callStackForError();
|
|
21671
21671
|
}
|
|
21672
21672
|
};
|
|
21673
21673
|
var specialPropKeyWarningShown;
|
|
21674
21674
|
var didWarnAboutElementRef = {};
|
|
21675
|
-
var unknownOwnerDebugStack =
|
|
21676
|
-
|
|
21675
|
+
var unknownOwnerDebugStack = React17.react_stack_bottom_frame.bind(
|
|
21676
|
+
React17,
|
|
21677
21677
|
UnknownOwner
|
|
21678
21678
|
)();
|
|
21679
21679
|
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
|
@@ -24492,7 +24492,7 @@ function useViewTransitionState(to, { relative } = {}) {
|
|
|
24492
24492
|
}
|
|
24493
24493
|
|
|
24494
24494
|
// source/gui/client/App.tsx
|
|
24495
|
-
var
|
|
24495
|
+
var import_react9 = __toESM(require_react(), 1);
|
|
24496
24496
|
|
|
24497
24497
|
// source/gui/client/components/Button.tsx
|
|
24498
24498
|
var import_react = __toESM(require_react(), 1);
|
|
@@ -24871,7 +24871,10 @@ var Panel = ({
|
|
|
24871
24871
|
style: {
|
|
24872
24872
|
position: "relative",
|
|
24873
24873
|
zIndex: 1,
|
|
24874
|
-
height: "100%"
|
|
24874
|
+
height: "100%",
|
|
24875
|
+
display: "flex",
|
|
24876
|
+
flexDirection: "column",
|
|
24877
|
+
minHeight: 0
|
|
24875
24878
|
},
|
|
24876
24879
|
children
|
|
24877
24880
|
}
|
|
@@ -24911,12 +24914,13 @@ var User = ({
|
|
|
24911
24914
|
);
|
|
24912
24915
|
|
|
24913
24916
|
// source/version.ts
|
|
24914
|
-
var EPIQ_VERSION = "1.
|
|
24917
|
+
var EPIQ_VERSION = "1.3.1";
|
|
24915
24918
|
|
|
24916
24919
|
// source/gui/client/components/Header.tsx
|
|
24917
24920
|
var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
|
|
24918
24921
|
var Header = ({ state, connected, syncStatus }) => {
|
|
24919
24922
|
const syncColor = syncStatus.status === "synced" ? GUI_THEME.green : syncStatus.status === "failed" ? GUI_THEME.red : GUI_THEME.accent;
|
|
24923
|
+
const syncLabel = syncStatus.status === "failed" ? "-" : syncStatus.msg.toLowerCase();
|
|
24920
24924
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
24921
24925
|
Panel,
|
|
24922
24926
|
{
|
|
@@ -24986,12 +24990,17 @@ var Header = ({ state, connected, syncStatus }) => {
|
|
|
24986
24990
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
24987
24991
|
"span",
|
|
24988
24992
|
{
|
|
24993
|
+
title: syncStatus.status === "failed" ? syncStatus.msg : void 0,
|
|
24989
24994
|
style: {
|
|
24990
24995
|
color: GUI_THEME.dim,
|
|
24991
24996
|
minWidth: 72,
|
|
24997
|
+
maxWidth: 220,
|
|
24998
|
+
overflow: "hidden",
|
|
24999
|
+
textOverflow: "ellipsis",
|
|
25000
|
+
whiteSpace: "nowrap",
|
|
24992
25001
|
textAlign: "right"
|
|
24993
25002
|
},
|
|
24994
|
-
children: connected ?
|
|
25003
|
+
children: connected ? syncLabel : "-"
|
|
24995
25004
|
}
|
|
24996
25005
|
),
|
|
24997
25006
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
@@ -25042,7 +25051,7 @@ var Header = ({ state, connected, syncStatus }) => {
|
|
|
25042
25051
|
};
|
|
25043
25052
|
|
|
25044
25053
|
// source/gui/client/components/IssueDetails.tsx
|
|
25045
|
-
var
|
|
25054
|
+
var import_react7 = __toESM(require_react(), 1);
|
|
25046
25055
|
|
|
25047
25056
|
// source/gui/client/components/Aside.tsx
|
|
25048
25057
|
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
@@ -25108,7 +25117,7 @@ var CopyRef = ({ refValue }) => {
|
|
|
25108
25117
|
onMouseLeave: (event) => {
|
|
25109
25118
|
event.currentTarget.style.color = copied ? GUI_THEME.green : GUI_THEME.dim;
|
|
25110
25119
|
},
|
|
25111
|
-
children: copied ? "copied!" :
|
|
25120
|
+
children: copied ? "copied!" : refValue
|
|
25112
25121
|
}
|
|
25113
25122
|
);
|
|
25114
25123
|
};
|
|
@@ -25182,9 +25191,299 @@ var AddRow = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("di
|
|
|
25182
25191
|
var ChipRow = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: "flex", gap: 8, flexWrap: "wrap", marginTop: 10 }, children });
|
|
25183
25192
|
var Empty = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { display: "inline-block", marginTop: 8, color: GUI_THEME.dim }, children });
|
|
25184
25193
|
|
|
25185
|
-
// source/gui/client/components/
|
|
25194
|
+
// source/gui/client/components/IssueAttachments.tsx
|
|
25186
25195
|
var import_react5 = __toESM(require_react(), 1);
|
|
25187
25196
|
|
|
25197
|
+
// source/gui/client/components/Section.tsx
|
|
25198
|
+
var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
|
|
25199
|
+
var Section = ({
|
|
25200
|
+
title,
|
|
25201
|
+
action,
|
|
25202
|
+
children,
|
|
25203
|
+
first = false
|
|
25204
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
25205
|
+
"section",
|
|
25206
|
+
{
|
|
25207
|
+
style: {
|
|
25208
|
+
padding: first ? "0px 0 14px 0" : "14px 0",
|
|
25209
|
+
borderTop: first ? "none" : `1px solid ${GUI_THEME.line}`
|
|
25210
|
+
},
|
|
25211
|
+
children: [
|
|
25212
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
25213
|
+
"div",
|
|
25214
|
+
{
|
|
25215
|
+
style: {
|
|
25216
|
+
display: "flex",
|
|
25217
|
+
justifyContent: "space-between",
|
|
25218
|
+
alignItems: "center",
|
|
25219
|
+
gap: 12
|
|
25220
|
+
},
|
|
25221
|
+
children: [
|
|
25222
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
25223
|
+
"span",
|
|
25224
|
+
{
|
|
25225
|
+
style: {
|
|
25226
|
+
color: GUI_THEME.secondary,
|
|
25227
|
+
fontSize: 10,
|
|
25228
|
+
textTransform: "uppercase",
|
|
25229
|
+
letterSpacing: "0.08em"
|
|
25230
|
+
},
|
|
25231
|
+
children: title
|
|
25232
|
+
}
|
|
25233
|
+
),
|
|
25234
|
+
action
|
|
25235
|
+
]
|
|
25236
|
+
}
|
|
25237
|
+
),
|
|
25238
|
+
children
|
|
25239
|
+
]
|
|
25240
|
+
}
|
|
25241
|
+
);
|
|
25242
|
+
|
|
25243
|
+
// source/gui/client/components/IssueAttachments.tsx
|
|
25244
|
+
var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
|
|
25245
|
+
var IssueAttachments = ({
|
|
25246
|
+
issueId,
|
|
25247
|
+
readonly,
|
|
25248
|
+
attachments,
|
|
25249
|
+
uploadStatus,
|
|
25250
|
+
onUploadFiles,
|
|
25251
|
+
onDeleteAttachment
|
|
25252
|
+
}) => {
|
|
25253
|
+
const [dragging, setDragging] = (0, import_react5.useState)(false);
|
|
25254
|
+
const [lightbox, setLightbox] = (0, import_react5.useState)(null);
|
|
25255
|
+
const [broken, setBroken] = (0, import_react5.useState)({});
|
|
25256
|
+
(0, import_react5.useEffect)(() => {
|
|
25257
|
+
setLightbox(null);
|
|
25258
|
+
setDragging(false);
|
|
25259
|
+
setBroken({});
|
|
25260
|
+
}, [issueId]);
|
|
25261
|
+
(0, import_react5.useEffect)(() => {
|
|
25262
|
+
if (!lightbox) return;
|
|
25263
|
+
const onKeyDown = (event) => {
|
|
25264
|
+
if (event.key === "Escape") setLightbox(null);
|
|
25265
|
+
};
|
|
25266
|
+
window.addEventListener("keydown", onKeyDown);
|
|
25267
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
25268
|
+
}, [lightbox]);
|
|
25269
|
+
const canUpload = !readonly && Boolean(onUploadFiles);
|
|
25270
|
+
const handleDrop = (event) => {
|
|
25271
|
+
event.preventDefault();
|
|
25272
|
+
setDragging(false);
|
|
25273
|
+
if (!canUpload) return;
|
|
25274
|
+
const files = Array.from(event.dataTransfer.files).filter(
|
|
25275
|
+
(file) => file.type.startsWith("image/")
|
|
25276
|
+
);
|
|
25277
|
+
if (files.length > 0) onUploadFiles?.(issueId, files);
|
|
25278
|
+
};
|
|
25279
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25280
|
+
Section,
|
|
25281
|
+
{
|
|
25282
|
+
title: `Attachments${attachments.length ? ` (${attachments.length})` : ""}`,
|
|
25283
|
+
children: [
|
|
25284
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25285
|
+
"div",
|
|
25286
|
+
{
|
|
25287
|
+
onDragOver: (event) => {
|
|
25288
|
+
if (!canUpload) return;
|
|
25289
|
+
event.preventDefault();
|
|
25290
|
+
setDragging(true);
|
|
25291
|
+
},
|
|
25292
|
+
onDragLeave: () => setDragging(false),
|
|
25293
|
+
onDrop: handleDrop,
|
|
25294
|
+
style: {
|
|
25295
|
+
marginTop: 8,
|
|
25296
|
+
padding: dragging ? 10 : 0,
|
|
25297
|
+
border: dragging ? `1px dashed ${GUI_THEME.accent}` : "1px dashed transparent",
|
|
25298
|
+
borderRadius: 4,
|
|
25299
|
+
transition: "padding 0.12s ease, border-color 0.12s ease"
|
|
25300
|
+
},
|
|
25301
|
+
children: [
|
|
25302
|
+
attachments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Empty, { children: canUpload ? "No attachments \u2014 drop an image here" : "No attachments" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25303
|
+
"div",
|
|
25304
|
+
{
|
|
25305
|
+
style: {
|
|
25306
|
+
display: "flex",
|
|
25307
|
+
flexWrap: "wrap",
|
|
25308
|
+
gap: 8
|
|
25309
|
+
},
|
|
25310
|
+
children: attachments.map((attachment) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25311
|
+
"div",
|
|
25312
|
+
{
|
|
25313
|
+
style: { position: "relative", width: 72, height: 72 },
|
|
25314
|
+
children: [
|
|
25315
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25316
|
+
"button",
|
|
25317
|
+
{
|
|
25318
|
+
type: "button",
|
|
25319
|
+
disabled: broken[attachment.id],
|
|
25320
|
+
onClick: () => setLightbox(attachment),
|
|
25321
|
+
title: `${attachment.name} (${Math.max(
|
|
25322
|
+
1,
|
|
25323
|
+
Math.round(attachment.bytes / 1024)
|
|
25324
|
+
)} KB)`,
|
|
25325
|
+
style: {
|
|
25326
|
+
padding: 0,
|
|
25327
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
25328
|
+
borderRadius: 4,
|
|
25329
|
+
background: GUI_THEME.panel2,
|
|
25330
|
+
cursor: broken[attachment.id] ? "default" : "zoom-in",
|
|
25331
|
+
overflow: "hidden",
|
|
25332
|
+
width: "100%",
|
|
25333
|
+
height: "100%"
|
|
25334
|
+
},
|
|
25335
|
+
children: broken[attachment.id] ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25336
|
+
"span",
|
|
25337
|
+
{
|
|
25338
|
+
title: "Attachment unavailable (missing, corrupt, or over the size cap)",
|
|
25339
|
+
style: {
|
|
25340
|
+
display: "flex",
|
|
25341
|
+
alignItems: "center",
|
|
25342
|
+
justifyContent: "center",
|
|
25343
|
+
width: "100%",
|
|
25344
|
+
height: "100%",
|
|
25345
|
+
color: GUI_THEME.dim2,
|
|
25346
|
+
fontSize: 9,
|
|
25347
|
+
padding: 4,
|
|
25348
|
+
textAlign: "center"
|
|
25349
|
+
},
|
|
25350
|
+
children: "unavailable"
|
|
25351
|
+
}
|
|
25352
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25353
|
+
"img",
|
|
25354
|
+
{
|
|
25355
|
+
src: `/media/${attachment.fileName}`,
|
|
25356
|
+
alt: attachment.name,
|
|
25357
|
+
loading: "lazy",
|
|
25358
|
+
onError: () => setBroken((prev) => ({ ...prev, [attachment.id]: true })),
|
|
25359
|
+
style: {
|
|
25360
|
+
width: "100%",
|
|
25361
|
+
height: "100%",
|
|
25362
|
+
objectFit: "cover",
|
|
25363
|
+
display: "block"
|
|
25364
|
+
}
|
|
25365
|
+
}
|
|
25366
|
+
)
|
|
25367
|
+
}
|
|
25368
|
+
),
|
|
25369
|
+
attachment.canDelete && !readonly && onDeleteAttachment && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25370
|
+
"button",
|
|
25371
|
+
{
|
|
25372
|
+
type: "button",
|
|
25373
|
+
title: "Delete attachment",
|
|
25374
|
+
onClick: () => onDeleteAttachment(issueId, attachment.id),
|
|
25375
|
+
style: {
|
|
25376
|
+
position: "absolute",
|
|
25377
|
+
top: 2,
|
|
25378
|
+
right: 2,
|
|
25379
|
+
width: 16,
|
|
25380
|
+
height: 16,
|
|
25381
|
+
lineHeight: "14px",
|
|
25382
|
+
padding: 0,
|
|
25383
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
25384
|
+
borderRadius: 3,
|
|
25385
|
+
background: "rgba(4, 5, 8, 0.75)",
|
|
25386
|
+
color: GUI_THEME.secondary,
|
|
25387
|
+
fontSize: 10,
|
|
25388
|
+
cursor: "pointer"
|
|
25389
|
+
},
|
|
25390
|
+
children: "\xD7"
|
|
25391
|
+
}
|
|
25392
|
+
)
|
|
25393
|
+
]
|
|
25394
|
+
},
|
|
25395
|
+
attachment.id
|
|
25396
|
+
))
|
|
25397
|
+
}
|
|
25398
|
+
),
|
|
25399
|
+
canUpload && attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25400
|
+
"div",
|
|
25401
|
+
{
|
|
25402
|
+
style: {
|
|
25403
|
+
marginTop: 8,
|
|
25404
|
+
color: GUI_THEME.dim2,
|
|
25405
|
+
fontSize: 10
|
|
25406
|
+
},
|
|
25407
|
+
children: "drop an image to attach"
|
|
25408
|
+
}
|
|
25409
|
+
),
|
|
25410
|
+
uploadStatus.state === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25411
|
+
"div",
|
|
25412
|
+
{
|
|
25413
|
+
style: {
|
|
25414
|
+
marginTop: 8,
|
|
25415
|
+
color: GUI_THEME.secondary,
|
|
25416
|
+
fontSize: 11
|
|
25417
|
+
},
|
|
25418
|
+
children: [
|
|
25419
|
+
"uploading ",
|
|
25420
|
+
uploadStatus.name,
|
|
25421
|
+
"\u2026"
|
|
25422
|
+
]
|
|
25423
|
+
}
|
|
25424
|
+
),
|
|
25425
|
+
uploadStatus.state === "error" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25426
|
+
"div",
|
|
25427
|
+
{
|
|
25428
|
+
style: {
|
|
25429
|
+
marginTop: 8,
|
|
25430
|
+
color: GUI_THEME.red,
|
|
25431
|
+
fontSize: 11
|
|
25432
|
+
},
|
|
25433
|
+
children: uploadStatus.message
|
|
25434
|
+
}
|
|
25435
|
+
)
|
|
25436
|
+
]
|
|
25437
|
+
}
|
|
25438
|
+
),
|
|
25439
|
+
lightbox && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25440
|
+
"div",
|
|
25441
|
+
{
|
|
25442
|
+
onClick: () => setLightbox(null),
|
|
25443
|
+
style: {
|
|
25444
|
+
position: "fixed",
|
|
25445
|
+
inset: 0,
|
|
25446
|
+
zIndex: 100,
|
|
25447
|
+
display: "flex",
|
|
25448
|
+
alignItems: "center",
|
|
25449
|
+
justifyContent: "center",
|
|
25450
|
+
flexDirection: "column",
|
|
25451
|
+
gap: 10,
|
|
25452
|
+
background: "rgba(4, 5, 8, 0.88)",
|
|
25453
|
+
cursor: "zoom-out"
|
|
25454
|
+
},
|
|
25455
|
+
children: [
|
|
25456
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25457
|
+
"img",
|
|
25458
|
+
{
|
|
25459
|
+
src: `/media/${lightbox.fileName}`,
|
|
25460
|
+
alt: lightbox.name,
|
|
25461
|
+
style: {
|
|
25462
|
+
maxWidth: "90vw",
|
|
25463
|
+
maxHeight: "85vh",
|
|
25464
|
+
borderRadius: 6,
|
|
25465
|
+
border: `1px solid ${GUI_THEME.line}`
|
|
25466
|
+
}
|
|
25467
|
+
}
|
|
25468
|
+
),
|
|
25469
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { color: GUI_THEME.secondary, fontSize: 11 }, children: [
|
|
25470
|
+
lightbox.name,
|
|
25471
|
+
" \xB7 ",
|
|
25472
|
+
Math.max(1, Math.round(lightbox.bytes / 1024)),
|
|
25473
|
+
" ",
|
|
25474
|
+
"KB \xB7 esc to close"
|
|
25475
|
+
] })
|
|
25476
|
+
]
|
|
25477
|
+
}
|
|
25478
|
+
)
|
|
25479
|
+
]
|
|
25480
|
+
}
|
|
25481
|
+
);
|
|
25482
|
+
};
|
|
25483
|
+
|
|
25484
|
+
// source/gui/client/components/IssueComments.tsx
|
|
25485
|
+
var import_react6 = __toESM(require_react(), 1);
|
|
25486
|
+
|
|
25188
25487
|
// source/gui/client/lib/gui-format.helper.ts
|
|
25189
25488
|
var timeAgo = (timestampMs) => {
|
|
25190
25489
|
const diff = Date.now() - timestampMs;
|
|
@@ -25205,7 +25504,7 @@ var timeAgo = (timestampMs) => {
|
|
|
25205
25504
|
};
|
|
25206
25505
|
|
|
25207
25506
|
// source/gui/client/components/IssueComments.tsx
|
|
25208
|
-
var
|
|
25507
|
+
var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
|
|
25209
25508
|
var IssueComments = ({
|
|
25210
25509
|
whoAmI,
|
|
25211
25510
|
issueId,
|
|
@@ -25214,15 +25513,15 @@ var IssueComments = ({
|
|
|
25214
25513
|
onAddComment,
|
|
25215
25514
|
onDeleteComment
|
|
25216
25515
|
}) => {
|
|
25217
|
-
const [body, setBody] = (0,
|
|
25516
|
+
const [body, setBody] = (0, import_react6.useState)("");
|
|
25218
25517
|
const addComment = () => {
|
|
25219
25518
|
const nextBody = body.trim();
|
|
25220
25519
|
if (!nextBody) return;
|
|
25221
25520
|
onAddComment?.(issueId, nextBody);
|
|
25222
25521
|
setBody("");
|
|
25223
25522
|
};
|
|
25224
|
-
return /* @__PURE__ */ (0,
|
|
25225
|
-
comments.length === 0 ? /* @__PURE__ */ (0,
|
|
25523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
25524
|
+
comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Empty, { children: "No comments" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: comments.map((comment) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
25226
25525
|
"div",
|
|
25227
25526
|
{
|
|
25228
25527
|
style: {
|
|
@@ -25232,7 +25531,7 @@ var IssueComments = ({
|
|
|
25232
25531
|
background: GUI_THEME.tertiary
|
|
25233
25532
|
},
|
|
25234
25533
|
children: [
|
|
25235
|
-
/* @__PURE__ */ (0,
|
|
25534
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
25236
25535
|
"div",
|
|
25237
25536
|
{
|
|
25238
25537
|
style: {
|
|
@@ -25242,15 +25541,15 @@ var IssueComments = ({
|
|
|
25242
25541
|
marginBottom: 8
|
|
25243
25542
|
},
|
|
25244
25543
|
children: [
|
|
25245
|
-
/* @__PURE__ */ (0,
|
|
25544
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { color: GUI_THEME.secondary, fontSize: 10 }, children: [
|
|
25246
25545
|
comment.author.name ?? "unknown",
|
|
25247
|
-
comment.createdAt && /* @__PURE__ */ (0,
|
|
25546
|
+
comment.createdAt && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { style: { color: GUI_THEME.dim2 }, children: [
|
|
25248
25547
|
" ",
|
|
25249
25548
|
"\xB7 ",
|
|
25250
25549
|
timeAgo(comment.createdAt)
|
|
25251
25550
|
] })
|
|
25252
25551
|
] }),
|
|
25253
|
-
comment.author.id === whoAmI.id && onDeleteComment && /* @__PURE__ */ (0,
|
|
25552
|
+
comment.author.id === whoAmI.id && onDeleteComment && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25254
25553
|
Button,
|
|
25255
25554
|
{
|
|
25256
25555
|
variant: "ghost",
|
|
@@ -25265,7 +25564,7 @@ var IssueComments = ({
|
|
|
25265
25564
|
]
|
|
25266
25565
|
}
|
|
25267
25566
|
),
|
|
25268
|
-
/* @__PURE__ */ (0,
|
|
25567
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25269
25568
|
"div",
|
|
25270
25569
|
{
|
|
25271
25570
|
style: {
|
|
@@ -25280,8 +25579,8 @@ var IssueComments = ({
|
|
|
25280
25579
|
},
|
|
25281
25580
|
comment.id
|
|
25282
25581
|
)) }),
|
|
25283
|
-
!readonly && /* @__PURE__ */ (0,
|
|
25284
|
-
/* @__PURE__ */ (0,
|
|
25582
|
+
!readonly && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginTop: 18 }, children: [
|
|
25583
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25285
25584
|
Textarea,
|
|
25286
25585
|
{
|
|
25287
25586
|
maxLength: 120,
|
|
@@ -25296,64 +25595,18 @@ var IssueComments = ({
|
|
|
25296
25595
|
style: { minHeight: 45 }
|
|
25297
25596
|
}
|
|
25298
25597
|
),
|
|
25299
|
-
/* @__PURE__ */ (0,
|
|
25598
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ActionRow, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { onClick: addComment, children: "comment" }) })
|
|
25300
25599
|
] })
|
|
25301
25600
|
] });
|
|
25302
25601
|
};
|
|
25303
25602
|
|
|
25304
|
-
// source/gui/client/components/Section.tsx
|
|
25305
|
-
var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
|
|
25306
|
-
var Section = ({
|
|
25307
|
-
title,
|
|
25308
|
-
action,
|
|
25309
|
-
children,
|
|
25310
|
-
first = false
|
|
25311
|
-
}) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25312
|
-
"section",
|
|
25313
|
-
{
|
|
25314
|
-
style: {
|
|
25315
|
-
padding: first ? "0px 0 14px 0" : "14px 0",
|
|
25316
|
-
borderTop: first ? "none" : `1px solid ${GUI_THEME.line}`
|
|
25317
|
-
},
|
|
25318
|
-
children: [
|
|
25319
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25320
|
-
"div",
|
|
25321
|
-
{
|
|
25322
|
-
style: {
|
|
25323
|
-
display: "flex",
|
|
25324
|
-
justifyContent: "space-between",
|
|
25325
|
-
alignItems: "center",
|
|
25326
|
-
gap: 12
|
|
25327
|
-
},
|
|
25328
|
-
children: [
|
|
25329
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25330
|
-
"span",
|
|
25331
|
-
{
|
|
25332
|
-
style: {
|
|
25333
|
-
color: GUI_THEME.secondary,
|
|
25334
|
-
fontSize: 10,
|
|
25335
|
-
textTransform: "uppercase",
|
|
25336
|
-
letterSpacing: "0.08em"
|
|
25337
|
-
},
|
|
25338
|
-
children: title
|
|
25339
|
-
}
|
|
25340
|
-
),
|
|
25341
|
-
action
|
|
25342
|
-
]
|
|
25343
|
-
}
|
|
25344
|
-
),
|
|
25345
|
-
children
|
|
25346
|
-
]
|
|
25347
|
-
}
|
|
25348
|
-
);
|
|
25349
|
-
|
|
25350
25603
|
// source/gui/client/components/Tabs.tsx
|
|
25351
|
-
var
|
|
25604
|
+
var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
|
|
25352
25605
|
var Tabs = ({
|
|
25353
25606
|
activeTab,
|
|
25354
25607
|
tabs,
|
|
25355
25608
|
onChange
|
|
25356
|
-
}) => /* @__PURE__ */ (0,
|
|
25609
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
25357
25610
|
"div",
|
|
25358
25611
|
{
|
|
25359
25612
|
style: {
|
|
@@ -25364,7 +25617,7 @@ var Tabs = ({
|
|
|
25364
25617
|
},
|
|
25365
25618
|
children: tabs.map((tab) => {
|
|
25366
25619
|
const active = tab.id === activeTab;
|
|
25367
|
-
return /* @__PURE__ */ (0,
|
|
25620
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
25368
25621
|
"button",
|
|
25369
25622
|
{
|
|
25370
25623
|
type: "button",
|
|
@@ -25382,7 +25635,7 @@ var Tabs = ({
|
|
|
25382
25635
|
},
|
|
25383
25636
|
children: [
|
|
25384
25637
|
tab.label,
|
|
25385
|
-
typeof tab.count === "number" && /* @__PURE__ */ (0,
|
|
25638
|
+
typeof tab.count === "number" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
25386
25639
|
"span",
|
|
25387
25640
|
{
|
|
25388
25641
|
style: { color: tab.count ? GUI_THEME.secondary : GUI_THEME.dim },
|
|
@@ -25403,7 +25656,7 @@ var Tabs = ({
|
|
|
25403
25656
|
);
|
|
25404
25657
|
|
|
25405
25658
|
// source/gui/client/components/IssueDetails.tsx
|
|
25406
|
-
var
|
|
25659
|
+
var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
|
|
25407
25660
|
var IssueDetails = ({
|
|
25408
25661
|
whoAmI,
|
|
25409
25662
|
comments,
|
|
@@ -25421,18 +25674,22 @@ var IssueDetails = ({
|
|
|
25421
25674
|
onReopenIssue,
|
|
25422
25675
|
onAddComment,
|
|
25423
25676
|
onDeleteComment,
|
|
25677
|
+
attachments,
|
|
25678
|
+
attachmentUploadStatus,
|
|
25679
|
+
onUploadAttachments,
|
|
25680
|
+
onDeleteAttachment,
|
|
25424
25681
|
knownTags: tags,
|
|
25425
25682
|
knownAssignees: assignees
|
|
25426
25683
|
}) => {
|
|
25427
|
-
const [title, setTitle] = (0,
|
|
25428
|
-
const [description, setDescription] = (0,
|
|
25429
|
-
const [tagName, setTagName] = (0,
|
|
25430
|
-
const [assigneeName, setAssigneeName] = (0,
|
|
25431
|
-
const [editingTitle, setEditingTitle] = (0,
|
|
25432
|
-
const [editingDescription, setEditingDescription] = (0,
|
|
25433
|
-
const [addingTag, setAddingTag] = (0,
|
|
25434
|
-
const [addingAssignee, setAddingAssignee] = (0,
|
|
25435
|
-
(0,
|
|
25684
|
+
const [title, setTitle] = (0, import_react7.useState)("");
|
|
25685
|
+
const [description, setDescription] = (0, import_react7.useState)("");
|
|
25686
|
+
const [tagName, setTagName] = (0, import_react7.useState)("");
|
|
25687
|
+
const [assigneeName, setAssigneeName] = (0, import_react7.useState)("");
|
|
25688
|
+
const [editingTitle, setEditingTitle] = (0, import_react7.useState)(false);
|
|
25689
|
+
const [editingDescription, setEditingDescription] = (0, import_react7.useState)(false);
|
|
25690
|
+
const [addingTag, setAddingTag] = (0, import_react7.useState)(false);
|
|
25691
|
+
const [addingAssignee, setAddingAssignee] = (0, import_react7.useState)(false);
|
|
25692
|
+
(0, import_react7.useEffect)(() => {
|
|
25436
25693
|
setTitle(issue?.title ?? "");
|
|
25437
25694
|
setDescription(issue?.description ?? "");
|
|
25438
25695
|
setTagName("");
|
|
@@ -25492,9 +25749,9 @@ var IssueDetails = ({
|
|
|
25492
25749
|
const availableAssignees = assignees.filter(
|
|
25493
25750
|
(assignee) => !issue?.assignees.some((issueAssignee) => issueAssignee.id === assignee.id)
|
|
25494
25751
|
);
|
|
25495
|
-
return /* @__PURE__ */ (0,
|
|
25496
|
-
/* @__PURE__ */ (0,
|
|
25497
|
-
/* @__PURE__ */ (0,
|
|
25752
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Aside, { children: issue ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
25753
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(FormHeader, { children: [
|
|
25754
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25498
25755
|
"span",
|
|
25499
25756
|
{
|
|
25500
25757
|
style: {
|
|
@@ -25503,19 +25760,19 @@ var IssueDetails = ({
|
|
|
25503
25760
|
textTransform: "uppercase",
|
|
25504
25761
|
letterSpacing: "0.08em"
|
|
25505
25762
|
},
|
|
25506
|
-
children: issue.ref && /* @__PURE__ */ (0,
|
|
25763
|
+
children: issue.ref && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CopyRef, { refValue: issue.ref })
|
|
25507
25764
|
}
|
|
25508
25765
|
),
|
|
25509
|
-
/* @__PURE__ */ (0,
|
|
25766
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "ghost", onClick: onClose, children: "\xD7" })
|
|
25510
25767
|
] }),
|
|
25511
|
-
/* @__PURE__ */ (0,
|
|
25512
|
-
activeTab === "overview" && /* @__PURE__ */ (0,
|
|
25513
|
-
/* @__PURE__ */ (0,
|
|
25768
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Tabs, { tabs, activeTab, onChange: onChangeTab }),
|
|
25769
|
+
activeTab === "overview" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
25770
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25514
25771
|
Section,
|
|
25515
25772
|
{
|
|
25516
25773
|
first: true,
|
|
25517
25774
|
title: "Title",
|
|
25518
|
-
action: !issue.readonly && !editingTitle && /* @__PURE__ */ (0,
|
|
25775
|
+
action: !issue.readonly && !editingTitle && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25519
25776
|
Button,
|
|
25520
25777
|
{
|
|
25521
25778
|
variant: "ghost",
|
|
@@ -25523,8 +25780,8 @@ var IssueDetails = ({
|
|
|
25523
25780
|
children: "edit"
|
|
25524
25781
|
}
|
|
25525
25782
|
),
|
|
25526
|
-
children: editingTitle ? /* @__PURE__ */ (0,
|
|
25527
|
-
/* @__PURE__ */ (0,
|
|
25783
|
+
children: editingTitle ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
25784
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25528
25785
|
Input,
|
|
25529
25786
|
{
|
|
25530
25787
|
value: title,
|
|
@@ -25536,11 +25793,11 @@ var IssueDetails = ({
|
|
|
25536
25793
|
}
|
|
25537
25794
|
}
|
|
25538
25795
|
),
|
|
25539
|
-
/* @__PURE__ */ (0,
|
|
25540
|
-
/* @__PURE__ */ (0,
|
|
25541
|
-
/* @__PURE__ */ (0,
|
|
25796
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(ActionRow, { children: [
|
|
25797
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: saveTitle, children: "save" }),
|
|
25798
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "ghost", onClick: cancelTitle, children: "cancel" })
|
|
25542
25799
|
] })
|
|
25543
|
-
] }) : /* @__PURE__ */ (0,
|
|
25800
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25544
25801
|
"div",
|
|
25545
25802
|
{
|
|
25546
25803
|
style: {
|
|
@@ -25555,11 +25812,11 @@ var IssueDetails = ({
|
|
|
25555
25812
|
)
|
|
25556
25813
|
}
|
|
25557
25814
|
),
|
|
25558
|
-
/* @__PURE__ */ (0,
|
|
25815
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25559
25816
|
Section,
|
|
25560
25817
|
{
|
|
25561
25818
|
title: "Description",
|
|
25562
|
-
action: !issue.readonly && !editingDescription && /* @__PURE__ */ (0,
|
|
25819
|
+
action: !issue.readonly && !editingDescription && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25563
25820
|
Button,
|
|
25564
25821
|
{
|
|
25565
25822
|
variant: "ghost",
|
|
@@ -25567,8 +25824,8 @@ var IssueDetails = ({
|
|
|
25567
25824
|
children: "edit"
|
|
25568
25825
|
}
|
|
25569
25826
|
),
|
|
25570
|
-
children: editingDescription ? /* @__PURE__ */ (0,
|
|
25571
|
-
/* @__PURE__ */ (0,
|
|
25827
|
+
children: editingDescription ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
25828
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25572
25829
|
Textarea,
|
|
25573
25830
|
{
|
|
25574
25831
|
value: description,
|
|
@@ -25583,31 +25840,34 @@ var IssueDetails = ({
|
|
|
25583
25840
|
}
|
|
25584
25841
|
}
|
|
25585
25842
|
),
|
|
25586
|
-
/* @__PURE__ */ (0,
|
|
25587
|
-
/* @__PURE__ */ (0,
|
|
25588
|
-
/* @__PURE__ */ (0,
|
|
25843
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(ActionRow, { children: [
|
|
25844
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: saveDescription, children: "save" }),
|
|
25845
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "ghost", onClick: cancelDescription, children: "cancel" })
|
|
25589
25846
|
] })
|
|
25590
|
-
] }) : issue.description ? /* @__PURE__ */ (0,
|
|
25847
|
+
] }) : issue.description ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25591
25848
|
"p",
|
|
25592
25849
|
{
|
|
25593
25850
|
style: {
|
|
25594
25851
|
lineHeight: 1.55,
|
|
25595
25852
|
whiteSpace: "pre-wrap",
|
|
25596
25853
|
margin: "8px 0 0",
|
|
25854
|
+
padding: "12px 16px",
|
|
25855
|
+
background: "rgba(0, 0, 0, 0.22)",
|
|
25856
|
+
borderRadius: 8,
|
|
25597
25857
|
color: GUI_THEME.primary
|
|
25598
25858
|
},
|
|
25599
25859
|
children: issue.description
|
|
25600
25860
|
}
|
|
25601
|
-
) : /* @__PURE__ */ (0,
|
|
25861
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Empty, { children: "No description" })
|
|
25602
25862
|
}
|
|
25603
25863
|
),
|
|
25604
|
-
/* @__PURE__ */ (0,
|
|
25864
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25605
25865
|
Section,
|
|
25606
25866
|
{
|
|
25607
25867
|
title: "Tags",
|
|
25608
|
-
action: !issue.readonly && !addingTag && /* @__PURE__ */ (0,
|
|
25868
|
+
action: !issue.readonly && !addingTag && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "ghost", onClick: () => setAddingTag(true), children: "+" }) || addingTag && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "ghost", onClick: () => setAddingTag(false), children: "-" }),
|
|
25609
25869
|
children: [
|
|
25610
|
-
/* @__PURE__ */ (0,
|
|
25870
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChipRow, { children: issue.tags.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Empty, { children: "No tags" }) : issue.tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25611
25871
|
Button,
|
|
25612
25872
|
{
|
|
25613
25873
|
variant: "chip",
|
|
@@ -25623,7 +25883,7 @@ var IssueDetails = ({
|
|
|
25623
25883
|
},
|
|
25624
25884
|
tag.id
|
|
25625
25885
|
)) }),
|
|
25626
|
-
addingTag && /* @__PURE__ */ (0,
|
|
25886
|
+
addingTag && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChipRow, { children: availableTags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25627
25887
|
Button,
|
|
25628
25888
|
{
|
|
25629
25889
|
variant: "chip",
|
|
@@ -25638,8 +25898,8 @@ var IssueDetails = ({
|
|
|
25638
25898
|
},
|
|
25639
25899
|
tag.id
|
|
25640
25900
|
)) }),
|
|
25641
|
-
addingTag && /* @__PURE__ */ (0,
|
|
25642
|
-
/* @__PURE__ */ (0,
|
|
25901
|
+
addingTag && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(AddRow, { children: [
|
|
25902
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25643
25903
|
Input,
|
|
25644
25904
|
{
|
|
25645
25905
|
value: tagName,
|
|
@@ -25655,23 +25915,23 @@ var IssueDetails = ({
|
|
|
25655
25915
|
}
|
|
25656
25916
|
}
|
|
25657
25917
|
),
|
|
25658
|
-
/* @__PURE__ */ (0,
|
|
25918
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: addTag, children: "add" })
|
|
25659
25919
|
] })
|
|
25660
25920
|
]
|
|
25661
25921
|
}
|
|
25662
25922
|
),
|
|
25663
|
-
/* @__PURE__ */ (0,
|
|
25923
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25664
25924
|
Section,
|
|
25665
25925
|
{
|
|
25666
25926
|
title: "Assignees",
|
|
25667
|
-
action: !issue.readonly && !addingAssignee && /* @__PURE__ */ (0,
|
|
25927
|
+
action: !issue.readonly && !addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25668
25928
|
Button,
|
|
25669
25929
|
{
|
|
25670
25930
|
variant: "ghost",
|
|
25671
25931
|
onClick: () => setAddingAssignee(true),
|
|
25672
25932
|
children: "+"
|
|
25673
25933
|
}
|
|
25674
|
-
) || addingAssignee && /* @__PURE__ */ (0,
|
|
25934
|
+
) || addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25675
25935
|
Button,
|
|
25676
25936
|
{
|
|
25677
25937
|
variant: "ghost",
|
|
@@ -25680,7 +25940,7 @@ var IssueDetails = ({
|
|
|
25680
25940
|
}
|
|
25681
25941
|
),
|
|
25682
25942
|
children: [
|
|
25683
|
-
/* @__PURE__ */ (0,
|
|
25943
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChipRow, { children: issue.assignees.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Empty, { children: "No assignees" }) : issue.assignees.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25684
25944
|
Button,
|
|
25685
25945
|
{
|
|
25686
25946
|
variant: "chip",
|
|
@@ -25697,7 +25957,7 @@ var IssueDetails = ({
|
|
|
25697
25957
|
},
|
|
25698
25958
|
assignee.id
|
|
25699
25959
|
)) }),
|
|
25700
|
-
addingAssignee && /* @__PURE__ */ (0,
|
|
25960
|
+
addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChipRow, { children: availableAssignees.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25701
25961
|
Button,
|
|
25702
25962
|
{
|
|
25703
25963
|
variant: "chip",
|
|
@@ -25712,8 +25972,8 @@ var IssueDetails = ({
|
|
|
25712
25972
|
},
|
|
25713
25973
|
assignee.id
|
|
25714
25974
|
)) }),
|
|
25715
|
-
addingAssignee && /* @__PURE__ */ (0,
|
|
25716
|
-
/* @__PURE__ */ (0,
|
|
25975
|
+
addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(AddRow, { children: [
|
|
25976
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25717
25977
|
Input,
|
|
25718
25978
|
{
|
|
25719
25979
|
value: assigneeName,
|
|
@@ -25729,21 +25989,32 @@ var IssueDetails = ({
|
|
|
25729
25989
|
}
|
|
25730
25990
|
}
|
|
25731
25991
|
),
|
|
25732
|
-
/* @__PURE__ */ (0,
|
|
25992
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: addAssignee, children: "add" })
|
|
25733
25993
|
] })
|
|
25734
25994
|
]
|
|
25735
25995
|
}
|
|
25736
25996
|
),
|
|
25737
|
-
/* @__PURE__ */ (0,
|
|
25997
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25998
|
+
IssueAttachments,
|
|
25999
|
+
{
|
|
26000
|
+
issueId: issue.id,
|
|
26001
|
+
readonly: Boolean(issue.readonly),
|
|
26002
|
+
attachments,
|
|
26003
|
+
uploadStatus: attachmentUploadStatus,
|
|
26004
|
+
onUploadFiles: onUploadAttachments,
|
|
26005
|
+
onDeleteAttachment
|
|
26006
|
+
}
|
|
26007
|
+
),
|
|
26008
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25738
26009
|
Section,
|
|
25739
26010
|
{
|
|
25740
26011
|
title: "Actions",
|
|
25741
|
-
action: issue.isClosed ? /* @__PURE__ */ (0,
|
|
26012
|
+
action: issue.isClosed ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: () => onReopenIssue(issue.id), children: "reopen issue" }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: () => onCloseIssue(issue.id), children: "close issue" }),
|
|
25742
26013
|
children: ""
|
|
25743
26014
|
}
|
|
25744
26015
|
)
|
|
25745
26016
|
] }),
|
|
25746
|
-
activeTab === "comments" && /* @__PURE__ */ (0,
|
|
26017
|
+
activeTab === "comments" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25747
26018
|
IssueComments,
|
|
25748
26019
|
{
|
|
25749
26020
|
whoAmI,
|
|
@@ -25754,15 +26025,15 @@ var IssueDetails = ({
|
|
|
25754
26025
|
onDeleteComment
|
|
25755
26026
|
}
|
|
25756
26027
|
)
|
|
25757
|
-
] }) : /* @__PURE__ */ (0,
|
|
26028
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Empty, { children: "Select an issue" }) });
|
|
25758
26029
|
};
|
|
25759
26030
|
|
|
25760
26031
|
// source/gui/client/components/SwimlaneColumn.tsx
|
|
25761
|
-
var
|
|
26032
|
+
var import_react8 = __toESM(require_react(), 1);
|
|
25762
26033
|
|
|
25763
26034
|
// source/gui/client/components/IconComment.tsx
|
|
25764
|
-
var
|
|
25765
|
-
var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
26035
|
+
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
26036
|
+
var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
25766
26037
|
"svg",
|
|
25767
26038
|
{
|
|
25768
26039
|
width: size,
|
|
@@ -25770,7 +26041,7 @@ var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.js
|
|
|
25770
26041
|
viewBox: "0 0 16 16",
|
|
25771
26042
|
fill: "none",
|
|
25772
26043
|
"aria-hidden": "true",
|
|
25773
|
-
children: /* @__PURE__ */ (0,
|
|
26044
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
25774
26045
|
"path",
|
|
25775
26046
|
{
|
|
25776
26047
|
d: "M3.9 2.6h5.2a2.4 2.4 0 0 1 2.4 2.4v2.5a2.4 2.4 0 0 1-2.4 2.4H6.6l-1.8 2.1.2-2.1H3.9a2.4 2.4 0 0 1-2.4-2.4V5a2.4 2.4 0 0 1 2.4-2.4Z",
|
|
@@ -25785,7 +26056,7 @@ var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.js
|
|
|
25785
26056
|
);
|
|
25786
26057
|
|
|
25787
26058
|
// source/gui/client/components/TicketCard.tsx
|
|
25788
|
-
var
|
|
26059
|
+
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
25789
26060
|
var TicketCard = ({
|
|
25790
26061
|
ticket,
|
|
25791
26062
|
index,
|
|
@@ -25798,7 +26069,7 @@ var TicketCard = ({
|
|
|
25798
26069
|
onDropIssueAt
|
|
25799
26070
|
}) => {
|
|
25800
26071
|
const getVisualTargetIndex = (isAfterMiddle) => index + (isAfterMiddle ? 1 : 0);
|
|
25801
|
-
return /* @__PURE__ */ (0,
|
|
26072
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25802
26073
|
"div",
|
|
25803
26074
|
{
|
|
25804
26075
|
draggable: !ticket.readonly,
|
|
@@ -25839,7 +26110,7 @@ var TicketCard = ({
|
|
|
25839
26110
|
border: `1px solid ${isSelected ? GUI_THEME.accent : "transparent"}`
|
|
25840
26111
|
},
|
|
25841
26112
|
children: [
|
|
25842
|
-
/* @__PURE__ */ (0,
|
|
26113
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25843
26114
|
"div",
|
|
25844
26115
|
{
|
|
25845
26116
|
style: {
|
|
@@ -25852,7 +26123,7 @@ var TicketCard = ({
|
|
|
25852
26123
|
children: isSelected ? "\u276F" : index + 1
|
|
25853
26124
|
}
|
|
25854
26125
|
),
|
|
25855
|
-
/* @__PURE__ */ (0,
|
|
26126
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25856
26127
|
"div",
|
|
25857
26128
|
{
|
|
25858
26129
|
style: {
|
|
@@ -25863,7 +26134,7 @@ var TicketCard = ({
|
|
|
25863
26134
|
gap: 12
|
|
25864
26135
|
},
|
|
25865
26136
|
children: [
|
|
25866
|
-
/* @__PURE__ */ (0,
|
|
26137
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25867
26138
|
"div",
|
|
25868
26139
|
{
|
|
25869
26140
|
style: {
|
|
@@ -25874,7 +26145,7 @@ var TicketCard = ({
|
|
|
25874
26145
|
flex: 1
|
|
25875
26146
|
},
|
|
25876
26147
|
children: [
|
|
25877
|
-
/* @__PURE__ */ (0,
|
|
26148
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25878
26149
|
"div",
|
|
25879
26150
|
{
|
|
25880
26151
|
style: {
|
|
@@ -25884,10 +26155,10 @@ var TicketCard = ({
|
|
|
25884
26155
|
fontWeight: 500,
|
|
25885
26156
|
fontSize: 12
|
|
25886
26157
|
},
|
|
25887
|
-
children: ticket.ref && /* @__PURE__ */ (0,
|
|
26158
|
+
children: ticket.ref && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { marginRight: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CopyRef, { refValue: ticket.ref }) })
|
|
25888
26159
|
}
|
|
25889
26160
|
),
|
|
25890
|
-
/* @__PURE__ */ (0,
|
|
26161
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25891
26162
|
"div",
|
|
25892
26163
|
{
|
|
25893
26164
|
style: {
|
|
@@ -25900,7 +26171,7 @@ var TicketCard = ({
|
|
|
25900
26171
|
children: ticket.title
|
|
25901
26172
|
}
|
|
25902
26173
|
),
|
|
25903
|
-
/* @__PURE__ */ (0,
|
|
26174
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25904
26175
|
"div",
|
|
25905
26176
|
{
|
|
25906
26177
|
style: {
|
|
@@ -25909,7 +26180,7 @@ var TicketCard = ({
|
|
|
25909
26180
|
gap: 6,
|
|
25910
26181
|
alignItems: "center"
|
|
25911
26182
|
},
|
|
25912
|
-
children: ticket.tags.map((tag) => /* @__PURE__ */ (0,
|
|
26183
|
+
children: ticket.tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25913
26184
|
"span",
|
|
25914
26185
|
{
|
|
25915
26186
|
style: {
|
|
@@ -25929,7 +26200,7 @@ var TicketCard = ({
|
|
|
25929
26200
|
]
|
|
25930
26201
|
}
|
|
25931
26202
|
),
|
|
25932
|
-
/* @__PURE__ */ (0,
|
|
26203
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25933
26204
|
"div",
|
|
25934
26205
|
{
|
|
25935
26206
|
style: {
|
|
@@ -25939,7 +26210,7 @@ var TicketCard = ({
|
|
|
25939
26210
|
flexShrink: 0,
|
|
25940
26211
|
paddingTop: 2
|
|
25941
26212
|
},
|
|
25942
|
-
children: commentCount > 0 && /* @__PURE__ */ (0,
|
|
26213
|
+
children: commentCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25943
26214
|
"button",
|
|
25944
26215
|
{
|
|
25945
26216
|
type: "button",
|
|
@@ -25977,14 +26248,14 @@ var TicketCard = ({
|
|
|
25977
26248
|
event.currentTarget.style.transform = "translateY(0)";
|
|
25978
26249
|
},
|
|
25979
26250
|
children: [
|
|
25980
|
-
/* @__PURE__ */ (0,
|
|
25981
|
-
/* @__PURE__ */ (0,
|
|
26251
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconComment, {}),
|
|
26252
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: commentCount })
|
|
25982
26253
|
]
|
|
25983
26254
|
}
|
|
25984
26255
|
)
|
|
25985
26256
|
}
|
|
25986
26257
|
),
|
|
25987
|
-
ticket.assignees.length > 0 && /* @__PURE__ */ (0,
|
|
26258
|
+
ticket.assignees.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25988
26259
|
"div",
|
|
25989
26260
|
{
|
|
25990
26261
|
style: {
|
|
@@ -25994,7 +26265,7 @@ var TicketCard = ({
|
|
|
25994
26265
|
paddingTop: 2,
|
|
25995
26266
|
marginTop: "-4px"
|
|
25996
26267
|
},
|
|
25997
|
-
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0,
|
|
26268
|
+
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(User, { user: assignee, index: idx, isFocus: isSelected }))
|
|
25998
26269
|
}
|
|
25999
26270
|
)
|
|
26000
26271
|
]
|
|
@@ -26006,7 +26277,7 @@ var TicketCard = ({
|
|
|
26006
26277
|
};
|
|
26007
26278
|
|
|
26008
26279
|
// source/gui/client/components/SwimlaneColumn.tsx
|
|
26009
|
-
var
|
|
26280
|
+
var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
|
|
26010
26281
|
var SwimlaneColumn = ({
|
|
26011
26282
|
swimlane,
|
|
26012
26283
|
selected,
|
|
@@ -26022,7 +26293,7 @@ var SwimlaneColumn = ({
|
|
|
26022
26293
|
onDragOverIssue,
|
|
26023
26294
|
onDragLeave
|
|
26024
26295
|
}) => {
|
|
26025
|
-
return /* @__PURE__ */ (0,
|
|
26296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
26026
26297
|
Panel,
|
|
26027
26298
|
{
|
|
26028
26299
|
as: "section",
|
|
@@ -26062,18 +26333,19 @@ var SwimlaneColumn = ({
|
|
|
26062
26333
|
onDragLeave();
|
|
26063
26334
|
},
|
|
26064
26335
|
children: [
|
|
26065
|
-
/* @__PURE__ */ (0,
|
|
26336
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
26066
26337
|
"header",
|
|
26067
26338
|
{
|
|
26068
26339
|
style: {
|
|
26069
26340
|
height: 48,
|
|
26341
|
+
flexShrink: 0,
|
|
26070
26342
|
display: "flex",
|
|
26071
26343
|
fontSize: 12,
|
|
26072
26344
|
justifyContent: "space-between",
|
|
26073
26345
|
alignItems: "center"
|
|
26074
26346
|
},
|
|
26075
26347
|
children: [
|
|
26076
|
-
/* @__PURE__ */ (0,
|
|
26348
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
26077
26349
|
"div",
|
|
26078
26350
|
{
|
|
26079
26351
|
style: {
|
|
@@ -26082,30 +26354,30 @@ var SwimlaneColumn = ({
|
|
|
26082
26354
|
gap: 8
|
|
26083
26355
|
},
|
|
26084
26356
|
children: [
|
|
26085
|
-
/* @__PURE__ */ (0,
|
|
26357
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26086
26358
|
"span",
|
|
26087
26359
|
{
|
|
26088
26360
|
style: { color: selected ? GUI_THEME.accent : GUI_THEME.secondary },
|
|
26089
26361
|
children: selected ? "\u276F" : " "
|
|
26090
26362
|
}
|
|
26091
26363
|
),
|
|
26092
|
-
/* @__PURE__ */ (0,
|
|
26364
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26093
26365
|
"strong",
|
|
26094
26366
|
{
|
|
26095
26367
|
style: { color: selected ? GUI_THEME.accent : GUI_THEME.primary },
|
|
26096
26368
|
children: swimlane.title
|
|
26097
26369
|
}
|
|
26098
26370
|
),
|
|
26099
|
-
/* @__PURE__ */ (0,
|
|
26371
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { style: { color: GUI_THEME.dim }, children: [
|
|
26100
26372
|
"(",
|
|
26101
26373
|
swimlane.issues.length,
|
|
26102
26374
|
")"
|
|
26103
26375
|
] }),
|
|
26104
|
-
swimlane.readonly && /* @__PURE__ */ (0,
|
|
26376
|
+
swimlane.readonly && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "\u{1F512}" })
|
|
26105
26377
|
]
|
|
26106
26378
|
}
|
|
26107
26379
|
),
|
|
26108
|
-
/* @__PURE__ */ (0,
|
|
26380
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26109
26381
|
Button,
|
|
26110
26382
|
{
|
|
26111
26383
|
variant: "ghost",
|
|
@@ -26118,9 +26390,9 @@ var SwimlaneColumn = ({
|
|
|
26118
26390
|
]
|
|
26119
26391
|
}
|
|
26120
26392
|
),
|
|
26121
|
-
/* @__PURE__ */ (0,
|
|
26122
|
-
dropIndex === 0 && /* @__PURE__ */ (0,
|
|
26123
|
-
/* @__PURE__ */ (0,
|
|
26393
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { overflow: "auto", paddingTop: 4, flex: 1, minHeight: 0 }, children: swimlane.issues.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
26394
|
+
dropIndex === 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropIndicator, {}),
|
|
26395
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26124
26396
|
"div",
|
|
26125
26397
|
{
|
|
26126
26398
|
style: {
|
|
@@ -26132,10 +26404,10 @@ var SwimlaneColumn = ({
|
|
|
26132
26404
|
children: "Drop issue here"
|
|
26133
26405
|
}
|
|
26134
26406
|
)
|
|
26135
|
-
] }) : /* @__PURE__ */ (0,
|
|
26136
|
-
swimlane.issues.map((ticket, index) => /* @__PURE__ */ (0,
|
|
26137
|
-
dropIndex === index && /* @__PURE__ */ (0,
|
|
26138
|
-
/* @__PURE__ */ (0,
|
|
26407
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
26408
|
+
swimlane.issues.map((ticket, index) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react8.default.Fragment, { children: [
|
|
26409
|
+
dropIndex === index && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropIndicator, {}),
|
|
26410
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26139
26411
|
TicketCard,
|
|
26140
26412
|
{
|
|
26141
26413
|
ticket,
|
|
@@ -26153,7 +26425,7 @@ var SwimlaneColumn = ({
|
|
|
26153
26425
|
}
|
|
26154
26426
|
)
|
|
26155
26427
|
] }, ticket.id)),
|
|
26156
|
-
dropIndex === swimlane.issues.length && /* @__PURE__ */ (0,
|
|
26428
|
+
dropIndex === swimlane.issues.length && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropIndicator, {})
|
|
26157
26429
|
] }) })
|
|
26158
26430
|
]
|
|
26159
26431
|
}
|
|
@@ -26291,9 +26563,73 @@ var updateIssueInGuiState = (state, issueId, updateIssue) => ({
|
|
|
26291
26563
|
}))
|
|
26292
26564
|
});
|
|
26293
26565
|
|
|
26566
|
+
// source/gui/client/lib/compress-image.ts
|
|
26567
|
+
var MAX_LONG_EDGE = 1600;
|
|
26568
|
+
var DEFAULT_MAX_KB = 500;
|
|
26569
|
+
var QUALITY_STEPS = [0.8, 0.7, 0.6, 0.5, 0.4];
|
|
26570
|
+
var toBlob = (canvas, type, quality) => new Promise((resolve) => canvas.toBlob(resolve, type, quality));
|
|
26571
|
+
var replaceExtension = (name, ext) => {
|
|
26572
|
+
const base = name.replace(/\.[a-z0-9]+$/i, "");
|
|
26573
|
+
return `${base || "image"}.${ext}`;
|
|
26574
|
+
};
|
|
26575
|
+
var compressImage = async (file, maxKb = DEFAULT_MAX_KB) => {
|
|
26576
|
+
const maxBytes = maxKb * 1024;
|
|
26577
|
+
if (file.type === "image/gif") {
|
|
26578
|
+
if (file.size <= maxBytes) {
|
|
26579
|
+
return { blob: file, name: file.name };
|
|
26580
|
+
}
|
|
26581
|
+
return {
|
|
26582
|
+
error: `GIFs are attached as-is and this one exceeds ${maxKb} KB`
|
|
26583
|
+
};
|
|
26584
|
+
}
|
|
26585
|
+
let bitmap;
|
|
26586
|
+
try {
|
|
26587
|
+
bitmap = await createImageBitmap(file);
|
|
26588
|
+
} catch {
|
|
26589
|
+
return { error: "Not a supported image" };
|
|
26590
|
+
}
|
|
26591
|
+
const scale = Math.min(
|
|
26592
|
+
1,
|
|
26593
|
+
MAX_LONG_EDGE / Math.max(bitmap.width, bitmap.height)
|
|
26594
|
+
);
|
|
26595
|
+
const canvas = document.createElement("canvas");
|
|
26596
|
+
canvas.width = Math.max(1, Math.round(bitmap.width * scale));
|
|
26597
|
+
canvas.height = Math.max(1, Math.round(bitmap.height * scale));
|
|
26598
|
+
const context = canvas.getContext("2d");
|
|
26599
|
+
if (!context) {
|
|
26600
|
+
bitmap.close();
|
|
26601
|
+
return { error: "Unable to process image" };
|
|
26602
|
+
}
|
|
26603
|
+
context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
|
|
26604
|
+
bitmap.close();
|
|
26605
|
+
for (const quality of QUALITY_STEPS) {
|
|
26606
|
+
const blob = await toBlob(canvas, "image/webp", quality);
|
|
26607
|
+
if (blob && blob.size <= maxBytes) {
|
|
26608
|
+
return { blob, name: replaceExtension(file.name, "webp") };
|
|
26609
|
+
}
|
|
26610
|
+
}
|
|
26611
|
+
return {
|
|
26612
|
+
error: `Unable to compress image under ${maxKb} KB`
|
|
26613
|
+
};
|
|
26614
|
+
};
|
|
26615
|
+
var blobToBase64 = (blob) => new Promise((resolve, reject) => {
|
|
26616
|
+
const reader = new FileReader();
|
|
26617
|
+
reader.onload = () => {
|
|
26618
|
+
const dataUrl = String(reader.result ?? "");
|
|
26619
|
+
const base64 = dataUrl.split(",")[1];
|
|
26620
|
+
if (!base64) {
|
|
26621
|
+
reject(new Error("Unable to encode image"));
|
|
26622
|
+
return;
|
|
26623
|
+
}
|
|
26624
|
+
resolve(base64);
|
|
26625
|
+
};
|
|
26626
|
+
reader.onerror = () => reject(new Error("Unable to read image"));
|
|
26627
|
+
reader.readAsDataURL(blob);
|
|
26628
|
+
});
|
|
26629
|
+
|
|
26294
26630
|
// source/gui/client/App.tsx
|
|
26295
|
-
var
|
|
26296
|
-
var DropIndicator = () => /* @__PURE__ */ (0,
|
|
26631
|
+
var import_jsx_runtime19 = __toESM(require_jsx_runtime(), 1);
|
|
26632
|
+
var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26297
26633
|
"div",
|
|
26298
26634
|
{
|
|
26299
26635
|
style: {
|
|
@@ -26308,34 +26644,51 @@ var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
|
26308
26644
|
var App = () => {
|
|
26309
26645
|
const { boardId, issueId } = useParams();
|
|
26310
26646
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
26311
|
-
const [connected, setConnected] = (0,
|
|
26312
|
-
const [syncStatus, setSyncStatus] = (0,
|
|
26647
|
+
const [connected, setConnected] = (0, import_react9.useState)(false);
|
|
26648
|
+
const [syncStatus, setSyncStatus] = (0, import_react9.useState)({
|
|
26313
26649
|
status: "synced",
|
|
26314
26650
|
msg: "idle"
|
|
26315
26651
|
});
|
|
26316
|
-
const [state, setState] = (0,
|
|
26317
|
-
const [dragOverSwimlaneId, setDragOverSwimlaneId] = (0,
|
|
26652
|
+
const [state, setState] = (0, import_react9.useState)(null);
|
|
26653
|
+
const [dragOverSwimlaneId, setDragOverSwimlaneId] = (0, import_react9.useState)(
|
|
26318
26654
|
null
|
|
26319
26655
|
);
|
|
26320
|
-
const [dropTarget, setDropTarget] = (0,
|
|
26321
|
-
const [boardMenuOpen, setBoardMenuOpen] = (0,
|
|
26322
|
-
const [createIssueModal, setCreateIssueModal] = (0,
|
|
26323
|
-
const boardMenuRef = (0,
|
|
26324
|
-
const socketRef = (0,
|
|
26656
|
+
const [dropTarget, setDropTarget] = (0, import_react9.useState)(null);
|
|
26657
|
+
const [boardMenuOpen, setBoardMenuOpen] = (0, import_react9.useState)(false);
|
|
26658
|
+
const [createIssueModal, setCreateIssueModal] = (0, import_react9.useState)(null);
|
|
26659
|
+
const boardMenuRef = (0, import_react9.useRef)(null);
|
|
26660
|
+
const socketRef = (0, import_react9.useRef)(null);
|
|
26325
26661
|
const selectedTab = searchParams.get("tab") === "comments" ? "comments" : "overview";
|
|
26326
26662
|
const navigate = useNavigate();
|
|
26327
26663
|
const selectedBoard = (state && boardId ? findBoard(state, boardId) : null) ?? state?.boards[0] ?? null;
|
|
26328
26664
|
const boardSlug = selectedBoard?.ref ?? boardId;
|
|
26329
26665
|
const selectedIssue = state && issueId ? findIssue(state, issueId) : null;
|
|
26666
|
+
(0, import_react9.useEffect)(() => {
|
|
26667
|
+
const onPaste = (event) => {
|
|
26668
|
+
if (!selectedIssue || selectedIssue.readonly) return;
|
|
26669
|
+
const target = event.target;
|
|
26670
|
+
if (target && (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable)) {
|
|
26671
|
+
return;
|
|
26672
|
+
}
|
|
26673
|
+
const files = Array.from(event.clipboardData?.items ?? []).filter((item) => item.kind === "file" && item.type.startsWith("image/")).map((item) => item.getAsFile()).filter((file) => Boolean(file));
|
|
26674
|
+
if (files.length === 0) return;
|
|
26675
|
+
event.preventDefault();
|
|
26676
|
+
void uploadIssueAttachments(selectedIssue.id, files);
|
|
26677
|
+
};
|
|
26678
|
+
window.addEventListener("paste", onPaste);
|
|
26679
|
+
return () => window.removeEventListener("paste", onPaste);
|
|
26680
|
+
});
|
|
26330
26681
|
const closeIssueDetails = () => {
|
|
26331
26682
|
if (!boardSlug) return;
|
|
26332
26683
|
void navigate(`/board/${boardSlug}`);
|
|
26333
26684
|
};
|
|
26334
26685
|
const commentsByIssueId = state?.commentsByIssueId ?? {};
|
|
26686
|
+
const attachmentsByIssueId = state?.attachmentsByIssueId ?? {};
|
|
26687
|
+
const [attachmentUploadStatus, setAttachmentUploadStatus] = (0, import_react9.useState)({ state: "idle" });
|
|
26335
26688
|
const requestState = () => {
|
|
26336
26689
|
socketRef.current?.send(JSON.stringify({ type: "state:get" }));
|
|
26337
26690
|
};
|
|
26338
|
-
(0,
|
|
26691
|
+
(0, import_react9.useEffect)(() => {
|
|
26339
26692
|
const socket = new WebSocket(
|
|
26340
26693
|
`ws://${window.location.host}/ws${boardId ? `?boardId=${boardId}` : ""}`
|
|
26341
26694
|
);
|
|
@@ -26379,12 +26732,12 @@ var App = () => {
|
|
|
26379
26732
|
socket.close();
|
|
26380
26733
|
};
|
|
26381
26734
|
}, [boardId, navigate]);
|
|
26382
|
-
(0,
|
|
26735
|
+
(0, import_react9.useEffect)(() => {
|
|
26383
26736
|
if (!boardId && state?.boards[0]) {
|
|
26384
26737
|
void navigate(`/board/${state.boards[0].ref}`, { replace: true });
|
|
26385
26738
|
}
|
|
26386
26739
|
}, [boardId, state, navigate]);
|
|
26387
|
-
(0,
|
|
26740
|
+
(0, import_react9.useEffect)(() => {
|
|
26388
26741
|
const close = (event) => {
|
|
26389
26742
|
if (boardMenuRef.current && !boardMenuRef.current.contains(event.target)) {
|
|
26390
26743
|
setBoardMenuOpen(false);
|
|
@@ -26569,6 +26922,68 @@ var App = () => {
|
|
|
26569
26922
|
});
|
|
26570
26923
|
send("issue:comment:add", { issueId: issueId2, body });
|
|
26571
26924
|
};
|
|
26925
|
+
const uploadIssueAttachments = async (issueId2, files) => {
|
|
26926
|
+
for (const file of files) {
|
|
26927
|
+
setAttachmentUploadStatus({ state: "uploading", name: file.name });
|
|
26928
|
+
const compressed = await compressImage(file, state?.attachmentMaxKb);
|
|
26929
|
+
if ("error" in compressed) {
|
|
26930
|
+
setAttachmentUploadStatus({ state: "error", message: compressed.error });
|
|
26931
|
+
return;
|
|
26932
|
+
}
|
|
26933
|
+
try {
|
|
26934
|
+
const dataBase64 = await blobToBase64(compressed.blob);
|
|
26935
|
+
const response = await fetch("/api/attachments", {
|
|
26936
|
+
method: "POST",
|
|
26937
|
+
headers: { "content-type": "application/json" },
|
|
26938
|
+
body: JSON.stringify({
|
|
26939
|
+
issueId: issueId2,
|
|
26940
|
+
name: compressed.name,
|
|
26941
|
+
dataBase64
|
|
26942
|
+
})
|
|
26943
|
+
});
|
|
26944
|
+
const payload = await response.json();
|
|
26945
|
+
if (!response.ok) {
|
|
26946
|
+
setAttachmentUploadStatus({
|
|
26947
|
+
state: "error",
|
|
26948
|
+
message: payload?.message ?? "Upload failed"
|
|
26949
|
+
});
|
|
26950
|
+
return;
|
|
26951
|
+
}
|
|
26952
|
+
const nextState = getResultValue(payload);
|
|
26953
|
+
if (nextState) setState(nextState);
|
|
26954
|
+
} catch (error) {
|
|
26955
|
+
setAttachmentUploadStatus({
|
|
26956
|
+
state: "error",
|
|
26957
|
+
message: error instanceof Error ? error.message : "Upload failed"
|
|
26958
|
+
});
|
|
26959
|
+
return;
|
|
26960
|
+
}
|
|
26961
|
+
}
|
|
26962
|
+
setAttachmentUploadStatus({ state: "idle" });
|
|
26963
|
+
};
|
|
26964
|
+
const deleteIssueAttachment = async (_issueId, attachmentId) => {
|
|
26965
|
+
try {
|
|
26966
|
+
const response = await fetch(
|
|
26967
|
+
`/api/attachments/${encodeURIComponent(attachmentId)}`,
|
|
26968
|
+
{ method: "DELETE" }
|
|
26969
|
+
);
|
|
26970
|
+
const payload = await response.json();
|
|
26971
|
+
if (!response.ok) {
|
|
26972
|
+
setAttachmentUploadStatus({
|
|
26973
|
+
state: "error",
|
|
26974
|
+
message: payload?.message ?? "Unable to delete attachment"
|
|
26975
|
+
});
|
|
26976
|
+
return;
|
|
26977
|
+
}
|
|
26978
|
+
const nextState = getResultValue(payload);
|
|
26979
|
+
if (nextState) setState(nextState);
|
|
26980
|
+
} catch (error) {
|
|
26981
|
+
setAttachmentUploadStatus({
|
|
26982
|
+
state: "error",
|
|
26983
|
+
message: error instanceof Error ? error.message : "Unable to delete attachment"
|
|
26984
|
+
});
|
|
26985
|
+
}
|
|
26986
|
+
};
|
|
26572
26987
|
const deleteIssueComment = (_issueId, commentId) => {
|
|
26573
26988
|
setState((prev) => {
|
|
26574
26989
|
if (!prev) return prev;
|
|
@@ -26586,7 +27001,7 @@ var App = () => {
|
|
|
26586
27001
|
});
|
|
26587
27002
|
send("issue:comment:delete", { commentId });
|
|
26588
27003
|
};
|
|
26589
|
-
return /* @__PURE__ */ (0,
|
|
27004
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
26590
27005
|
"div",
|
|
26591
27006
|
{
|
|
26592
27007
|
style: {
|
|
@@ -26598,8 +27013,8 @@ var App = () => {
|
|
|
26598
27013
|
flexDirection: "column"
|
|
26599
27014
|
},
|
|
26600
27015
|
children: [
|
|
26601
|
-
/* @__PURE__ */ (0,
|
|
26602
|
-
/* @__PURE__ */ (0,
|
|
27016
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Header, { state, connected, syncStatus }),
|
|
27017
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
26603
27018
|
"div",
|
|
26604
27019
|
{
|
|
26605
27020
|
style: {
|
|
@@ -26608,8 +27023,8 @@ var App = () => {
|
|
|
26608
27023
|
overflow: "hidden"
|
|
26609
27024
|
},
|
|
26610
27025
|
children: [
|
|
26611
|
-
/* @__PURE__ */ (0,
|
|
26612
|
-
/* @__PURE__ */ (0,
|
|
27026
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("main", { style: { padding: "0 30px 30px 30px", overflow: "auto", flex: 1 }, children: [
|
|
27027
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { padding: "20px 10px" }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26613
27028
|
Dropdown,
|
|
26614
27029
|
{
|
|
26615
27030
|
label: "Board:",
|
|
@@ -26625,7 +27040,7 @@ var App = () => {
|
|
|
26625
27040
|
onSelect: selectBoard
|
|
26626
27041
|
}
|
|
26627
27042
|
) }),
|
|
26628
|
-
/* @__PURE__ */ (0,
|
|
27043
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { display: "flex", gap: 8 }, children: selectedBoard?.swimlanes.map((swimlane) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26629
27044
|
SwimlaneColumn,
|
|
26630
27045
|
{
|
|
26631
27046
|
swimlane,
|
|
@@ -26645,7 +27060,7 @@ var App = () => {
|
|
|
26645
27060
|
swimlane.id
|
|
26646
27061
|
)) })
|
|
26647
27062
|
] }),
|
|
26648
|
-
selectedIssue && state?.user && /* @__PURE__ */ (0,
|
|
27063
|
+
selectedIssue && state?.user && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26649
27064
|
IssueDetails,
|
|
26650
27065
|
{
|
|
26651
27066
|
whoAmI: state.user,
|
|
@@ -26662,6 +27077,10 @@ var App = () => {
|
|
|
26662
27077
|
onRemoveAssignee: removeIssueAssignee,
|
|
26663
27078
|
onAddComment: addIssueComment,
|
|
26664
27079
|
onDeleteComment: deleteIssueComment,
|
|
27080
|
+
attachments: attachmentsByIssueId[selectedIssue.id] ?? [],
|
|
27081
|
+
attachmentUploadStatus,
|
|
27082
|
+
onUploadAttachments: uploadIssueAttachments,
|
|
27083
|
+
onDeleteAttachment: deleteIssueAttachment,
|
|
26665
27084
|
onReopenIssue: reopenIssue,
|
|
26666
27085
|
onCloseIssue: closeIssue,
|
|
26667
27086
|
knownTags: state.tags ?? [],
|
|
@@ -26671,7 +27090,7 @@ var App = () => {
|
|
|
26671
27090
|
]
|
|
26672
27091
|
}
|
|
26673
27092
|
),
|
|
26674
|
-
createIssueModal && /* @__PURE__ */ (0,
|
|
27093
|
+
createIssueModal && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26675
27094
|
CreateIssueModal,
|
|
26676
27095
|
{
|
|
26677
27096
|
title: createIssueModal.title,
|
|
@@ -26686,14 +27105,14 @@ var App = () => {
|
|
|
26686
27105
|
};
|
|
26687
27106
|
|
|
26688
27107
|
// source/gui/client/main.tsx
|
|
26689
|
-
var
|
|
27108
|
+
var import_jsx_runtime20 = __toESM(require_jsx_runtime(), 1);
|
|
26690
27109
|
(0, import_client.createRoot)(document.getElementById("root")).render(
|
|
26691
|
-
/* @__PURE__ */ (0,
|
|
26692
|
-
/* @__PURE__ */ (0,
|
|
26693
|
-
/* @__PURE__ */ (0,
|
|
26694
|
-
/* @__PURE__ */ (0,
|
|
26695
|
-
/* @__PURE__ */ (0,
|
|
26696
|
-
/* @__PURE__ */ (0,
|
|
27110
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(BrowserRouter, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Routes, { children: [
|
|
27111
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(App, {}) }),
|
|
27112
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "/board/:boardId", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(App, {}) }),
|
|
27113
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "/board/:boardId/issue/:issueId", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(App, {}) }),
|
|
27114
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "/board/:boardId/:issueId", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(App, {}) }),
|
|
27115
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Navigate, { to: "/", replace: true }) })
|
|
26697
27116
|
] }) })
|
|
26698
27117
|
);
|
|
26699
27118
|
/*! Bundled license information:
|