epiq 1.2.3 → 1.3.0
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 +612 -197
- package/dist/index.js +53 -52
- package/dist/mcp.js +42 -41
- package/package.json +1 -1
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);
|
|
@@ -24911,12 +24911,13 @@ var User = ({
|
|
|
24911
24911
|
);
|
|
24912
24912
|
|
|
24913
24913
|
// source/version.ts
|
|
24914
|
-
var EPIQ_VERSION = "1.
|
|
24914
|
+
var EPIQ_VERSION = "1.3.0";
|
|
24915
24915
|
|
|
24916
24916
|
// source/gui/client/components/Header.tsx
|
|
24917
24917
|
var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
|
|
24918
24918
|
var Header = ({ state, connected, syncStatus }) => {
|
|
24919
24919
|
const syncColor = syncStatus.status === "synced" ? GUI_THEME.green : syncStatus.status === "failed" ? GUI_THEME.red : GUI_THEME.accent;
|
|
24920
|
+
const syncLabel = syncStatus.status === "failed" ? "-" : syncStatus.msg.toLowerCase();
|
|
24920
24921
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
24921
24922
|
Panel,
|
|
24922
24923
|
{
|
|
@@ -24986,12 +24987,17 @@ var Header = ({ state, connected, syncStatus }) => {
|
|
|
24986
24987
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
24987
24988
|
"span",
|
|
24988
24989
|
{
|
|
24990
|
+
title: syncStatus.status === "failed" ? syncStatus.msg : void 0,
|
|
24989
24991
|
style: {
|
|
24990
24992
|
color: GUI_THEME.dim,
|
|
24991
24993
|
minWidth: 72,
|
|
24994
|
+
maxWidth: 220,
|
|
24995
|
+
overflow: "hidden",
|
|
24996
|
+
textOverflow: "ellipsis",
|
|
24997
|
+
whiteSpace: "nowrap",
|
|
24992
24998
|
textAlign: "right"
|
|
24993
24999
|
},
|
|
24994
|
-
children: connected ?
|
|
25000
|
+
children: connected ? syncLabel : "-"
|
|
24995
25001
|
}
|
|
24996
25002
|
),
|
|
24997
25003
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
@@ -25042,7 +25048,7 @@ var Header = ({ state, connected, syncStatus }) => {
|
|
|
25042
25048
|
};
|
|
25043
25049
|
|
|
25044
25050
|
// source/gui/client/components/IssueDetails.tsx
|
|
25045
|
-
var
|
|
25051
|
+
var import_react7 = __toESM(require_react(), 1);
|
|
25046
25052
|
|
|
25047
25053
|
// source/gui/client/components/Aside.tsx
|
|
25048
25054
|
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
@@ -25108,7 +25114,7 @@ var CopyRef = ({ refValue }) => {
|
|
|
25108
25114
|
onMouseLeave: (event) => {
|
|
25109
25115
|
event.currentTarget.style.color = copied ? GUI_THEME.green : GUI_THEME.dim;
|
|
25110
25116
|
},
|
|
25111
|
-
children: copied ? "copied!" :
|
|
25117
|
+
children: copied ? "copied!" : refValue
|
|
25112
25118
|
}
|
|
25113
25119
|
);
|
|
25114
25120
|
};
|
|
@@ -25182,9 +25188,299 @@ var AddRow = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("di
|
|
|
25182
25188
|
var ChipRow = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: "flex", gap: 8, flexWrap: "wrap", marginTop: 10 }, children });
|
|
25183
25189
|
var Empty = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { display: "inline-block", marginTop: 8, color: GUI_THEME.dim }, children });
|
|
25184
25190
|
|
|
25185
|
-
// source/gui/client/components/
|
|
25191
|
+
// source/gui/client/components/IssueAttachments.tsx
|
|
25186
25192
|
var import_react5 = __toESM(require_react(), 1);
|
|
25187
25193
|
|
|
25194
|
+
// source/gui/client/components/Section.tsx
|
|
25195
|
+
var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
|
|
25196
|
+
var Section = ({
|
|
25197
|
+
title,
|
|
25198
|
+
action,
|
|
25199
|
+
children,
|
|
25200
|
+
first = false
|
|
25201
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
25202
|
+
"section",
|
|
25203
|
+
{
|
|
25204
|
+
style: {
|
|
25205
|
+
padding: first ? "0px 0 14px 0" : "14px 0",
|
|
25206
|
+
borderTop: first ? "none" : `1px solid ${GUI_THEME.line}`
|
|
25207
|
+
},
|
|
25208
|
+
children: [
|
|
25209
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
25210
|
+
"div",
|
|
25211
|
+
{
|
|
25212
|
+
style: {
|
|
25213
|
+
display: "flex",
|
|
25214
|
+
justifyContent: "space-between",
|
|
25215
|
+
alignItems: "center",
|
|
25216
|
+
gap: 12
|
|
25217
|
+
},
|
|
25218
|
+
children: [
|
|
25219
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
25220
|
+
"span",
|
|
25221
|
+
{
|
|
25222
|
+
style: {
|
|
25223
|
+
color: GUI_THEME.secondary,
|
|
25224
|
+
fontSize: 10,
|
|
25225
|
+
textTransform: "uppercase",
|
|
25226
|
+
letterSpacing: "0.08em"
|
|
25227
|
+
},
|
|
25228
|
+
children: title
|
|
25229
|
+
}
|
|
25230
|
+
),
|
|
25231
|
+
action
|
|
25232
|
+
]
|
|
25233
|
+
}
|
|
25234
|
+
),
|
|
25235
|
+
children
|
|
25236
|
+
]
|
|
25237
|
+
}
|
|
25238
|
+
);
|
|
25239
|
+
|
|
25240
|
+
// source/gui/client/components/IssueAttachments.tsx
|
|
25241
|
+
var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
|
|
25242
|
+
var IssueAttachments = ({
|
|
25243
|
+
issueId,
|
|
25244
|
+
readonly,
|
|
25245
|
+
attachments,
|
|
25246
|
+
uploadStatus,
|
|
25247
|
+
onUploadFiles,
|
|
25248
|
+
onDeleteAttachment
|
|
25249
|
+
}) => {
|
|
25250
|
+
const [dragging, setDragging] = (0, import_react5.useState)(false);
|
|
25251
|
+
const [lightbox, setLightbox] = (0, import_react5.useState)(null);
|
|
25252
|
+
const [broken, setBroken] = (0, import_react5.useState)({});
|
|
25253
|
+
(0, import_react5.useEffect)(() => {
|
|
25254
|
+
setLightbox(null);
|
|
25255
|
+
setDragging(false);
|
|
25256
|
+
setBroken({});
|
|
25257
|
+
}, [issueId]);
|
|
25258
|
+
(0, import_react5.useEffect)(() => {
|
|
25259
|
+
if (!lightbox) return;
|
|
25260
|
+
const onKeyDown = (event) => {
|
|
25261
|
+
if (event.key === "Escape") setLightbox(null);
|
|
25262
|
+
};
|
|
25263
|
+
window.addEventListener("keydown", onKeyDown);
|
|
25264
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
25265
|
+
}, [lightbox]);
|
|
25266
|
+
const canUpload = !readonly && Boolean(onUploadFiles);
|
|
25267
|
+
const handleDrop = (event) => {
|
|
25268
|
+
event.preventDefault();
|
|
25269
|
+
setDragging(false);
|
|
25270
|
+
if (!canUpload) return;
|
|
25271
|
+
const files = Array.from(event.dataTransfer.files).filter(
|
|
25272
|
+
(file) => file.type.startsWith("image/")
|
|
25273
|
+
);
|
|
25274
|
+
if (files.length > 0) onUploadFiles?.(issueId, files);
|
|
25275
|
+
};
|
|
25276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25277
|
+
Section,
|
|
25278
|
+
{
|
|
25279
|
+
title: `Attachments${attachments.length ? ` (${attachments.length})` : ""}`,
|
|
25280
|
+
children: [
|
|
25281
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25282
|
+
"div",
|
|
25283
|
+
{
|
|
25284
|
+
onDragOver: (event) => {
|
|
25285
|
+
if (!canUpload) return;
|
|
25286
|
+
event.preventDefault();
|
|
25287
|
+
setDragging(true);
|
|
25288
|
+
},
|
|
25289
|
+
onDragLeave: () => setDragging(false),
|
|
25290
|
+
onDrop: handleDrop,
|
|
25291
|
+
style: {
|
|
25292
|
+
marginTop: 8,
|
|
25293
|
+
padding: dragging ? 10 : 0,
|
|
25294
|
+
border: dragging ? `1px dashed ${GUI_THEME.accent}` : "1px dashed transparent",
|
|
25295
|
+
borderRadius: 4,
|
|
25296
|
+
transition: "padding 0.12s ease, border-color 0.12s ease"
|
|
25297
|
+
},
|
|
25298
|
+
children: [
|
|
25299
|
+
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)(
|
|
25300
|
+
"div",
|
|
25301
|
+
{
|
|
25302
|
+
style: {
|
|
25303
|
+
display: "flex",
|
|
25304
|
+
flexWrap: "wrap",
|
|
25305
|
+
gap: 8
|
|
25306
|
+
},
|
|
25307
|
+
children: attachments.map((attachment) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25308
|
+
"div",
|
|
25309
|
+
{
|
|
25310
|
+
style: { position: "relative", width: 72, height: 72 },
|
|
25311
|
+
children: [
|
|
25312
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25313
|
+
"button",
|
|
25314
|
+
{
|
|
25315
|
+
type: "button",
|
|
25316
|
+
disabled: broken[attachment.id],
|
|
25317
|
+
onClick: () => setLightbox(attachment),
|
|
25318
|
+
title: `${attachment.name} (${Math.max(
|
|
25319
|
+
1,
|
|
25320
|
+
Math.round(attachment.bytes / 1024)
|
|
25321
|
+
)} KB)`,
|
|
25322
|
+
style: {
|
|
25323
|
+
padding: 0,
|
|
25324
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
25325
|
+
borderRadius: 4,
|
|
25326
|
+
background: GUI_THEME.panel2,
|
|
25327
|
+
cursor: broken[attachment.id] ? "default" : "zoom-in",
|
|
25328
|
+
overflow: "hidden",
|
|
25329
|
+
width: "100%",
|
|
25330
|
+
height: "100%"
|
|
25331
|
+
},
|
|
25332
|
+
children: broken[attachment.id] ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25333
|
+
"span",
|
|
25334
|
+
{
|
|
25335
|
+
title: "Attachment unavailable (missing, corrupt, or over the size cap)",
|
|
25336
|
+
style: {
|
|
25337
|
+
display: "flex",
|
|
25338
|
+
alignItems: "center",
|
|
25339
|
+
justifyContent: "center",
|
|
25340
|
+
width: "100%",
|
|
25341
|
+
height: "100%",
|
|
25342
|
+
color: GUI_THEME.dim2,
|
|
25343
|
+
fontSize: 9,
|
|
25344
|
+
padding: 4,
|
|
25345
|
+
textAlign: "center"
|
|
25346
|
+
},
|
|
25347
|
+
children: "unavailable"
|
|
25348
|
+
}
|
|
25349
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25350
|
+
"img",
|
|
25351
|
+
{
|
|
25352
|
+
src: `/media/${attachment.fileName}`,
|
|
25353
|
+
alt: attachment.name,
|
|
25354
|
+
loading: "lazy",
|
|
25355
|
+
onError: () => setBroken((prev) => ({ ...prev, [attachment.id]: true })),
|
|
25356
|
+
style: {
|
|
25357
|
+
width: "100%",
|
|
25358
|
+
height: "100%",
|
|
25359
|
+
objectFit: "cover",
|
|
25360
|
+
display: "block"
|
|
25361
|
+
}
|
|
25362
|
+
}
|
|
25363
|
+
)
|
|
25364
|
+
}
|
|
25365
|
+
),
|
|
25366
|
+
attachment.canDelete && !readonly && onDeleteAttachment && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25367
|
+
"button",
|
|
25368
|
+
{
|
|
25369
|
+
type: "button",
|
|
25370
|
+
title: "Delete attachment",
|
|
25371
|
+
onClick: () => onDeleteAttachment(issueId, attachment.id),
|
|
25372
|
+
style: {
|
|
25373
|
+
position: "absolute",
|
|
25374
|
+
top: 2,
|
|
25375
|
+
right: 2,
|
|
25376
|
+
width: 16,
|
|
25377
|
+
height: 16,
|
|
25378
|
+
lineHeight: "14px",
|
|
25379
|
+
padding: 0,
|
|
25380
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
25381
|
+
borderRadius: 3,
|
|
25382
|
+
background: "rgba(4, 5, 8, 0.75)",
|
|
25383
|
+
color: GUI_THEME.secondary,
|
|
25384
|
+
fontSize: 10,
|
|
25385
|
+
cursor: "pointer"
|
|
25386
|
+
},
|
|
25387
|
+
children: "\xD7"
|
|
25388
|
+
}
|
|
25389
|
+
)
|
|
25390
|
+
]
|
|
25391
|
+
},
|
|
25392
|
+
attachment.id
|
|
25393
|
+
))
|
|
25394
|
+
}
|
|
25395
|
+
),
|
|
25396
|
+
canUpload && attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25397
|
+
"div",
|
|
25398
|
+
{
|
|
25399
|
+
style: {
|
|
25400
|
+
marginTop: 8,
|
|
25401
|
+
color: GUI_THEME.dim2,
|
|
25402
|
+
fontSize: 10
|
|
25403
|
+
},
|
|
25404
|
+
children: "drop an image to attach"
|
|
25405
|
+
}
|
|
25406
|
+
),
|
|
25407
|
+
uploadStatus.state === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25408
|
+
"div",
|
|
25409
|
+
{
|
|
25410
|
+
style: {
|
|
25411
|
+
marginTop: 8,
|
|
25412
|
+
color: GUI_THEME.secondary,
|
|
25413
|
+
fontSize: 11
|
|
25414
|
+
},
|
|
25415
|
+
children: [
|
|
25416
|
+
"uploading ",
|
|
25417
|
+
uploadStatus.name,
|
|
25418
|
+
"\u2026"
|
|
25419
|
+
]
|
|
25420
|
+
}
|
|
25421
|
+
),
|
|
25422
|
+
uploadStatus.state === "error" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25423
|
+
"div",
|
|
25424
|
+
{
|
|
25425
|
+
style: {
|
|
25426
|
+
marginTop: 8,
|
|
25427
|
+
color: GUI_THEME.red,
|
|
25428
|
+
fontSize: 11
|
|
25429
|
+
},
|
|
25430
|
+
children: uploadStatus.message
|
|
25431
|
+
}
|
|
25432
|
+
)
|
|
25433
|
+
]
|
|
25434
|
+
}
|
|
25435
|
+
),
|
|
25436
|
+
lightbox && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25437
|
+
"div",
|
|
25438
|
+
{
|
|
25439
|
+
onClick: () => setLightbox(null),
|
|
25440
|
+
style: {
|
|
25441
|
+
position: "fixed",
|
|
25442
|
+
inset: 0,
|
|
25443
|
+
zIndex: 100,
|
|
25444
|
+
display: "flex",
|
|
25445
|
+
alignItems: "center",
|
|
25446
|
+
justifyContent: "center",
|
|
25447
|
+
flexDirection: "column",
|
|
25448
|
+
gap: 10,
|
|
25449
|
+
background: "rgba(4, 5, 8, 0.88)",
|
|
25450
|
+
cursor: "zoom-out"
|
|
25451
|
+
},
|
|
25452
|
+
children: [
|
|
25453
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
25454
|
+
"img",
|
|
25455
|
+
{
|
|
25456
|
+
src: `/media/${lightbox.fileName}`,
|
|
25457
|
+
alt: lightbox.name,
|
|
25458
|
+
style: {
|
|
25459
|
+
maxWidth: "90vw",
|
|
25460
|
+
maxHeight: "85vh",
|
|
25461
|
+
borderRadius: 6,
|
|
25462
|
+
border: `1px solid ${GUI_THEME.line}`
|
|
25463
|
+
}
|
|
25464
|
+
}
|
|
25465
|
+
),
|
|
25466
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { color: GUI_THEME.secondary, fontSize: 11 }, children: [
|
|
25467
|
+
lightbox.name,
|
|
25468
|
+
" \xB7 ",
|
|
25469
|
+
Math.max(1, Math.round(lightbox.bytes / 1024)),
|
|
25470
|
+
" ",
|
|
25471
|
+
"KB \xB7 esc to close"
|
|
25472
|
+
] })
|
|
25473
|
+
]
|
|
25474
|
+
}
|
|
25475
|
+
)
|
|
25476
|
+
]
|
|
25477
|
+
}
|
|
25478
|
+
);
|
|
25479
|
+
};
|
|
25480
|
+
|
|
25481
|
+
// source/gui/client/components/IssueComments.tsx
|
|
25482
|
+
var import_react6 = __toESM(require_react(), 1);
|
|
25483
|
+
|
|
25188
25484
|
// source/gui/client/lib/gui-format.helper.ts
|
|
25189
25485
|
var timeAgo = (timestampMs) => {
|
|
25190
25486
|
const diff = Date.now() - timestampMs;
|
|
@@ -25205,7 +25501,7 @@ var timeAgo = (timestampMs) => {
|
|
|
25205
25501
|
};
|
|
25206
25502
|
|
|
25207
25503
|
// source/gui/client/components/IssueComments.tsx
|
|
25208
|
-
var
|
|
25504
|
+
var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
|
|
25209
25505
|
var IssueComments = ({
|
|
25210
25506
|
whoAmI,
|
|
25211
25507
|
issueId,
|
|
@@ -25214,15 +25510,15 @@ var IssueComments = ({
|
|
|
25214
25510
|
onAddComment,
|
|
25215
25511
|
onDeleteComment
|
|
25216
25512
|
}) => {
|
|
25217
|
-
const [body, setBody] = (0,
|
|
25513
|
+
const [body, setBody] = (0, import_react6.useState)("");
|
|
25218
25514
|
const addComment = () => {
|
|
25219
25515
|
const nextBody = body.trim();
|
|
25220
25516
|
if (!nextBody) return;
|
|
25221
25517
|
onAddComment?.(issueId, nextBody);
|
|
25222
25518
|
setBody("");
|
|
25223
25519
|
};
|
|
25224
|
-
return /* @__PURE__ */ (0,
|
|
25225
|
-
comments.length === 0 ? /* @__PURE__ */ (0,
|
|
25520
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
25521
|
+
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
25522
|
"div",
|
|
25227
25523
|
{
|
|
25228
25524
|
style: {
|
|
@@ -25232,7 +25528,7 @@ var IssueComments = ({
|
|
|
25232
25528
|
background: GUI_THEME.tertiary
|
|
25233
25529
|
},
|
|
25234
25530
|
children: [
|
|
25235
|
-
/* @__PURE__ */ (0,
|
|
25531
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
25236
25532
|
"div",
|
|
25237
25533
|
{
|
|
25238
25534
|
style: {
|
|
@@ -25242,15 +25538,15 @@ var IssueComments = ({
|
|
|
25242
25538
|
marginBottom: 8
|
|
25243
25539
|
},
|
|
25244
25540
|
children: [
|
|
25245
|
-
/* @__PURE__ */ (0,
|
|
25541
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { color: GUI_THEME.secondary, fontSize: 10 }, children: [
|
|
25246
25542
|
comment.author.name ?? "unknown",
|
|
25247
|
-
comment.createdAt && /* @__PURE__ */ (0,
|
|
25543
|
+
comment.createdAt && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { style: { color: GUI_THEME.dim2 }, children: [
|
|
25248
25544
|
" ",
|
|
25249
25545
|
"\xB7 ",
|
|
25250
25546
|
timeAgo(comment.createdAt)
|
|
25251
25547
|
] })
|
|
25252
25548
|
] }),
|
|
25253
|
-
comment.author.id === whoAmI.id && onDeleteComment && /* @__PURE__ */ (0,
|
|
25549
|
+
comment.author.id === whoAmI.id && onDeleteComment && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25254
25550
|
Button,
|
|
25255
25551
|
{
|
|
25256
25552
|
variant: "ghost",
|
|
@@ -25265,7 +25561,7 @@ var IssueComments = ({
|
|
|
25265
25561
|
]
|
|
25266
25562
|
}
|
|
25267
25563
|
),
|
|
25268
|
-
/* @__PURE__ */ (0,
|
|
25564
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25269
25565
|
"div",
|
|
25270
25566
|
{
|
|
25271
25567
|
style: {
|
|
@@ -25280,8 +25576,8 @@ var IssueComments = ({
|
|
|
25280
25576
|
},
|
|
25281
25577
|
comment.id
|
|
25282
25578
|
)) }),
|
|
25283
|
-
!readonly && /* @__PURE__ */ (0,
|
|
25284
|
-
/* @__PURE__ */ (0,
|
|
25579
|
+
!readonly && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginTop: 18 }, children: [
|
|
25580
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25285
25581
|
Textarea,
|
|
25286
25582
|
{
|
|
25287
25583
|
maxLength: 120,
|
|
@@ -25296,64 +25592,18 @@ var IssueComments = ({
|
|
|
25296
25592
|
style: { minHeight: 45 }
|
|
25297
25593
|
}
|
|
25298
25594
|
),
|
|
25299
|
-
/* @__PURE__ */ (0,
|
|
25595
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ActionRow, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { onClick: addComment, children: "comment" }) })
|
|
25300
25596
|
] })
|
|
25301
25597
|
] });
|
|
25302
25598
|
};
|
|
25303
25599
|
|
|
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
25600
|
// source/gui/client/components/Tabs.tsx
|
|
25351
|
-
var
|
|
25601
|
+
var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
|
|
25352
25602
|
var Tabs = ({
|
|
25353
25603
|
activeTab,
|
|
25354
25604
|
tabs,
|
|
25355
25605
|
onChange
|
|
25356
|
-
}) => /* @__PURE__ */ (0,
|
|
25606
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
25357
25607
|
"div",
|
|
25358
25608
|
{
|
|
25359
25609
|
style: {
|
|
@@ -25364,7 +25614,7 @@ var Tabs = ({
|
|
|
25364
25614
|
},
|
|
25365
25615
|
children: tabs.map((tab) => {
|
|
25366
25616
|
const active = tab.id === activeTab;
|
|
25367
|
-
return /* @__PURE__ */ (0,
|
|
25617
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
25368
25618
|
"button",
|
|
25369
25619
|
{
|
|
25370
25620
|
type: "button",
|
|
@@ -25382,7 +25632,7 @@ var Tabs = ({
|
|
|
25382
25632
|
},
|
|
25383
25633
|
children: [
|
|
25384
25634
|
tab.label,
|
|
25385
|
-
typeof tab.count === "number" && /* @__PURE__ */ (0,
|
|
25635
|
+
typeof tab.count === "number" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
25386
25636
|
"span",
|
|
25387
25637
|
{
|
|
25388
25638
|
style: { color: tab.count ? GUI_THEME.secondary : GUI_THEME.dim },
|
|
@@ -25403,7 +25653,7 @@ var Tabs = ({
|
|
|
25403
25653
|
);
|
|
25404
25654
|
|
|
25405
25655
|
// source/gui/client/components/IssueDetails.tsx
|
|
25406
|
-
var
|
|
25656
|
+
var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
|
|
25407
25657
|
var IssueDetails = ({
|
|
25408
25658
|
whoAmI,
|
|
25409
25659
|
comments,
|
|
@@ -25421,18 +25671,22 @@ var IssueDetails = ({
|
|
|
25421
25671
|
onReopenIssue,
|
|
25422
25672
|
onAddComment,
|
|
25423
25673
|
onDeleteComment,
|
|
25674
|
+
attachments,
|
|
25675
|
+
attachmentUploadStatus,
|
|
25676
|
+
onUploadAttachments,
|
|
25677
|
+
onDeleteAttachment,
|
|
25424
25678
|
knownTags: tags,
|
|
25425
25679
|
knownAssignees: assignees
|
|
25426
25680
|
}) => {
|
|
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,
|
|
25681
|
+
const [title, setTitle] = (0, import_react7.useState)("");
|
|
25682
|
+
const [description, setDescription] = (0, import_react7.useState)("");
|
|
25683
|
+
const [tagName, setTagName] = (0, import_react7.useState)("");
|
|
25684
|
+
const [assigneeName, setAssigneeName] = (0, import_react7.useState)("");
|
|
25685
|
+
const [editingTitle, setEditingTitle] = (0, import_react7.useState)(false);
|
|
25686
|
+
const [editingDescription, setEditingDescription] = (0, import_react7.useState)(false);
|
|
25687
|
+
const [addingTag, setAddingTag] = (0, import_react7.useState)(false);
|
|
25688
|
+
const [addingAssignee, setAddingAssignee] = (0, import_react7.useState)(false);
|
|
25689
|
+
(0, import_react7.useEffect)(() => {
|
|
25436
25690
|
setTitle(issue?.title ?? "");
|
|
25437
25691
|
setDescription(issue?.description ?? "");
|
|
25438
25692
|
setTagName("");
|
|
@@ -25492,9 +25746,9 @@ var IssueDetails = ({
|
|
|
25492
25746
|
const availableAssignees = assignees.filter(
|
|
25493
25747
|
(assignee) => !issue?.assignees.some((issueAssignee) => issueAssignee.id === assignee.id)
|
|
25494
25748
|
);
|
|
25495
|
-
return /* @__PURE__ */ (0,
|
|
25496
|
-
/* @__PURE__ */ (0,
|
|
25497
|
-
/* @__PURE__ */ (0,
|
|
25749
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Aside, { children: issue ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
25750
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(FormHeader, { children: [
|
|
25751
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25498
25752
|
"span",
|
|
25499
25753
|
{
|
|
25500
25754
|
style: {
|
|
@@ -25503,19 +25757,19 @@ var IssueDetails = ({
|
|
|
25503
25757
|
textTransform: "uppercase",
|
|
25504
25758
|
letterSpacing: "0.08em"
|
|
25505
25759
|
},
|
|
25506
|
-
children: issue.ref && /* @__PURE__ */ (0,
|
|
25760
|
+
children: issue.ref && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CopyRef, { refValue: issue.ref })
|
|
25507
25761
|
}
|
|
25508
25762
|
),
|
|
25509
|
-
/* @__PURE__ */ (0,
|
|
25763
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "ghost", onClick: onClose, children: "\xD7" })
|
|
25510
25764
|
] }),
|
|
25511
|
-
/* @__PURE__ */ (0,
|
|
25512
|
-
activeTab === "overview" && /* @__PURE__ */ (0,
|
|
25513
|
-
/* @__PURE__ */ (0,
|
|
25765
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Tabs, { tabs, activeTab, onChange: onChangeTab }),
|
|
25766
|
+
activeTab === "overview" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
25767
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25514
25768
|
Section,
|
|
25515
25769
|
{
|
|
25516
25770
|
first: true,
|
|
25517
25771
|
title: "Title",
|
|
25518
|
-
action: !issue.readonly && !editingTitle && /* @__PURE__ */ (0,
|
|
25772
|
+
action: !issue.readonly && !editingTitle && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25519
25773
|
Button,
|
|
25520
25774
|
{
|
|
25521
25775
|
variant: "ghost",
|
|
@@ -25523,8 +25777,8 @@ var IssueDetails = ({
|
|
|
25523
25777
|
children: "edit"
|
|
25524
25778
|
}
|
|
25525
25779
|
),
|
|
25526
|
-
children: editingTitle ? /* @__PURE__ */ (0,
|
|
25527
|
-
/* @__PURE__ */ (0,
|
|
25780
|
+
children: editingTitle ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
25781
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25528
25782
|
Input,
|
|
25529
25783
|
{
|
|
25530
25784
|
value: title,
|
|
@@ -25536,11 +25790,11 @@ var IssueDetails = ({
|
|
|
25536
25790
|
}
|
|
25537
25791
|
}
|
|
25538
25792
|
),
|
|
25539
|
-
/* @__PURE__ */ (0,
|
|
25540
|
-
/* @__PURE__ */ (0,
|
|
25541
|
-
/* @__PURE__ */ (0,
|
|
25793
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(ActionRow, { children: [
|
|
25794
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: saveTitle, children: "save" }),
|
|
25795
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "ghost", onClick: cancelTitle, children: "cancel" })
|
|
25542
25796
|
] })
|
|
25543
|
-
] }) : /* @__PURE__ */ (0,
|
|
25797
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25544
25798
|
"div",
|
|
25545
25799
|
{
|
|
25546
25800
|
style: {
|
|
@@ -25555,11 +25809,11 @@ var IssueDetails = ({
|
|
|
25555
25809
|
)
|
|
25556
25810
|
}
|
|
25557
25811
|
),
|
|
25558
|
-
/* @__PURE__ */ (0,
|
|
25812
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25559
25813
|
Section,
|
|
25560
25814
|
{
|
|
25561
25815
|
title: "Description",
|
|
25562
|
-
action: !issue.readonly && !editingDescription && /* @__PURE__ */ (0,
|
|
25816
|
+
action: !issue.readonly && !editingDescription && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25563
25817
|
Button,
|
|
25564
25818
|
{
|
|
25565
25819
|
variant: "ghost",
|
|
@@ -25567,8 +25821,8 @@ var IssueDetails = ({
|
|
|
25567
25821
|
children: "edit"
|
|
25568
25822
|
}
|
|
25569
25823
|
),
|
|
25570
|
-
children: editingDescription ? /* @__PURE__ */ (0,
|
|
25571
|
-
/* @__PURE__ */ (0,
|
|
25824
|
+
children: editingDescription ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
25825
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25572
25826
|
Textarea,
|
|
25573
25827
|
{
|
|
25574
25828
|
value: description,
|
|
@@ -25583,31 +25837,34 @@ var IssueDetails = ({
|
|
|
25583
25837
|
}
|
|
25584
25838
|
}
|
|
25585
25839
|
),
|
|
25586
|
-
/* @__PURE__ */ (0,
|
|
25587
|
-
/* @__PURE__ */ (0,
|
|
25588
|
-
/* @__PURE__ */ (0,
|
|
25840
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(ActionRow, { children: [
|
|
25841
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: saveDescription, children: "save" }),
|
|
25842
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "ghost", onClick: cancelDescription, children: "cancel" })
|
|
25589
25843
|
] })
|
|
25590
|
-
] }) : issue.description ? /* @__PURE__ */ (0,
|
|
25844
|
+
] }) : issue.description ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25591
25845
|
"p",
|
|
25592
25846
|
{
|
|
25593
25847
|
style: {
|
|
25594
25848
|
lineHeight: 1.55,
|
|
25595
25849
|
whiteSpace: "pre-wrap",
|
|
25596
25850
|
margin: "8px 0 0",
|
|
25851
|
+
padding: "12px 16px",
|
|
25852
|
+
background: "rgba(0, 0, 0, 0.22)",
|
|
25853
|
+
borderRadius: 8,
|
|
25597
25854
|
color: GUI_THEME.primary
|
|
25598
25855
|
},
|
|
25599
25856
|
children: issue.description
|
|
25600
25857
|
}
|
|
25601
|
-
) : /* @__PURE__ */ (0,
|
|
25858
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Empty, { children: "No description" })
|
|
25602
25859
|
}
|
|
25603
25860
|
),
|
|
25604
|
-
/* @__PURE__ */ (0,
|
|
25861
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25605
25862
|
Section,
|
|
25606
25863
|
{
|
|
25607
25864
|
title: "Tags",
|
|
25608
|
-
action: !issue.readonly && !addingTag && /* @__PURE__ */ (0,
|
|
25865
|
+
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
25866
|
children: [
|
|
25610
|
-
/* @__PURE__ */ (0,
|
|
25867
|
+
/* @__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
25868
|
Button,
|
|
25612
25869
|
{
|
|
25613
25870
|
variant: "chip",
|
|
@@ -25623,7 +25880,7 @@ var IssueDetails = ({
|
|
|
25623
25880
|
},
|
|
25624
25881
|
tag.id
|
|
25625
25882
|
)) }),
|
|
25626
|
-
addingTag && /* @__PURE__ */ (0,
|
|
25883
|
+
addingTag && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChipRow, { children: availableTags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25627
25884
|
Button,
|
|
25628
25885
|
{
|
|
25629
25886
|
variant: "chip",
|
|
@@ -25638,8 +25895,8 @@ var IssueDetails = ({
|
|
|
25638
25895
|
},
|
|
25639
25896
|
tag.id
|
|
25640
25897
|
)) }),
|
|
25641
|
-
addingTag && /* @__PURE__ */ (0,
|
|
25642
|
-
/* @__PURE__ */ (0,
|
|
25898
|
+
addingTag && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(AddRow, { children: [
|
|
25899
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25643
25900
|
Input,
|
|
25644
25901
|
{
|
|
25645
25902
|
value: tagName,
|
|
@@ -25655,23 +25912,23 @@ var IssueDetails = ({
|
|
|
25655
25912
|
}
|
|
25656
25913
|
}
|
|
25657
25914
|
),
|
|
25658
|
-
/* @__PURE__ */ (0,
|
|
25915
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: addTag, children: "add" })
|
|
25659
25916
|
] })
|
|
25660
25917
|
]
|
|
25661
25918
|
}
|
|
25662
25919
|
),
|
|
25663
|
-
/* @__PURE__ */ (0,
|
|
25920
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25664
25921
|
Section,
|
|
25665
25922
|
{
|
|
25666
25923
|
title: "Assignees",
|
|
25667
|
-
action: !issue.readonly && !addingAssignee && /* @__PURE__ */ (0,
|
|
25924
|
+
action: !issue.readonly && !addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25668
25925
|
Button,
|
|
25669
25926
|
{
|
|
25670
25927
|
variant: "ghost",
|
|
25671
25928
|
onClick: () => setAddingAssignee(true),
|
|
25672
25929
|
children: "+"
|
|
25673
25930
|
}
|
|
25674
|
-
) || addingAssignee && /* @__PURE__ */ (0,
|
|
25931
|
+
) || addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25675
25932
|
Button,
|
|
25676
25933
|
{
|
|
25677
25934
|
variant: "ghost",
|
|
@@ -25680,7 +25937,7 @@ var IssueDetails = ({
|
|
|
25680
25937
|
}
|
|
25681
25938
|
),
|
|
25682
25939
|
children: [
|
|
25683
|
-
/* @__PURE__ */ (0,
|
|
25940
|
+
/* @__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
25941
|
Button,
|
|
25685
25942
|
{
|
|
25686
25943
|
variant: "chip",
|
|
@@ -25697,7 +25954,7 @@ var IssueDetails = ({
|
|
|
25697
25954
|
},
|
|
25698
25955
|
assignee.id
|
|
25699
25956
|
)) }),
|
|
25700
|
-
addingAssignee && /* @__PURE__ */ (0,
|
|
25957
|
+
addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChipRow, { children: availableAssignees.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
25701
25958
|
Button,
|
|
25702
25959
|
{
|
|
25703
25960
|
variant: "chip",
|
|
@@ -25712,8 +25969,8 @@ var IssueDetails = ({
|
|
|
25712
25969
|
},
|
|
25713
25970
|
assignee.id
|
|
25714
25971
|
)) }),
|
|
25715
|
-
addingAssignee && /* @__PURE__ */ (0,
|
|
25716
|
-
/* @__PURE__ */ (0,
|
|
25972
|
+
addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(AddRow, { children: [
|
|
25973
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25717
25974
|
Input,
|
|
25718
25975
|
{
|
|
25719
25976
|
value: assigneeName,
|
|
@@ -25729,21 +25986,32 @@ var IssueDetails = ({
|
|
|
25729
25986
|
}
|
|
25730
25987
|
}
|
|
25731
25988
|
),
|
|
25732
|
-
/* @__PURE__ */ (0,
|
|
25989
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { onClick: addAssignee, children: "add" })
|
|
25733
25990
|
] })
|
|
25734
25991
|
]
|
|
25735
25992
|
}
|
|
25736
25993
|
),
|
|
25737
|
-
/* @__PURE__ */ (0,
|
|
25994
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25995
|
+
IssueAttachments,
|
|
25996
|
+
{
|
|
25997
|
+
issueId: issue.id,
|
|
25998
|
+
readonly: Boolean(issue.readonly),
|
|
25999
|
+
attachments,
|
|
26000
|
+
uploadStatus: attachmentUploadStatus,
|
|
26001
|
+
onUploadFiles: onUploadAttachments,
|
|
26002
|
+
onDeleteAttachment
|
|
26003
|
+
}
|
|
26004
|
+
),
|
|
26005
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25738
26006
|
Section,
|
|
25739
26007
|
{
|
|
25740
26008
|
title: "Actions",
|
|
25741
|
-
action: issue.isClosed ? /* @__PURE__ */ (0,
|
|
26009
|
+
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
26010
|
children: ""
|
|
25743
26011
|
}
|
|
25744
26012
|
)
|
|
25745
26013
|
] }),
|
|
25746
|
-
activeTab === "comments" && /* @__PURE__ */ (0,
|
|
26014
|
+
activeTab === "comments" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25747
26015
|
IssueComments,
|
|
25748
26016
|
{
|
|
25749
26017
|
whoAmI,
|
|
@@ -25754,15 +26022,15 @@ var IssueDetails = ({
|
|
|
25754
26022
|
onDeleteComment
|
|
25755
26023
|
}
|
|
25756
26024
|
)
|
|
25757
|
-
] }) : /* @__PURE__ */ (0,
|
|
26025
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Empty, { children: "Select an issue" }) });
|
|
25758
26026
|
};
|
|
25759
26027
|
|
|
25760
26028
|
// source/gui/client/components/SwimlaneColumn.tsx
|
|
25761
|
-
var
|
|
26029
|
+
var import_react8 = __toESM(require_react(), 1);
|
|
25762
26030
|
|
|
25763
26031
|
// source/gui/client/components/IconComment.tsx
|
|
25764
|
-
var
|
|
25765
|
-
var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
26032
|
+
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
26033
|
+
var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
25766
26034
|
"svg",
|
|
25767
26035
|
{
|
|
25768
26036
|
width: size,
|
|
@@ -25770,7 +26038,7 @@ var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.js
|
|
|
25770
26038
|
viewBox: "0 0 16 16",
|
|
25771
26039
|
fill: "none",
|
|
25772
26040
|
"aria-hidden": "true",
|
|
25773
|
-
children: /* @__PURE__ */ (0,
|
|
26041
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
25774
26042
|
"path",
|
|
25775
26043
|
{
|
|
25776
26044
|
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 +26053,7 @@ var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime15.js
|
|
|
25785
26053
|
);
|
|
25786
26054
|
|
|
25787
26055
|
// source/gui/client/components/TicketCard.tsx
|
|
25788
|
-
var
|
|
26056
|
+
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
25789
26057
|
var TicketCard = ({
|
|
25790
26058
|
ticket,
|
|
25791
26059
|
index,
|
|
@@ -25798,7 +26066,7 @@ var TicketCard = ({
|
|
|
25798
26066
|
onDropIssueAt
|
|
25799
26067
|
}) => {
|
|
25800
26068
|
const getVisualTargetIndex = (isAfterMiddle) => index + (isAfterMiddle ? 1 : 0);
|
|
25801
|
-
return /* @__PURE__ */ (0,
|
|
26069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25802
26070
|
"div",
|
|
25803
26071
|
{
|
|
25804
26072
|
draggable: !ticket.readonly,
|
|
@@ -25839,7 +26107,7 @@ var TicketCard = ({
|
|
|
25839
26107
|
border: `1px solid ${isSelected ? GUI_THEME.accent : "transparent"}`
|
|
25840
26108
|
},
|
|
25841
26109
|
children: [
|
|
25842
|
-
/* @__PURE__ */ (0,
|
|
26110
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25843
26111
|
"div",
|
|
25844
26112
|
{
|
|
25845
26113
|
style: {
|
|
@@ -25852,7 +26120,7 @@ var TicketCard = ({
|
|
|
25852
26120
|
children: isSelected ? "\u276F" : index + 1
|
|
25853
26121
|
}
|
|
25854
26122
|
),
|
|
25855
|
-
/* @__PURE__ */ (0,
|
|
26123
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25856
26124
|
"div",
|
|
25857
26125
|
{
|
|
25858
26126
|
style: {
|
|
@@ -25863,7 +26131,7 @@ var TicketCard = ({
|
|
|
25863
26131
|
gap: 12
|
|
25864
26132
|
},
|
|
25865
26133
|
children: [
|
|
25866
|
-
/* @__PURE__ */ (0,
|
|
26134
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25867
26135
|
"div",
|
|
25868
26136
|
{
|
|
25869
26137
|
style: {
|
|
@@ -25874,7 +26142,7 @@ var TicketCard = ({
|
|
|
25874
26142
|
flex: 1
|
|
25875
26143
|
},
|
|
25876
26144
|
children: [
|
|
25877
|
-
/* @__PURE__ */ (0,
|
|
26145
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25878
26146
|
"div",
|
|
25879
26147
|
{
|
|
25880
26148
|
style: {
|
|
@@ -25884,10 +26152,10 @@ var TicketCard = ({
|
|
|
25884
26152
|
fontWeight: 500,
|
|
25885
26153
|
fontSize: 12
|
|
25886
26154
|
},
|
|
25887
|
-
children: ticket.ref && /* @__PURE__ */ (0,
|
|
26155
|
+
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
26156
|
}
|
|
25889
26157
|
),
|
|
25890
|
-
/* @__PURE__ */ (0,
|
|
26158
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25891
26159
|
"div",
|
|
25892
26160
|
{
|
|
25893
26161
|
style: {
|
|
@@ -25900,7 +26168,7 @@ var TicketCard = ({
|
|
|
25900
26168
|
children: ticket.title
|
|
25901
26169
|
}
|
|
25902
26170
|
),
|
|
25903
|
-
/* @__PURE__ */ (0,
|
|
26171
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25904
26172
|
"div",
|
|
25905
26173
|
{
|
|
25906
26174
|
style: {
|
|
@@ -25909,7 +26177,7 @@ var TicketCard = ({
|
|
|
25909
26177
|
gap: 6,
|
|
25910
26178
|
alignItems: "center"
|
|
25911
26179
|
},
|
|
25912
|
-
children: ticket.tags.map((tag) => /* @__PURE__ */ (0,
|
|
26180
|
+
children: ticket.tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25913
26181
|
"span",
|
|
25914
26182
|
{
|
|
25915
26183
|
style: {
|
|
@@ -25929,7 +26197,7 @@ var TicketCard = ({
|
|
|
25929
26197
|
]
|
|
25930
26198
|
}
|
|
25931
26199
|
),
|
|
25932
|
-
/* @__PURE__ */ (0,
|
|
26200
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25933
26201
|
"div",
|
|
25934
26202
|
{
|
|
25935
26203
|
style: {
|
|
@@ -25939,7 +26207,7 @@ var TicketCard = ({
|
|
|
25939
26207
|
flexShrink: 0,
|
|
25940
26208
|
paddingTop: 2
|
|
25941
26209
|
},
|
|
25942
|
-
children: commentCount > 0 && /* @__PURE__ */ (0,
|
|
26210
|
+
children: commentCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25943
26211
|
"button",
|
|
25944
26212
|
{
|
|
25945
26213
|
type: "button",
|
|
@@ -25977,14 +26245,14 @@ var TicketCard = ({
|
|
|
25977
26245
|
event.currentTarget.style.transform = "translateY(0)";
|
|
25978
26246
|
},
|
|
25979
26247
|
children: [
|
|
25980
|
-
/* @__PURE__ */ (0,
|
|
25981
|
-
/* @__PURE__ */ (0,
|
|
26248
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconComment, {}),
|
|
26249
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: commentCount })
|
|
25982
26250
|
]
|
|
25983
26251
|
}
|
|
25984
26252
|
)
|
|
25985
26253
|
}
|
|
25986
26254
|
),
|
|
25987
|
-
ticket.assignees.length > 0 && /* @__PURE__ */ (0,
|
|
26255
|
+
ticket.assignees.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25988
26256
|
"div",
|
|
25989
26257
|
{
|
|
25990
26258
|
style: {
|
|
@@ -25994,7 +26262,7 @@ var TicketCard = ({
|
|
|
25994
26262
|
paddingTop: 2,
|
|
25995
26263
|
marginTop: "-4px"
|
|
25996
26264
|
},
|
|
25997
|
-
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0,
|
|
26265
|
+
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(User, { user: assignee, index: idx, isFocus: isSelected }))
|
|
25998
26266
|
}
|
|
25999
26267
|
)
|
|
26000
26268
|
]
|
|
@@ -26006,7 +26274,7 @@ var TicketCard = ({
|
|
|
26006
26274
|
};
|
|
26007
26275
|
|
|
26008
26276
|
// source/gui/client/components/SwimlaneColumn.tsx
|
|
26009
|
-
var
|
|
26277
|
+
var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
|
|
26010
26278
|
var SwimlaneColumn = ({
|
|
26011
26279
|
swimlane,
|
|
26012
26280
|
selected,
|
|
@@ -26022,7 +26290,7 @@ var SwimlaneColumn = ({
|
|
|
26022
26290
|
onDragOverIssue,
|
|
26023
26291
|
onDragLeave
|
|
26024
26292
|
}) => {
|
|
26025
|
-
return /* @__PURE__ */ (0,
|
|
26293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
26026
26294
|
Panel,
|
|
26027
26295
|
{
|
|
26028
26296
|
as: "section",
|
|
@@ -26062,7 +26330,7 @@ var SwimlaneColumn = ({
|
|
|
26062
26330
|
onDragLeave();
|
|
26063
26331
|
},
|
|
26064
26332
|
children: [
|
|
26065
|
-
/* @__PURE__ */ (0,
|
|
26333
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
26066
26334
|
"header",
|
|
26067
26335
|
{
|
|
26068
26336
|
style: {
|
|
@@ -26073,7 +26341,7 @@ var SwimlaneColumn = ({
|
|
|
26073
26341
|
alignItems: "center"
|
|
26074
26342
|
},
|
|
26075
26343
|
children: [
|
|
26076
|
-
/* @__PURE__ */ (0,
|
|
26344
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
26077
26345
|
"div",
|
|
26078
26346
|
{
|
|
26079
26347
|
style: {
|
|
@@ -26082,30 +26350,30 @@ var SwimlaneColumn = ({
|
|
|
26082
26350
|
gap: 8
|
|
26083
26351
|
},
|
|
26084
26352
|
children: [
|
|
26085
|
-
/* @__PURE__ */ (0,
|
|
26353
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26086
26354
|
"span",
|
|
26087
26355
|
{
|
|
26088
26356
|
style: { color: selected ? GUI_THEME.accent : GUI_THEME.secondary },
|
|
26089
26357
|
children: selected ? "\u276F" : " "
|
|
26090
26358
|
}
|
|
26091
26359
|
),
|
|
26092
|
-
/* @__PURE__ */ (0,
|
|
26360
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26093
26361
|
"strong",
|
|
26094
26362
|
{
|
|
26095
26363
|
style: { color: selected ? GUI_THEME.accent : GUI_THEME.primary },
|
|
26096
26364
|
children: swimlane.title
|
|
26097
26365
|
}
|
|
26098
26366
|
),
|
|
26099
|
-
/* @__PURE__ */ (0,
|
|
26367
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { style: { color: GUI_THEME.dim }, children: [
|
|
26100
26368
|
"(",
|
|
26101
26369
|
swimlane.issues.length,
|
|
26102
26370
|
")"
|
|
26103
26371
|
] }),
|
|
26104
|
-
swimlane.readonly && /* @__PURE__ */ (0,
|
|
26372
|
+
swimlane.readonly && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "\u{1F512}" })
|
|
26105
26373
|
]
|
|
26106
26374
|
}
|
|
26107
26375
|
),
|
|
26108
|
-
/* @__PURE__ */ (0,
|
|
26376
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26109
26377
|
Button,
|
|
26110
26378
|
{
|
|
26111
26379
|
variant: "ghost",
|
|
@@ -26118,9 +26386,9 @@ var SwimlaneColumn = ({
|
|
|
26118
26386
|
]
|
|
26119
26387
|
}
|
|
26120
26388
|
),
|
|
26121
|
-
/* @__PURE__ */ (0,
|
|
26122
|
-
dropIndex === 0 && /* @__PURE__ */ (0,
|
|
26123
|
-
/* @__PURE__ */ (0,
|
|
26389
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { overflow: "auto", paddingTop: 4, flex: 1 }, children: swimlane.issues.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
26390
|
+
dropIndex === 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropIndicator, {}),
|
|
26391
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26124
26392
|
"div",
|
|
26125
26393
|
{
|
|
26126
26394
|
style: {
|
|
@@ -26132,10 +26400,10 @@ var SwimlaneColumn = ({
|
|
|
26132
26400
|
children: "Drop issue here"
|
|
26133
26401
|
}
|
|
26134
26402
|
)
|
|
26135
|
-
] }) : /* @__PURE__ */ (0,
|
|
26136
|
-
swimlane.issues.map((ticket, index) => /* @__PURE__ */ (0,
|
|
26137
|
-
dropIndex === index && /* @__PURE__ */ (0,
|
|
26138
|
-
/* @__PURE__ */ (0,
|
|
26403
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
26404
|
+
swimlane.issues.map((ticket, index) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react8.default.Fragment, { children: [
|
|
26405
|
+
dropIndex === index && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropIndicator, {}),
|
|
26406
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26139
26407
|
TicketCard,
|
|
26140
26408
|
{
|
|
26141
26409
|
ticket,
|
|
@@ -26153,7 +26421,7 @@ var SwimlaneColumn = ({
|
|
|
26153
26421
|
}
|
|
26154
26422
|
)
|
|
26155
26423
|
] }, ticket.id)),
|
|
26156
|
-
dropIndex === swimlane.issues.length && /* @__PURE__ */ (0,
|
|
26424
|
+
dropIndex === swimlane.issues.length && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropIndicator, {})
|
|
26157
26425
|
] }) })
|
|
26158
26426
|
]
|
|
26159
26427
|
}
|
|
@@ -26291,9 +26559,73 @@ var updateIssueInGuiState = (state, issueId, updateIssue) => ({
|
|
|
26291
26559
|
}))
|
|
26292
26560
|
});
|
|
26293
26561
|
|
|
26562
|
+
// source/gui/client/lib/compress-image.ts
|
|
26563
|
+
var MAX_LONG_EDGE = 1600;
|
|
26564
|
+
var DEFAULT_MAX_KB = 500;
|
|
26565
|
+
var QUALITY_STEPS = [0.8, 0.7, 0.6, 0.5, 0.4];
|
|
26566
|
+
var toBlob = (canvas, type, quality) => new Promise((resolve) => canvas.toBlob(resolve, type, quality));
|
|
26567
|
+
var replaceExtension = (name, ext) => {
|
|
26568
|
+
const base = name.replace(/\.[a-z0-9]+$/i, "");
|
|
26569
|
+
return `${base || "image"}.${ext}`;
|
|
26570
|
+
};
|
|
26571
|
+
var compressImage = async (file, maxKb = DEFAULT_MAX_KB) => {
|
|
26572
|
+
const maxBytes = maxKb * 1024;
|
|
26573
|
+
if (file.type === "image/gif") {
|
|
26574
|
+
if (file.size <= maxBytes) {
|
|
26575
|
+
return { blob: file, name: file.name };
|
|
26576
|
+
}
|
|
26577
|
+
return {
|
|
26578
|
+
error: `GIFs are attached as-is and this one exceeds ${maxKb} KB`
|
|
26579
|
+
};
|
|
26580
|
+
}
|
|
26581
|
+
let bitmap;
|
|
26582
|
+
try {
|
|
26583
|
+
bitmap = await createImageBitmap(file);
|
|
26584
|
+
} catch {
|
|
26585
|
+
return { error: "Not a supported image" };
|
|
26586
|
+
}
|
|
26587
|
+
const scale = Math.min(
|
|
26588
|
+
1,
|
|
26589
|
+
MAX_LONG_EDGE / Math.max(bitmap.width, bitmap.height)
|
|
26590
|
+
);
|
|
26591
|
+
const canvas = document.createElement("canvas");
|
|
26592
|
+
canvas.width = Math.max(1, Math.round(bitmap.width * scale));
|
|
26593
|
+
canvas.height = Math.max(1, Math.round(bitmap.height * scale));
|
|
26594
|
+
const context = canvas.getContext("2d");
|
|
26595
|
+
if (!context) {
|
|
26596
|
+
bitmap.close();
|
|
26597
|
+
return { error: "Unable to process image" };
|
|
26598
|
+
}
|
|
26599
|
+
context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
|
|
26600
|
+
bitmap.close();
|
|
26601
|
+
for (const quality of QUALITY_STEPS) {
|
|
26602
|
+
const blob = await toBlob(canvas, "image/webp", quality);
|
|
26603
|
+
if (blob && blob.size <= maxBytes) {
|
|
26604
|
+
return { blob, name: replaceExtension(file.name, "webp") };
|
|
26605
|
+
}
|
|
26606
|
+
}
|
|
26607
|
+
return {
|
|
26608
|
+
error: `Unable to compress image under ${maxKb} KB`
|
|
26609
|
+
};
|
|
26610
|
+
};
|
|
26611
|
+
var blobToBase64 = (blob) => new Promise((resolve, reject) => {
|
|
26612
|
+
const reader = new FileReader();
|
|
26613
|
+
reader.onload = () => {
|
|
26614
|
+
const dataUrl = String(reader.result ?? "");
|
|
26615
|
+
const base64 = dataUrl.split(",")[1];
|
|
26616
|
+
if (!base64) {
|
|
26617
|
+
reject(new Error("Unable to encode image"));
|
|
26618
|
+
return;
|
|
26619
|
+
}
|
|
26620
|
+
resolve(base64);
|
|
26621
|
+
};
|
|
26622
|
+
reader.onerror = () => reject(new Error("Unable to read image"));
|
|
26623
|
+
reader.readAsDataURL(blob);
|
|
26624
|
+
});
|
|
26625
|
+
|
|
26294
26626
|
// source/gui/client/App.tsx
|
|
26295
|
-
var
|
|
26296
|
-
var DropIndicator = () => /* @__PURE__ */ (0,
|
|
26627
|
+
var import_jsx_runtime19 = __toESM(require_jsx_runtime(), 1);
|
|
26628
|
+
var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26297
26629
|
"div",
|
|
26298
26630
|
{
|
|
26299
26631
|
style: {
|
|
@@ -26308,34 +26640,51 @@ var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
|
26308
26640
|
var App = () => {
|
|
26309
26641
|
const { boardId, issueId } = useParams();
|
|
26310
26642
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
26311
|
-
const [connected, setConnected] = (0,
|
|
26312
|
-
const [syncStatus, setSyncStatus] = (0,
|
|
26643
|
+
const [connected, setConnected] = (0, import_react9.useState)(false);
|
|
26644
|
+
const [syncStatus, setSyncStatus] = (0, import_react9.useState)({
|
|
26313
26645
|
status: "synced",
|
|
26314
26646
|
msg: "idle"
|
|
26315
26647
|
});
|
|
26316
|
-
const [state, setState] = (0,
|
|
26317
|
-
const [dragOverSwimlaneId, setDragOverSwimlaneId] = (0,
|
|
26648
|
+
const [state, setState] = (0, import_react9.useState)(null);
|
|
26649
|
+
const [dragOverSwimlaneId, setDragOverSwimlaneId] = (0, import_react9.useState)(
|
|
26318
26650
|
null
|
|
26319
26651
|
);
|
|
26320
|
-
const [dropTarget, setDropTarget] = (0,
|
|
26321
|
-
const [boardMenuOpen, setBoardMenuOpen] = (0,
|
|
26322
|
-
const [createIssueModal, setCreateIssueModal] = (0,
|
|
26323
|
-
const boardMenuRef = (0,
|
|
26324
|
-
const socketRef = (0,
|
|
26652
|
+
const [dropTarget, setDropTarget] = (0, import_react9.useState)(null);
|
|
26653
|
+
const [boardMenuOpen, setBoardMenuOpen] = (0, import_react9.useState)(false);
|
|
26654
|
+
const [createIssueModal, setCreateIssueModal] = (0, import_react9.useState)(null);
|
|
26655
|
+
const boardMenuRef = (0, import_react9.useRef)(null);
|
|
26656
|
+
const socketRef = (0, import_react9.useRef)(null);
|
|
26325
26657
|
const selectedTab = searchParams.get("tab") === "comments" ? "comments" : "overview";
|
|
26326
26658
|
const navigate = useNavigate();
|
|
26327
26659
|
const selectedBoard = (state && boardId ? findBoard(state, boardId) : null) ?? state?.boards[0] ?? null;
|
|
26328
26660
|
const boardSlug = selectedBoard?.ref ?? boardId;
|
|
26329
26661
|
const selectedIssue = state && issueId ? findIssue(state, issueId) : null;
|
|
26662
|
+
(0, import_react9.useEffect)(() => {
|
|
26663
|
+
const onPaste = (event) => {
|
|
26664
|
+
if (!selectedIssue || selectedIssue.readonly) return;
|
|
26665
|
+
const target = event.target;
|
|
26666
|
+
if (target && (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable)) {
|
|
26667
|
+
return;
|
|
26668
|
+
}
|
|
26669
|
+
const files = Array.from(event.clipboardData?.items ?? []).filter((item) => item.kind === "file" && item.type.startsWith("image/")).map((item) => item.getAsFile()).filter((file) => Boolean(file));
|
|
26670
|
+
if (files.length === 0) return;
|
|
26671
|
+
event.preventDefault();
|
|
26672
|
+
void uploadIssueAttachments(selectedIssue.id, files);
|
|
26673
|
+
};
|
|
26674
|
+
window.addEventListener("paste", onPaste);
|
|
26675
|
+
return () => window.removeEventListener("paste", onPaste);
|
|
26676
|
+
});
|
|
26330
26677
|
const closeIssueDetails = () => {
|
|
26331
26678
|
if (!boardSlug) return;
|
|
26332
26679
|
void navigate(`/board/${boardSlug}`);
|
|
26333
26680
|
};
|
|
26334
26681
|
const commentsByIssueId = state?.commentsByIssueId ?? {};
|
|
26682
|
+
const attachmentsByIssueId = state?.attachmentsByIssueId ?? {};
|
|
26683
|
+
const [attachmentUploadStatus, setAttachmentUploadStatus] = (0, import_react9.useState)({ state: "idle" });
|
|
26335
26684
|
const requestState = () => {
|
|
26336
26685
|
socketRef.current?.send(JSON.stringify({ type: "state:get" }));
|
|
26337
26686
|
};
|
|
26338
|
-
(0,
|
|
26687
|
+
(0, import_react9.useEffect)(() => {
|
|
26339
26688
|
const socket = new WebSocket(
|
|
26340
26689
|
`ws://${window.location.host}/ws${boardId ? `?boardId=${boardId}` : ""}`
|
|
26341
26690
|
);
|
|
@@ -26379,12 +26728,12 @@ var App = () => {
|
|
|
26379
26728
|
socket.close();
|
|
26380
26729
|
};
|
|
26381
26730
|
}, [boardId, navigate]);
|
|
26382
|
-
(0,
|
|
26731
|
+
(0, import_react9.useEffect)(() => {
|
|
26383
26732
|
if (!boardId && state?.boards[0]) {
|
|
26384
26733
|
void navigate(`/board/${state.boards[0].ref}`, { replace: true });
|
|
26385
26734
|
}
|
|
26386
26735
|
}, [boardId, state, navigate]);
|
|
26387
|
-
(0,
|
|
26736
|
+
(0, import_react9.useEffect)(() => {
|
|
26388
26737
|
const close = (event) => {
|
|
26389
26738
|
if (boardMenuRef.current && !boardMenuRef.current.contains(event.target)) {
|
|
26390
26739
|
setBoardMenuOpen(false);
|
|
@@ -26569,6 +26918,68 @@ var App = () => {
|
|
|
26569
26918
|
});
|
|
26570
26919
|
send("issue:comment:add", { issueId: issueId2, body });
|
|
26571
26920
|
};
|
|
26921
|
+
const uploadIssueAttachments = async (issueId2, files) => {
|
|
26922
|
+
for (const file of files) {
|
|
26923
|
+
setAttachmentUploadStatus({ state: "uploading", name: file.name });
|
|
26924
|
+
const compressed = await compressImage(file, state?.attachmentMaxKb);
|
|
26925
|
+
if ("error" in compressed) {
|
|
26926
|
+
setAttachmentUploadStatus({ state: "error", message: compressed.error });
|
|
26927
|
+
return;
|
|
26928
|
+
}
|
|
26929
|
+
try {
|
|
26930
|
+
const dataBase64 = await blobToBase64(compressed.blob);
|
|
26931
|
+
const response = await fetch("/api/attachments", {
|
|
26932
|
+
method: "POST",
|
|
26933
|
+
headers: { "content-type": "application/json" },
|
|
26934
|
+
body: JSON.stringify({
|
|
26935
|
+
issueId: issueId2,
|
|
26936
|
+
name: compressed.name,
|
|
26937
|
+
dataBase64
|
|
26938
|
+
})
|
|
26939
|
+
});
|
|
26940
|
+
const payload = await response.json();
|
|
26941
|
+
if (!response.ok) {
|
|
26942
|
+
setAttachmentUploadStatus({
|
|
26943
|
+
state: "error",
|
|
26944
|
+
message: payload?.message ?? "Upload failed"
|
|
26945
|
+
});
|
|
26946
|
+
return;
|
|
26947
|
+
}
|
|
26948
|
+
const nextState = getResultValue(payload);
|
|
26949
|
+
if (nextState) setState(nextState);
|
|
26950
|
+
} catch (error) {
|
|
26951
|
+
setAttachmentUploadStatus({
|
|
26952
|
+
state: "error",
|
|
26953
|
+
message: error instanceof Error ? error.message : "Upload failed"
|
|
26954
|
+
});
|
|
26955
|
+
return;
|
|
26956
|
+
}
|
|
26957
|
+
}
|
|
26958
|
+
setAttachmentUploadStatus({ state: "idle" });
|
|
26959
|
+
};
|
|
26960
|
+
const deleteIssueAttachment = async (_issueId, attachmentId) => {
|
|
26961
|
+
try {
|
|
26962
|
+
const response = await fetch(
|
|
26963
|
+
`/api/attachments/${encodeURIComponent(attachmentId)}`,
|
|
26964
|
+
{ method: "DELETE" }
|
|
26965
|
+
);
|
|
26966
|
+
const payload = await response.json();
|
|
26967
|
+
if (!response.ok) {
|
|
26968
|
+
setAttachmentUploadStatus({
|
|
26969
|
+
state: "error",
|
|
26970
|
+
message: payload?.message ?? "Unable to delete attachment"
|
|
26971
|
+
});
|
|
26972
|
+
return;
|
|
26973
|
+
}
|
|
26974
|
+
const nextState = getResultValue(payload);
|
|
26975
|
+
if (nextState) setState(nextState);
|
|
26976
|
+
} catch (error) {
|
|
26977
|
+
setAttachmentUploadStatus({
|
|
26978
|
+
state: "error",
|
|
26979
|
+
message: error instanceof Error ? error.message : "Unable to delete attachment"
|
|
26980
|
+
});
|
|
26981
|
+
}
|
|
26982
|
+
};
|
|
26572
26983
|
const deleteIssueComment = (_issueId, commentId) => {
|
|
26573
26984
|
setState((prev) => {
|
|
26574
26985
|
if (!prev) return prev;
|
|
@@ -26586,7 +26997,7 @@ var App = () => {
|
|
|
26586
26997
|
});
|
|
26587
26998
|
send("issue:comment:delete", { commentId });
|
|
26588
26999
|
};
|
|
26589
|
-
return /* @__PURE__ */ (0,
|
|
27000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
26590
27001
|
"div",
|
|
26591
27002
|
{
|
|
26592
27003
|
style: {
|
|
@@ -26598,8 +27009,8 @@ var App = () => {
|
|
|
26598
27009
|
flexDirection: "column"
|
|
26599
27010
|
},
|
|
26600
27011
|
children: [
|
|
26601
|
-
/* @__PURE__ */ (0,
|
|
26602
|
-
/* @__PURE__ */ (0,
|
|
27012
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Header, { state, connected, syncStatus }),
|
|
27013
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
26603
27014
|
"div",
|
|
26604
27015
|
{
|
|
26605
27016
|
style: {
|
|
@@ -26608,8 +27019,8 @@ var App = () => {
|
|
|
26608
27019
|
overflow: "hidden"
|
|
26609
27020
|
},
|
|
26610
27021
|
children: [
|
|
26611
|
-
/* @__PURE__ */ (0,
|
|
26612
|
-
/* @__PURE__ */ (0,
|
|
27022
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("main", { style: { padding: "0 30px 30px 30px", overflow: "auto", flex: 1 }, children: [
|
|
27023
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { padding: "20px 10px" }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26613
27024
|
Dropdown,
|
|
26614
27025
|
{
|
|
26615
27026
|
label: "Board:",
|
|
@@ -26625,7 +27036,7 @@ var App = () => {
|
|
|
26625
27036
|
onSelect: selectBoard
|
|
26626
27037
|
}
|
|
26627
27038
|
) }),
|
|
26628
|
-
/* @__PURE__ */ (0,
|
|
27039
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { display: "flex", gap: 8 }, children: selectedBoard?.swimlanes.map((swimlane) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26629
27040
|
SwimlaneColumn,
|
|
26630
27041
|
{
|
|
26631
27042
|
swimlane,
|
|
@@ -26645,7 +27056,7 @@ var App = () => {
|
|
|
26645
27056
|
swimlane.id
|
|
26646
27057
|
)) })
|
|
26647
27058
|
] }),
|
|
26648
|
-
selectedIssue && state?.user && /* @__PURE__ */ (0,
|
|
27059
|
+
selectedIssue && state?.user && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26649
27060
|
IssueDetails,
|
|
26650
27061
|
{
|
|
26651
27062
|
whoAmI: state.user,
|
|
@@ -26662,6 +27073,10 @@ var App = () => {
|
|
|
26662
27073
|
onRemoveAssignee: removeIssueAssignee,
|
|
26663
27074
|
onAddComment: addIssueComment,
|
|
26664
27075
|
onDeleteComment: deleteIssueComment,
|
|
27076
|
+
attachments: attachmentsByIssueId[selectedIssue.id] ?? [],
|
|
27077
|
+
attachmentUploadStatus,
|
|
27078
|
+
onUploadAttachments: uploadIssueAttachments,
|
|
27079
|
+
onDeleteAttachment: deleteIssueAttachment,
|
|
26665
27080
|
onReopenIssue: reopenIssue,
|
|
26666
27081
|
onCloseIssue: closeIssue,
|
|
26667
27082
|
knownTags: state.tags ?? [],
|
|
@@ -26671,7 +27086,7 @@ var App = () => {
|
|
|
26671
27086
|
]
|
|
26672
27087
|
}
|
|
26673
27088
|
),
|
|
26674
|
-
createIssueModal && /* @__PURE__ */ (0,
|
|
27089
|
+
createIssueModal && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
26675
27090
|
CreateIssueModal,
|
|
26676
27091
|
{
|
|
26677
27092
|
title: createIssueModal.title,
|
|
@@ -26686,14 +27101,14 @@ var App = () => {
|
|
|
26686
27101
|
};
|
|
26687
27102
|
|
|
26688
27103
|
// source/gui/client/main.tsx
|
|
26689
|
-
var
|
|
27104
|
+
var import_jsx_runtime20 = __toESM(require_jsx_runtime(), 1);
|
|
26690
27105
|
(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,
|
|
27106
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(BrowserRouter, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Routes, { children: [
|
|
27107
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(App, {}) }),
|
|
27108
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "/board/:boardId", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(App, {}) }),
|
|
27109
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "/board/:boardId/issue/:issueId", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(App, {}) }),
|
|
27110
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "/board/:boardId/:issueId", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(App, {}) }),
|
|
27111
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Navigate, { to: "/", replace: true }) })
|
|
26697
27112
|
] }) })
|
|
26698
27113
|
);
|
|
26699
27114
|
/*! Bundled license information:
|