sprintify-ui 0.6.8 → 0.6.10
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/sprintify-ui.es.js +2651 -2594
- package/dist/types/src/components/BaseGantt.vue.d.ts +9 -0
- package/dist/types/src/services/gantt/format.d.ts +2 -1
- package/dist/types/src/services/gantt/timescale.d.ts +2 -1
- package/dist/types/src/services/gantt/types.d.ts +4 -0
- package/package.json +1 -1
- package/src/components/BaseGantt.stories.js +9 -4
- package/src/components/BaseGantt.vue +55 -7
- package/src/components/BaseLayoutStackedConfigurable.stories.js +3 -0
- package/src/components/BaseNavbarItem.vue +5 -0
- package/src/services/gantt/format.ts +24 -4
- package/src/services/gantt/timescale.ts +1 -0
- package/src/services/gantt/types.ts +6 -1
|
@@ -16,6 +16,10 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
16
16
|
type: import("vue").PropType<number>;
|
|
17
17
|
default: number;
|
|
18
18
|
};
|
|
19
|
+
includeToday: {
|
|
20
|
+
type: import("vue").PropType<boolean>;
|
|
21
|
+
default: boolean;
|
|
22
|
+
};
|
|
19
23
|
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
20
24
|
"item:click": (...args: any[]) => void;
|
|
21
25
|
"row:click": (...args: any[]) => void;
|
|
@@ -36,6 +40,10 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
36
40
|
type: import("vue").PropType<number>;
|
|
37
41
|
default: number;
|
|
38
42
|
};
|
|
43
|
+
includeToday: {
|
|
44
|
+
type: import("vue").PropType<boolean>;
|
|
45
|
+
default: boolean;
|
|
46
|
+
};
|
|
39
47
|
}>> & {
|
|
40
48
|
"onItem:click"?: ((...args: any[]) => any) | undefined;
|
|
41
49
|
"onRow:click"?: ((...args: any[]) => any) | undefined;
|
|
@@ -43,6 +51,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
43
51
|
maxHeight: number;
|
|
44
52
|
rowHeight: number;
|
|
45
53
|
rowPadding: number;
|
|
54
|
+
includeToday: boolean;
|
|
46
55
|
}, {}>, {
|
|
47
56
|
sidebarItem?(_: {
|
|
48
57
|
row: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DateTime } from "luxon";
|
|
2
|
-
import { FormatConfig, GanttItem, GanttItemFormatted, GanttRow, GanttRowFormatted } from "./types";
|
|
2
|
+
import { FormatConfig, GanttItem, GanttItemFormatted, GanttRow, GanttRowFormatted, NowLine } from "./types";
|
|
3
3
|
export declare class Format {
|
|
4
4
|
private rows;
|
|
5
5
|
private config;
|
|
@@ -13,6 +13,7 @@ export declare class Format {
|
|
|
13
13
|
width: number;
|
|
14
14
|
groups: import("./types").Group[];
|
|
15
15
|
ticks: import("./types").Tick[];
|
|
16
|
+
nowLine: NowLine | null;
|
|
16
17
|
};
|
|
17
18
|
formatGanttRows(): GanttRowFormatted[];
|
|
18
19
|
formatGanttRow(row: GanttRow): GanttRowFormatted;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DateTime } from "luxon";
|
|
2
|
-
import { Group, Tick } from "./types";
|
|
2
|
+
import { Group, Scale, Tick } from "./types";
|
|
3
3
|
export declare class Timescale {
|
|
4
4
|
private minWidth;
|
|
5
5
|
private width;
|
|
@@ -9,6 +9,7 @@ export declare class Timescale {
|
|
|
9
9
|
private millisecondToPixel;
|
|
10
10
|
constructor(minWidth: number, min: DateTime, max: DateTime);
|
|
11
11
|
handle(): {
|
|
12
|
+
scale: Scale;
|
|
12
13
|
groups: Group[];
|
|
13
14
|
ticks: Tick[];
|
|
14
15
|
width: number;
|
|
@@ -37,6 +37,7 @@ export interface FormatConfig {
|
|
|
37
37
|
minWidth: number;
|
|
38
38
|
rowHeight: number;
|
|
39
39
|
rowPadding: number;
|
|
40
|
+
includeToday: boolean;
|
|
40
41
|
}
|
|
41
42
|
export interface Tick {
|
|
42
43
|
date: DateTime;
|
|
@@ -65,3 +66,6 @@ export interface Scale {
|
|
|
65
66
|
format: string;
|
|
66
67
|
};
|
|
67
68
|
}
|
|
69
|
+
export interface NowLine {
|
|
70
|
+
x: number;
|
|
71
|
+
}
|
package/package.json
CHANGED
|
@@ -7,14 +7,14 @@ import { random } from 'lodash';
|
|
|
7
7
|
|
|
8
8
|
const rows = [];
|
|
9
9
|
|
|
10
|
-
for (let i = 0; i <
|
|
10
|
+
for (let i = 0; i < 10; i++) {
|
|
11
11
|
|
|
12
12
|
const items = [];
|
|
13
13
|
|
|
14
14
|
for (let j = 0; j < 1; j++) {
|
|
15
15
|
|
|
16
|
-
const start = DateTime.now().plus({ days: i *
|
|
17
|
-
const end = start.plus({ days:
|
|
16
|
+
const start = DateTime.now().minus({ days: 50 }).plus({ days: i * 2 });
|
|
17
|
+
const end = start.plus({ days: 50 });
|
|
18
18
|
|
|
19
19
|
const colors = ['blue', 'green', 'red', 'yellow', 'indigo', 'pink', 'purple', 'gray'];
|
|
20
20
|
|
|
@@ -114,7 +114,12 @@ const SlotSidebarItemTemplate = (args) => ({
|
|
|
114
114
|
Icon,
|
|
115
115
|
},
|
|
116
116
|
setup() {
|
|
117
|
-
|
|
117
|
+
|
|
118
|
+
function onItemClick(item) {
|
|
119
|
+
alert(`Item "${item.name}" clicked`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return { args, onItemClick };
|
|
118
123
|
},
|
|
119
124
|
template: `
|
|
120
125
|
<BaseCard clipped>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
<div
|
|
56
56
|
ref="contentRef"
|
|
57
|
-
class="grow flex flex-col relative overflow-hidden"
|
|
57
|
+
class="grow flex flex-col items-stretch relative overflow-hidden"
|
|
58
58
|
>
|
|
59
59
|
<!-- Time Scale Header -->
|
|
60
60
|
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
|
|
139
139
|
<ul
|
|
140
140
|
ref="itemsRef"
|
|
141
|
-
class="relative overflow-scroll grow"
|
|
141
|
+
class="relative w-full overflow-scroll grow"
|
|
142
142
|
>
|
|
143
143
|
<li
|
|
144
144
|
v-for="row in rowsInternal"
|
|
@@ -228,6 +228,35 @@
|
|
|
228
228
|
</g>
|
|
229
229
|
</svg>
|
|
230
230
|
</div>
|
|
231
|
+
|
|
232
|
+
<!-- Now line -->
|
|
233
|
+
|
|
234
|
+
<div
|
|
235
|
+
v-if="nowLine"
|
|
236
|
+
class="absolute left-0 pointer-events-none"
|
|
237
|
+
:style="{
|
|
238
|
+
top: `${HEADER_HEIGHT}px`,
|
|
239
|
+
width: `${width}px`,
|
|
240
|
+
height: height + 'px',
|
|
241
|
+
transform: `translateX(${scrollX}px)`,
|
|
242
|
+
}"
|
|
243
|
+
>
|
|
244
|
+
<svg
|
|
245
|
+
:view-box="`${width} ${height}`"
|
|
246
|
+
:width="width"
|
|
247
|
+
:height="height"
|
|
248
|
+
>
|
|
249
|
+
<line
|
|
250
|
+
:x1="nowLine.x"
|
|
251
|
+
:x2="nowLine.x"
|
|
252
|
+
y1="0"
|
|
253
|
+
:y2="height"
|
|
254
|
+
stroke="red"
|
|
255
|
+
stroke-width="2"
|
|
256
|
+
style="filter: drop-shadow(0px 0px 2px rgb(0 0 0 / 0.1));"
|
|
257
|
+
></line>
|
|
258
|
+
</svg>
|
|
259
|
+
</div>
|
|
231
260
|
</div>
|
|
232
261
|
</div>
|
|
233
262
|
</template>
|
|
@@ -235,7 +264,7 @@
|
|
|
235
264
|
<script lang="ts" setup>
|
|
236
265
|
import { useElementSize, useScroll } from '@vueuse/core';
|
|
237
266
|
import { Format } from '@/services/gantt/format';
|
|
238
|
-
import { FormatConfig, GanttRow, GanttRowFormatted, Group, Tick } from '@/services/gantt/types';
|
|
267
|
+
import { FormatConfig, GanttRow, GanttRowFormatted, Group, Tick, NowLine } from '@/services/gantt/types';
|
|
239
268
|
import { debounce } from 'lodash';
|
|
240
269
|
import { slate } from 'tailwindcss/colors';
|
|
241
270
|
|
|
@@ -244,10 +273,12 @@ const props = withDefaults(defineProps<{
|
|
|
244
273
|
rowHeight?: number,
|
|
245
274
|
rowPadding?: number,
|
|
246
275
|
maxHeight?: number,
|
|
276
|
+
includeToday?: boolean,
|
|
247
277
|
}>(), {
|
|
248
278
|
rowHeight: 40,
|
|
249
279
|
rowPadding: 4,
|
|
250
280
|
maxHeight: undefined,
|
|
281
|
+
includeToday: true,
|
|
251
282
|
});
|
|
252
283
|
|
|
253
284
|
defineEmits([
|
|
@@ -264,6 +295,7 @@ const HEADER_HEIGHT = 40;
|
|
|
264
295
|
|
|
265
296
|
const contentRef = ref<HTMLDivElement | null>(null);
|
|
266
297
|
const contentSize = useElementSize(contentRef);
|
|
298
|
+
const itemsRef = ref<HTMLUListElement | null>(null);
|
|
267
299
|
|
|
268
300
|
const width = ref(800);
|
|
269
301
|
const height = ref(100);
|
|
@@ -271,6 +303,7 @@ const height = ref(100);
|
|
|
271
303
|
const rowsInternal = ref<GanttRowFormatted[]>([]);
|
|
272
304
|
const groups = ref<Group[]>([]);
|
|
273
305
|
const ticks = ref<Tick[]>([]);
|
|
306
|
+
const nowLine = ref<NowLine | null>(null);
|
|
274
307
|
|
|
275
308
|
const config = computed<FormatConfig>(() => {
|
|
276
309
|
return {
|
|
@@ -278,11 +311,11 @@ const config = computed<FormatConfig>(() => {
|
|
|
278
311
|
minWidth: contentSize.width.value,
|
|
279
312
|
rowHeight: props.rowHeight,
|
|
280
313
|
rowPadding: props.rowPadding,
|
|
314
|
+
includeToday: props.includeToday,
|
|
281
315
|
};
|
|
282
316
|
});
|
|
283
317
|
|
|
284
318
|
function init() {
|
|
285
|
-
|
|
286
319
|
const format = (new Format(config.value)).handle();
|
|
287
320
|
|
|
288
321
|
width.value = format.width;
|
|
@@ -292,18 +325,33 @@ function init() {
|
|
|
292
325
|
|
|
293
326
|
groups.value = format.groups;
|
|
294
327
|
ticks.value = format.ticks;
|
|
328
|
+
|
|
329
|
+
nowLine.value = format.nowLine;
|
|
330
|
+
|
|
331
|
+
// Scroll to now line
|
|
332
|
+
|
|
333
|
+
nextTick(() => {
|
|
334
|
+
if (nowLine.value && itemsRef.value) {
|
|
335
|
+
const scrollLeft = nowLine.value.x + contentSize.width.value / 2;
|
|
336
|
+
itemsRef.value.scrollLeft = scrollLeft;
|
|
337
|
+
}
|
|
338
|
+
});
|
|
295
339
|
}
|
|
296
340
|
|
|
297
341
|
// Init triggers
|
|
298
342
|
|
|
299
343
|
const initDebounced = debounce(init, 200);
|
|
300
344
|
|
|
301
|
-
|
|
345
|
+
onMounted(() => {
|
|
346
|
+
// Wait for the contentSize to be available
|
|
347
|
+
setTimeout(() => {
|
|
348
|
+
init();
|
|
349
|
+
watch(() => config.value, initDebounced, { deep: true });
|
|
350
|
+
}, 1);
|
|
351
|
+
});
|
|
302
352
|
|
|
303
353
|
// Scroll
|
|
304
354
|
|
|
305
|
-
const itemsRef = ref<HTMLUListElement | null>(null);
|
|
306
|
-
|
|
307
355
|
const scrollX = ref(0);
|
|
308
356
|
const scrollY = ref(0);
|
|
309
357
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { DateTime } from "luxon";
|
|
2
|
-
import { FormatConfig, GanttItem, GanttItemFormatted, GanttRow, GanttRowFormatted } from "./types";
|
|
3
|
-
import { minBy } from "lodash";
|
|
2
|
+
import { FormatConfig, GanttItem, GanttItemFormatted, GanttRow, GanttRowFormatted, NowLine } from "./types";
|
|
4
3
|
import { Timescale } from "./timescale";
|
|
5
4
|
|
|
6
5
|
export class Format {
|
|
@@ -47,6 +46,16 @@ export class Format {
|
|
|
47
46
|
});
|
|
48
47
|
});
|
|
49
48
|
|
|
49
|
+
const today = DateTime.local().startOf(timescale.scale.tick.step);
|
|
50
|
+
|
|
51
|
+
let nowLine = null;
|
|
52
|
+
|
|
53
|
+
if (today >= min && today <= max) {
|
|
54
|
+
nowLine = {
|
|
55
|
+
x: (today.toMillis() - min.toMillis()) * millisecondToPixel,
|
|
56
|
+
} as NowLine;
|
|
57
|
+
}
|
|
58
|
+
|
|
50
59
|
return {
|
|
51
60
|
rows: rowsFormatted,
|
|
52
61
|
min,
|
|
@@ -56,6 +65,7 @@ export class Format {
|
|
|
56
65
|
width: timescale.width,
|
|
57
66
|
groups: timescale.groups,
|
|
58
67
|
ticks: timescale.ticks,
|
|
68
|
+
nowLine: nowLine,
|
|
59
69
|
};
|
|
60
70
|
}
|
|
61
71
|
|
|
@@ -102,8 +112,18 @@ export class Format {
|
|
|
102
112
|
const flatItems = rowsFormatted.flatMap((row) => row.items);
|
|
103
113
|
const flatDateTimes = flatItems.flatMap((item) => [item.start, item.end]);
|
|
104
114
|
|
|
105
|
-
|
|
106
|
-
const
|
|
115
|
+
|
|
116
|
+
const flatMillis = flatDateTimes.map((dateTime) => dateTime.toMillis());
|
|
117
|
+
|
|
118
|
+
if (this.config.includeToday) {
|
|
119
|
+
const today = DateTime.local().startOf("day");
|
|
120
|
+
|
|
121
|
+
flatMillis.push(today.plus({ days: 1 }).toMillis());
|
|
122
|
+
flatMillis.push(today.minus({ days: 1 }).toMillis());
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const min = Math.min(...flatMillis);
|
|
126
|
+
const max = Math.max(...flatMillis);
|
|
107
127
|
|
|
108
128
|
const minDateTime = DateTime.fromMillis(min);
|
|
109
129
|
const maxDateTime = DateTime.fromMillis(max);
|
|
@@ -42,6 +42,7 @@ export interface FormatConfig {
|
|
|
42
42
|
minWidth: number;
|
|
43
43
|
rowHeight: number;
|
|
44
44
|
rowPadding: number;
|
|
45
|
+
includeToday: boolean;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export interface Tick {
|
|
@@ -72,4 +73,8 @@ export interface Scale {
|
|
|
72
73
|
step: DateTimeUnit;
|
|
73
74
|
format: string;
|
|
74
75
|
};
|
|
75
|
-
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface NowLine {
|
|
79
|
+
x: number;
|
|
80
|
+
}
|