@activecollab/components 2.0.366 → 2.0.367
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/cjs/presentation/listView/columns.js +135 -60
- package/dist/cjs/presentation/listView/columns.js.map +1 -1
- package/dist/esm/presentation/listView/columns.d.ts +14 -0
- package/dist/esm/presentation/listView/columns.d.ts.map +1 -1
- package/dist/esm/presentation/listView/columns.js +130 -59
- package/dist/esm/presentation/listView/columns.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
3
3
|
const _excluded = ["open", "className", "children"],
|
|
4
|
-
_excluded2 = ["
|
|
5
|
-
_excluded3 = ["
|
|
4
|
+
_excluded2 = ["value", "tooltip"],
|
|
5
|
+
_excluded3 = ["labels"],
|
|
6
|
+
_excluded4 = ["value", "tooltip", "overdue"];
|
|
6
7
|
import React, { createContext, forwardRef, useCallback, useContext, useMemo, useState } from "react";
|
|
7
8
|
import moment from "moment-timezone";
|
|
8
9
|
import styled, { css } from "styled-components";
|
|
@@ -24,10 +25,16 @@ import { Body2, Caption1, Caption2, Header3 } from "../../components/Typography"
|
|
|
24
25
|
import { formatHours } from "../../utils";
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
|
-
* Interactive list-view column cells for the `Presentation/List view`
|
|
28
|
-
* the Label, Date and Time cells
|
|
29
|
-
*
|
|
28
|
+
* Interactive list-view column cells for the `Presentation/List view` and
|
|
29
|
+
* `Presentation/List View ID Column` stories — the Label, Date and Time cells
|
|
30
|
+
* with their editors, mirroring
|
|
31
|
+
* `new-activecollab-front/src/components/ListView/columns/*`, plus an
|
|
32
|
+
* Identifier cell that only the ID-column story uses (it has no counterpart in
|
|
33
|
+
* the app yet):
|
|
30
34
|
*
|
|
35
|
+
* - **Identifier** (no app equivalent): `#<id>` as a Copy Link trigger, styled
|
|
36
|
+
* like the Date trigger. One typography at every length — the column's width
|
|
37
|
+
* is what adapts to how large the identifiers get.
|
|
31
38
|
* - **Label** (`columns/Label.js` + `LabelTrigger`/`LabelItems`): chips for 1–2
|
|
32
39
|
* labels, dots from 3 up, `+N` past 8, and a DS `Select` picker (search,
|
|
33
40
|
* colored dot + label name in the label's own colour, checkbox, "+ Add new").
|
|
@@ -88,6 +95,70 @@ const StyledListButton = styled(ListButtonBase).withConfig({
|
|
|
88
95
|
componentId: "sc-9f4385-0"
|
|
89
96
|
})(["&&{display:inline-flex;align-items:center;justify-content:flex-end;width:auto;min-width:0;max-width:100%;padding:4px 8px;overflow:visible;text-align:right;}", ""], CooltipStyle);
|
|
90
97
|
|
|
98
|
+
/* ================================================================== */
|
|
99
|
+
/* Identifier (task ID) */
|
|
100
|
+
/* ================================================================== */
|
|
101
|
+
|
|
102
|
+
const StyledIdValue = styled.span.withConfig({
|
|
103
|
+
displayName: "columns__StyledIdValue",
|
|
104
|
+
componentId: "sc-9f4385-1"
|
|
105
|
+
})(["font-family:", ";white-space:nowrap;font-variant-numeric:tabular-nums;"], SANS);
|
|
106
|
+
/**
|
|
107
|
+
* Same trigger the Date cell uses, so the id gets the identical hover outline
|
|
108
|
+
* and 8px inset — it is a link, not an editor, so it is always visible
|
|
109
|
+
* (`has-value`) rather than appearing on row hover.
|
|
110
|
+
*
|
|
111
|
+
* The typography is Caption 1 bold at every identifier length, like the Date
|
|
112
|
+
* value next to it; long identifiers are handled by the column's width tier,
|
|
113
|
+
* not by shrinking the text.
|
|
114
|
+
*/
|
|
115
|
+
const IdTrigger = /*#__PURE__*/forwardRef((_ref2, ref) => {
|
|
116
|
+
let value = _ref2.value,
|
|
117
|
+
tooltip = _ref2.tooltip,
|
|
118
|
+
rest = _objectWithoutPropertiesLoose(_ref2, _excluded2);
|
|
119
|
+
return /*#__PURE__*/React.createElement(StyledListButton, _extends({}, rest, {
|
|
120
|
+
ref: ref,
|
|
121
|
+
className: "show-on-hover has-value",
|
|
122
|
+
"aria-label": "Copy link to task " + value,
|
|
123
|
+
"data-tooltip": tooltip
|
|
124
|
+
}), /*#__PURE__*/React.createElement(StyledIdValue, null, /*#__PURE__*/React.createElement(Caption1, {
|
|
125
|
+
weight: "bold",
|
|
126
|
+
color: "secondary"
|
|
127
|
+
}, value)));
|
|
128
|
+
});
|
|
129
|
+
IdTrigger.displayName = "IdTrigger";
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Task identifier cell — the `#<id>` value as a copy-link control, mirroring
|
|
133
|
+
* how `tasks/Metadata.js` turns `Task #248` into the task's Copy Link action:
|
|
134
|
+
* the click writes the task URL to the clipboard and reports back so the page
|
|
135
|
+
* can raise the app's "Link copied to clipboard." toast (utils/copyLinkToClipboard).
|
|
136
|
+
* It never navigates — the row itself is the navigation target.
|
|
137
|
+
*/
|
|
138
|
+
export const IdentifierCell = _ref3 => {
|
|
139
|
+
let identifier = _ref3.identifier,
|
|
140
|
+
link = _ref3.link,
|
|
141
|
+
onCopy = _ref3.onCopy;
|
|
142
|
+
const handleClick = useCallback(event => {
|
|
143
|
+
var _navigator$clipboard;
|
|
144
|
+
/* the whole row navigates to the task, so copying must not also open it */
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
event.stopPropagation();
|
|
147
|
+
if ((_navigator$clipboard = navigator.clipboard) != null && _navigator$clipboard.writeText) {
|
|
148
|
+
navigator.clipboard.writeText(link).then(() => onCopy == null ? void 0 : onCopy(true)).catch(() => onCopy == null ? void 0 : onCopy(false));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
onCopy == null || onCopy(false);
|
|
152
|
+
}, [link, onCopy]);
|
|
153
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
154
|
+
className: "col col-identifier"
|
|
155
|
+
}, /*#__PURE__*/React.createElement(IdTrigger, {
|
|
156
|
+
value: "#" + identifier,
|
|
157
|
+
tooltip: "Copy Link",
|
|
158
|
+
onClick: handleClick
|
|
159
|
+
}));
|
|
160
|
+
};
|
|
161
|
+
|
|
91
162
|
/* ================================================================== */
|
|
92
163
|
/* Labels */
|
|
93
164
|
/* ================================================================== */
|
|
@@ -199,8 +270,8 @@ const LabelsContext = /*#__PURE__*/createContext({
|
|
|
199
270
|
* Holds the label catalogue for the whole list, so a label created in one
|
|
200
271
|
* task's picker shows up in every other picker too.
|
|
201
272
|
*/
|
|
202
|
-
export const LabelsProvider =
|
|
203
|
-
let children =
|
|
273
|
+
export const LabelsProvider = _ref4 => {
|
|
274
|
+
let children = _ref4.children;
|
|
204
275
|
const _useState = useState(INITIAL_LABELS),
|
|
205
276
|
labels = _useState[0],
|
|
206
277
|
setLabels = _useState[1];
|
|
@@ -235,15 +306,15 @@ const useTaskLabels = () => useContext(LabelsContext);
|
|
|
235
306
|
/* Empty state pill (mirrors EntityLabel + .entity-label in list-view.less) */
|
|
236
307
|
const StyledLabelPlaceholder = styled.span.withConfig({
|
|
237
308
|
displayName: "columns__StyledLabelPlaceholder",
|
|
238
|
-
componentId: "sc-9f4385-
|
|
309
|
+
componentId: "sc-9f4385-2"
|
|
239
310
|
})(["display:inline-flex;align-items:center;padding:1px 6px;border:1px solid var(--color-theme-700);border-radius:4px;.list-button.open &,.list-button:hover &{border-color:var(--color-primary-700,var(--color-primary));}"]);
|
|
240
311
|
const StyledLabelItems = styled.span.withConfig({
|
|
241
312
|
displayName: "columns__StyledLabelItems",
|
|
242
|
-
componentId: "sc-9f4385-
|
|
313
|
+
componentId: "sc-9f4385-3"
|
|
243
314
|
})(["display:inline-flex;align-items:center;min-width:0;> *:not(:last-child){margin-right:2px;}.rest-count{margin-left:2px;}", ""], CooltipStyle);
|
|
244
315
|
const MAX_SHOWN_LABELS = 8;
|
|
245
|
-
const LabelItems =
|
|
246
|
-
let labels =
|
|
316
|
+
const LabelItems = _ref5 => {
|
|
317
|
+
let labels = _ref5.labels;
|
|
247
318
|
const showAsDot = labels.length > 2;
|
|
248
319
|
let shown = labels;
|
|
249
320
|
let restCount = 0;
|
|
@@ -274,9 +345,9 @@ const LabelItems = _ref3 => {
|
|
|
274
345
|
className: "rest-count"
|
|
275
346
|
}, "+", restCount) : null);
|
|
276
347
|
};
|
|
277
|
-
const LabelTrigger = /*#__PURE__*/forwardRef((
|
|
278
|
-
let labels =
|
|
279
|
-
rest = _objectWithoutPropertiesLoose(
|
|
348
|
+
const LabelTrigger = /*#__PURE__*/forwardRef((_ref6, ref) => {
|
|
349
|
+
let labels = _ref6.labels,
|
|
350
|
+
rest = _objectWithoutPropertiesLoose(_ref6, _excluded3);
|
|
280
351
|
if (labels.length === 0) {
|
|
281
352
|
return /*#__PURE__*/React.createElement(StyledListButton, _extends({}, rest, {
|
|
282
353
|
ref: ref,
|
|
@@ -296,10 +367,10 @@ const LabelTrigger = /*#__PURE__*/forwardRef((_ref4, ref) => {
|
|
|
296
367
|
}));
|
|
297
368
|
});
|
|
298
369
|
LabelTrigger.displayName = "LabelTrigger";
|
|
299
|
-
export const LabelCell =
|
|
300
|
-
let labelIds =
|
|
301
|
-
|
|
302
|
-
completed =
|
|
370
|
+
export const LabelCell = _ref7 => {
|
|
371
|
+
let labelIds = _ref7.labelIds,
|
|
372
|
+
_ref7$completed = _ref7.completed,
|
|
373
|
+
completed = _ref7$completed === void 0 ? false : _ref7$completed;
|
|
303
374
|
const _useTaskLabels = useTaskLabels(),
|
|
304
375
|
catalog = _useTaskLabels.labels,
|
|
305
376
|
labelsById = _useTaskLabels.labelsById,
|
|
@@ -388,14 +459,14 @@ const formatDateLong = value => value ? moment.unix(value).utc().format(DATE_FOR
|
|
|
388
459
|
export const isOverdue = (dueOn, completed) => Boolean(dueOn && !completed && dueOn < todayUnix());
|
|
389
460
|
const StyledDateValue = styled.span.withConfig({
|
|
390
461
|
displayName: "columns__StyledDateValue",
|
|
391
|
-
componentId: "sc-9f4385-
|
|
462
|
+
componentId: "sc-9f4385-4"
|
|
392
463
|
})(["font-family:", ";white-space:nowrap;"], SANS);
|
|
393
464
|
|
|
394
465
|
/* completed rows render values without a trigger, so the cell itself hosts the
|
|
395
466
|
CSS tooltip */
|
|
396
467
|
const StyledReadOnlyCell = styled.div.withConfig({
|
|
397
468
|
displayName: "columns__StyledReadOnlyCell",
|
|
398
|
-
componentId: "sc-9f4385-
|
|
469
|
+
componentId: "sc-9f4385-5"
|
|
399
470
|
})(["padding-right:8px;", ""], CooltipStyle);
|
|
400
471
|
|
|
401
472
|
/**
|
|
@@ -407,13 +478,13 @@ const StyledReadOnlyCell = styled.div.withConfig({
|
|
|
407
478
|
*/
|
|
408
479
|
const StyledPickerCell = styled.div.withConfig({
|
|
409
480
|
displayName: "columns__StyledPickerCell",
|
|
410
|
-
componentId: "sc-9f4385-
|
|
481
|
+
componentId: "sc-9f4385-6"
|
|
411
482
|
})(["> div{text-align:right;}"]);
|
|
412
|
-
const DateTrigger = /*#__PURE__*/forwardRef((
|
|
413
|
-
let value =
|
|
414
|
-
tooltip =
|
|
415
|
-
overdue =
|
|
416
|
-
rest = _objectWithoutPropertiesLoose(
|
|
483
|
+
const DateTrigger = /*#__PURE__*/forwardRef((_ref8, ref) => {
|
|
484
|
+
let value = _ref8.value,
|
|
485
|
+
tooltip = _ref8.tooltip,
|
|
486
|
+
overdue = _ref8.overdue,
|
|
487
|
+
rest = _objectWithoutPropertiesLoose(_ref8, _excluded4);
|
|
417
488
|
return /*#__PURE__*/React.createElement(StyledListButton, _extends({}, rest, {
|
|
418
489
|
ref: ref,
|
|
419
490
|
className: value ? "show-on-hover has-value" : "show-on-hover",
|
|
@@ -425,12 +496,12 @@ const DateTrigger = /*#__PURE__*/forwardRef((_ref6, ref) => {
|
|
|
425
496
|
}, value)) : /*#__PURE__*/React.createElement(CalendarIcon, null));
|
|
426
497
|
});
|
|
427
498
|
DateTrigger.displayName = "DateTrigger";
|
|
428
|
-
export const DateCell =
|
|
499
|
+
export const DateCell = _ref9 => {
|
|
429
500
|
var _dates$from, _dates$to2;
|
|
430
|
-
let startOn =
|
|
431
|
-
dueOn =
|
|
432
|
-
|
|
433
|
-
completed =
|
|
501
|
+
let startOn = _ref9.startOn,
|
|
502
|
+
dueOn = _ref9.dueOn,
|
|
503
|
+
_ref9$completed = _ref9.completed,
|
|
504
|
+
completed = _ref9$completed === void 0 ? false : _ref9$completed;
|
|
434
505
|
const _useState3 = useState({
|
|
435
506
|
from: startOn,
|
|
436
507
|
to: dueOn
|
|
@@ -553,11 +624,11 @@ const progressColor = percent => {
|
|
|
553
624
|
};
|
|
554
625
|
const StyledTimeValue = styled.span.withConfig({
|
|
555
626
|
displayName: "columns__StyledTimeValue",
|
|
556
|
-
componentId: "sc-9f4385-
|
|
627
|
+
componentId: "sc-9f4385-7"
|
|
557
628
|
})(["display:inline-flex;align-items:center;font-family:", ";white-space:nowrap;.c-progress-pie,svg{flex-shrink:0;}.time-pie{margin-right:8px;}"], SANS);
|
|
558
|
-
const TimeValue =
|
|
559
|
-
let tracked =
|
|
560
|
-
estimated =
|
|
629
|
+
const TimeValue = _ref0 => {
|
|
630
|
+
let tracked = _ref0.tracked,
|
|
631
|
+
estimated = _ref0.estimated;
|
|
561
632
|
const percent = timeToEstimatePercentage(tracked, estimated);
|
|
562
633
|
return /*#__PURE__*/React.createElement(StyledTimeValue, null, estimated > 0 ? /*#__PURE__*/React.createElement(ProgressPie, {
|
|
563
634
|
className: "time-pie",
|
|
@@ -569,10 +640,10 @@ const TimeValue = _ref8 => {
|
|
|
569
640
|
weight: "bold"
|
|
570
641
|
}, formatTrackedAndEstimated(tracked, estimated)));
|
|
571
642
|
};
|
|
572
|
-
const TimeTrigger =
|
|
573
|
-
let tracked =
|
|
574
|
-
estimated =
|
|
575
|
-
onClick =
|
|
643
|
+
const TimeTrigger = _ref1 => {
|
|
644
|
+
let tracked = _ref1.tracked,
|
|
645
|
+
estimated = _ref1.estimated,
|
|
646
|
+
onClick = _ref1.onClick;
|
|
576
647
|
const hasTime = tracked > 0 || estimated > 0;
|
|
577
648
|
return /*#__PURE__*/React.createElement(StyledListButton, {
|
|
578
649
|
onClick: onClick,
|
|
@@ -584,16 +655,16 @@ const TimeTrigger = _ref9 => {
|
|
|
584
655
|
estimated: estimated
|
|
585
656
|
}) : /*#__PURE__*/React.createElement(ClockAddIcon, null));
|
|
586
657
|
};
|
|
587
|
-
export const TimeCell =
|
|
588
|
-
let taskName =
|
|
589
|
-
|
|
590
|
-
tracked =
|
|
591
|
-
|
|
592
|
-
estimated =
|
|
593
|
-
users =
|
|
594
|
-
currentUserId =
|
|
595
|
-
|
|
596
|
-
completed =
|
|
658
|
+
export const TimeCell = _ref10 => {
|
|
659
|
+
let taskName = _ref10.taskName,
|
|
660
|
+
_ref10$tracked = _ref10.tracked,
|
|
661
|
+
tracked = _ref10$tracked === void 0 ? 0 : _ref10$tracked,
|
|
662
|
+
_ref10$estimated = _ref10.estimated,
|
|
663
|
+
estimated = _ref10$estimated === void 0 ? 0 : _ref10$estimated,
|
|
664
|
+
users = _ref10.users,
|
|
665
|
+
currentUserId = _ref10.currentUserId,
|
|
666
|
+
_ref10$completed = _ref10.completed,
|
|
667
|
+
completed = _ref10$completed === void 0 ? false : _ref10$completed;
|
|
597
668
|
const _useState5 = useState(false),
|
|
598
669
|
open = _useState5[0],
|
|
599
670
|
setOpen = _useState5[1];
|
|
@@ -672,17 +743,17 @@ const JOB_TYPES = [{
|
|
|
672
743
|
`Dialog` because it is 770px wide (`.time_record_form_modal_wrapper`). */
|
|
673
744
|
const StyledTimeRecordPaper = styled.div.withConfig({
|
|
674
745
|
displayName: "columns__StyledTimeRecordPaper",
|
|
675
|
-
componentId: "sc-9f4385-
|
|
746
|
+
componentId: "sc-9f4385-8"
|
|
676
747
|
})(["position:relative;width:770px;max-width:95vw;max-height:calc(100vh - 156px);margin:126px auto 30px auto;padding:20px 30px;overflow:auto;border-radius:8px;background-color:var(--page-paper-main);color:var(--color-theme-900);box-shadow:var(--shadow-primary);box-sizing:border-box;font-family:", ";*{box-sizing:border-box;}@media (max-width:830px){width:calc(100vw - 60px);}.trd-header{display:flex;align-items:center;justify-content:space-between;}.trd-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:16px;font-size:1rem;font-weight:700;}.trd-date button{width:auto;}.trd-date > div{text-align:right;}.trd-divider{margin:20px 0 32px 0;border-bottom:1px solid var(--border-primary);height:1px;}.trd-body{display:flex;justify-content:space-between;position:relative;}.trd-form{width:100%;}.trd-fields{display:flex;align-items:flex-end;}.trd-hours{width:144px;margin-right:16px;flex-shrink:0;}.trd-hours .c-input-wrapper,.trd-hours input{width:100%;}.trd-field{margin-right:16px;}.trd-field:last-of-type{margin-right:20px;}.trd-field .c-label{display:block;margin-bottom:2px;}.trd-field button{width:144px;}.trd-billable{display:flex;align-items:center;margin-top:24px;}.trd-billable .c-label{margin-left:8px;cursor:pointer;}.trd-description-trigger{display:inline-flex;align-items:center;margin-top:16px;color:var(--color-secondary);font-size:14px;font-weight:500;background:none;border:none;padding:0;cursor:pointer;font-family:", ";}.trd-description-trigger svg{margin-right:4px;fill:var(--color-primary);transition:transform 200ms ease;}.trd-description-trigger.collapsed svg{transform:rotate(180deg);}.trd-textarea{width:360px;max-width:100%;margin-top:8px;font-size:12px;resize:none;}.trd-actions{display:flex;margin-top:24px;}.trd-actions .c-button:first-child{margin-right:12px;}.trd-total{position:absolute;right:0;bottom:0;display:inline-flex;align-items:center;align-self:flex-end;background:none;border:none;padding:0;cursor:pointer;}.trd-total svg{margin-right:4px;fill:var(--color-primary);transition:transform 200ms ease;}.trd-total.collapsed svg{transform:rotate(180deg);}.trd-records{margin-top:32px;border-top:1px solid var(--border-primary);}.trd-record{display:flex;align-items:center;justify-content:space-between;height:36px;border-bottom:1px solid var(--color-theme-300);}.trd-record-left{display:flex;align-items:center;gap:12px;min-width:0;}"], SANS, SANS);
|
|
677
|
-
const TimeRecordDialog =
|
|
678
|
-
let open =
|
|
679
|
-
taskName =
|
|
680
|
-
users =
|
|
681
|
-
currentUserId =
|
|
682
|
-
records =
|
|
683
|
-
total =
|
|
684
|
-
onSubmit =
|
|
685
|
-
onClose =
|
|
748
|
+
const TimeRecordDialog = _ref11 => {
|
|
749
|
+
let open = _ref11.open,
|
|
750
|
+
taskName = _ref11.taskName,
|
|
751
|
+
users = _ref11.users,
|
|
752
|
+
currentUserId = _ref11.currentUserId,
|
|
753
|
+
records = _ref11.records,
|
|
754
|
+
total = _ref11.total,
|
|
755
|
+
onSubmit = _ref11.onSubmit,
|
|
756
|
+
onClose = _ref11.onClose;
|
|
686
757
|
const _useState7 = useState(""),
|
|
687
758
|
value = _useState7[0],
|
|
688
759
|
setValue = _useState7[1];
|