- Layout converted to set `min-height` on top-most `c-swimlane` element.
Interior containers now use 100% height or absolute positioning.
- Removed `c-timeline-holder` from `c-events-tsv` in EventTimelineView.vue;
Refactored `c-events-tsv__contents` to be `js-events-tsv` as that was being used as a reference.
- New theme constant `eventLineW` sets event lines to be 1px wide for more precision.
This commit is contained in:
Charles Hacskaylo 2024-12-16 16:14:38 -08:00
parent 20426fe359
commit 6bda108e95
9 changed files with 43 additions and 32 deletions

View File

@ -21,11 +21,7 @@
--> -->
<template> <template>
<div <div ref="events" class="c-events-tsv js-events-tsv" :style="{ left: leftOffset + 'px' }" />
ref="events"
class="c-events-tsv c-timeline-holder c-events-tsv__contents"
:style="{ left: leftOffset + 'px' }"
/>
</template> </template>
<script> <script>
@ -40,11 +36,10 @@ import { useAlignment } from '../../../ui/composables/alignmentContext.js';
import eventData from '../mixins/eventData.js'; import eventData from '../mixins/eventData.js';
const PADDING = 1; const PADDING = 1;
const ROW_HEIGHT = 100; const CONTAINER_CLASS = 'c-events-tsv__container';
const CONTAINER_CLASS = 'c-events-tsv-container';
const NO_ITEMS_CLASS = 'c-events-tsv__no-items'; const NO_ITEMS_CLASS = 'c-events-tsv__no-items';
const EVENT_WRAPPER_CLASS = 'c-events-tsv__event-wrapper'; const EVENT_WRAPPER_CLASS = 'c-events-tsv__event-wrapper';
const EVENT_SELECTED_CLASS = '.c-event-selected'; const EVENT_SELECTED_CLASS = 'is-selected';
const ID_PREFIX = 'wrapper-'; const ID_PREFIX = 'wrapper-';
const AXES_PADDING = 20; const AXES_PADDING = 20;
@ -295,7 +290,7 @@ export default {
let existingContainer = this.$el.querySelector(`.${CONTAINER_CLASS}`); let existingContainer = this.$el.querySelector(`.${CONTAINER_CLASS}`);
if (existingContainer) { if (existingContainer) {
eventContainer = existingContainer; eventContainer = existingContainer;
eventContainer.style.maxWidth = `${containerWidth}px`; // eventContainer.style.maxWidth = `${containerWidth}px`;
} else { } else {
if (this.destroyEventsContainer) { if (this.destroyEventsContainer) {
this.destroyEventsContainer(); this.destroyEventsContainer();
@ -315,7 +310,7 @@ export default {
}, },
template: `<swim-lane :is-nested="isNested" :hide-label="true"> template: `<swim-lane :is-nested="isNested" :hide-label="true">
<template v-slot:object> <template v-slot:object>
<div class="c-events-tsv-container"/> <div class="c-events-tsv__container"/>
</template> </template>
</swim-lane>` </swim-lane>`
}, },
@ -329,8 +324,8 @@ export default {
this.$refs.events.appendChild(component.$el); this.$refs.events.appendChild(component.$el);
eventContainer = component.$el.querySelector(`.${CONTAINER_CLASS}`); eventContainer = component.$el.querySelector(`.${CONTAINER_CLASS}`);
eventContainer.style.maxWidth = `${containerWidth}px`; // eventContainer.style.maxWidth = `${containerWidth}px`;
eventContainer.style.height = `${containerHeight}px`; // eventContainer.style.height = `${containerHeight}px`;
} }
return eventContainer; return eventContainer;
@ -348,7 +343,7 @@ export default {
} }
}, },
plotNoItems(containerElement) { plotNoItems(containerElement) {
const textElement = document.createElement('text'); const textElement = document.createElement('div');
textElement.classList.add(NO_ITEMS_CLASS); textElement.classList.add(NO_ITEMS_CLASS);
textElement.innerHTML = 'No events within timeframe'; textElement.innerHTML = 'No events within timeframe';
@ -357,7 +352,7 @@ export default {
getEventWrapper(item) { getEventWrapper(item) {
const id = `${ID_PREFIX}${item.time}`; const id = `${ID_PREFIX}${item.time}`;
return this.$el.querySelector(`.c-events-tsv__contents div[id=${id}]`); return this.$el.querySelector(`.js-events-tsv div[id=${id}]`);
}, },
plotEvents(item, containerElement) { plotEvents(item, containerElement) {
const existingEventWrapper = this.getEventWrapper(item); const existingEventWrapper = this.getEventWrapper(item);
@ -433,8 +428,6 @@ export default {
eventWrapper.style.left = `${this.xScale(event.time)}px`; eventWrapper.style.left = `${this.xScale(event.time)}px`;
const eventTickElement = document.createElement('div'); const eventTickElement = document.createElement('div');
eventTickElement.classList.add('c-events-tsv__event-handle'); eventTickElement.classList.add('c-events-tsv__event-handle');
eventTickElement.style.width = '2px';
eventTickElement.style.height = `${String(ROW_HEIGHT - 10)}px`;
if (this.titleKey) { if (this.titleKey) {
const textToShow = event[this.titleKey]; const textToShow = event[this.titleKey];
eventWrapper.addEventListener('mouseover', () => { eventWrapper.addEventListener('mouseover', () => {
@ -492,6 +485,7 @@ export default {
} }
}, },
toggleEventSelection(clickedEvent) { toggleEventSelection(clickedEvent) {
console.log(clickedEvent);
this.selectedEvent?.classList.remove(EVENT_SELECTED_CLASS); this.selectedEvent?.classList.remove(EVENT_SELECTED_CLASS);
clickedEvent.classList.add(EVENT_SELECTED_CLASS); clickedEvent.classList.add(EVENT_SELECTED_CLASS);
this.selectedEvent = clickedEvent; this.selectedEvent = clickedEvent;

View File

@ -1,13 +1,23 @@
.c-events-tsv { .c-events-tsv {
$m: $interiorMargin;
overflow: hidden; overflow: hidden;
@include abs();
&__container {
// Holds event lines
background: $colorPlotBg;
box-shadow: inset $colorPlotAreaBorder 0 0 0 1px; // Using box-shadow instead of border to not affect box size
position: absolute;
top: $m; right: 0; bottom: $m; left: 0;
}
&__event-wrapper { &__event-wrapper {
// Wraps an individual event line // Wraps an individual event line
// Also holds the hover flyout element // Also holds the hover flyout element
$c: $colorEventLine; $c: $colorEventLine;
$lineW: 2px; $lineW: $eventLineW;
$hitAreaW: 6px; $hitAreaW: 7px;
$m: $interiorMargin; $m: $interiorMarginSm;
background-color: rgba($c, 0.6); background-color: rgba($c, 0.6);
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
@ -38,7 +48,10 @@
} }
&__no-items { &__no-items {
fill: $colorBodyFg !important; position: absolute;
left: $interiorMargin;
top: 50%;
transform: translateY(-50%);
} }
} }

View File

@ -38,22 +38,25 @@
.c-timeline { .c-timeline {
&__objects { &__objects {
display: contents; display: contents;
.c-swimlane {
min-height: 100px; // TEMP!! Will be replaced when heights are set by user
}
} }
&__overlay-lines { &__overlay-lines {
//background: rgba(deeppink, 0.2); //background: rgba(deeppink, 0.2);
@include abs(); @include abs();
pointer-events: none; /* Allows clicks to pass through */ pointer-events: none; // Allows clicks to pass through
z-index: 10; /* Ensure it sits atop swimlanes */ z-index: 10; // Ensure it sits atop swimlanes
} }
&__extended-line { &__extended-line {
opacity: 0.3;
position: absolute; position: absolute;
top: 20px; // Offset down to line up with time axis ticks line top: 20px; // Offset down to line up with time axis ticks line
width: 2px; width: $eventLineW;
pointer-events: auto; pointer-events: auto; // TODO: don't think we want this, extended lines shouldn't be accepting pointer events
background-color: $colorEventLine; //$colorBodyFg; /* Use desired color */ background-color: $colorEventLineExtended;
} }
&__extended-line-hovered { &__extended-line-hovered {

View File

@ -519,6 +519,7 @@ $colorInProgressFgEm: $colorTimeRealtimeFg;
$colorGanttSelectedBorder: rgba(#fff, 0.3); $colorGanttSelectedBorder: rgba(#fff, 0.3);
$colorEventLine: $colorBodyFg; $colorEventLine: $colorBodyFg;
$colorEventLineExtended: rgba($colorEventLine, 0.3); $colorEventLineExtended: rgba($colorEventLine, 0.3);
$eventLineW: 1px;
// Tree // Tree
$colorTreeBg: transparent; $colorTreeBg: transparent;

View File

@ -484,6 +484,7 @@ $colorInProgressFgEm: $colorTimeRealtimeFg;
$colorGanttSelectedBorder: rgba(#fff, 0.3); $colorGanttSelectedBorder: rgba(#fff, 0.3);
$colorEventLine: $colorBodyFg; $colorEventLine: $colorBodyFg;
$colorEventLineExtended: rgba($colorEventLine, 0.3); $colorEventLineExtended: rgba($colorEventLine, 0.3);
$eventLineW: 1px;
// Tree // Tree
$colorTreeBg: transparent; $colorTreeBg: transparent;

View File

@ -500,6 +500,7 @@ $colorInProgressFgEm: $colorTimeRealtimeFg;
$colorGanttSelectedBorder: rgba(#fff, 0.3); $colorGanttSelectedBorder: rgba(#fff, 0.3);
$colorEventLine: $colorBodyFg; $colorEventLine: $colorBodyFg;
$colorEventLineExtended: rgba($colorEventLine, 0.3); $colorEventLineExtended: rgba($colorEventLine, 0.3);
$eventLineW: 1px;
// Tree // Tree
$colorTreeBg: transparent; $colorTreeBg: transparent;

View File

@ -483,6 +483,7 @@ $colorInProgressFgEm: $colorCurrentFgEm;
$colorGanttSelectedBorder: #fff; $colorGanttSelectedBorder: #fff;
$colorEventLine: $colorBodyFg; $colorEventLine: $colorBodyFg;
$colorEventLineExtended: rgba($colorEventLine, 0.3); $colorEventLineExtended: rgba($colorEventLine, 0.3);
$eventLineW: 1px;
// Tree // Tree
$colorTreeBg: transparent; $colorTreeBg: transparent;

View File

@ -55,11 +55,7 @@
/> />
</div> </div>
</div> </div>
<div <div class="c-swimlane__lane-object" :class="{ 'u-contents': showUcontents }">
class="c-swimlane__lane-object"
:style="{ 'min-height': minHeight }"
:class="{ 'u-contents': showUcontents }"
>
<slot name="object"></slot> <slot name="object"></slot>
</div> </div>
</div> </div>

View File

@ -24,7 +24,7 @@
display: grid; display: grid;
grid-template-columns: 100px 100px 1fr; grid-template-columns: 100px 100px 1fr;
grid-column-gap: 1px; grid-column-gap: 1px;
grid-row-gap: 1px; // Is this being used? grid-row-gap: 1px; // Used for grid within a swimlane for Plan views
width: 100%; width: 100%;
&.is-status--draft { &.is-status--draft {
@ -43,6 +43,7 @@
&__lane-object { &__lane-object {
background: rgba(black, 0.1); background: rgba(black, 0.1);
height: 100%;
.c-plan { .c-plan {
display: contents; display: contents;