Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize column layout experience #4006

Merged
merged 10 commits into from
Oct 22, 2023
19 changes: 16 additions & 3 deletions frontend/src/components/activity/CardContentNode.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<template>
<v-card :elevation="draggable ? 4 : 0" :class="{ 'mx-2 my-2': draggable }">
<v-card
:elevation="draggable ? 4 : 0"
:tile="draggable ? null : true"
class="d-flex flex-column"
:class="{ 'mx-2 my-2': draggable }"
>
<v-card-title hide-actions class="pa-0 pr-sm-2">
<v-toolbar dense flat>
<v-icon class="mr-2">{{ icon }}</v-icon>
Expand Down Expand Up @@ -56,7 +61,7 @@
</v-toolbar>
</v-card-title>
<slot name="outer">
<v-card-text>
<v-card-text class="flex-grow-1">
<slot />
</v-card-text>
</slot>
Expand Down Expand Up @@ -108,7 +113,7 @@ export default {
}
</script>

<style scoped>
<style scoped lang="scss">
.v-card:not(:hover):deep(button.visible-on-hover),
.v-card:not(:hover):deep(button.tooltip-activator) {
opacity: 0;
Expand All @@ -127,4 +132,12 @@ export default {
opacity 0.2s linear,
width 0.3s steps(1, start);
}

::v-deep {
.e-form-container,
.v-input,
.v-input__control {
height: 100%;
}
}
</style>
1 change: 0 additions & 1 deletion frontend/src/components/activity/ContentNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export default {

<style lang="scss">
.content-node:not(.draggable) + .content-node:not(.draggable) {
border-top: 1px solid rgba(0, 0, 0, 0.12) !important;
border-radius: 0 !important;
}

Expand Down
43 changes: 38 additions & 5 deletions frontend/src/components/activity/DraggableContentNodes.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
<template>
<div>
<div class="d-flex flex-column flex-grow-1">
<draggable
v-if="contentNodeIds"
v-model="localContentNodeIds"
:disabled="!draggingEnabled"
group="contentNodes"
class="draggable-area d-flex flex-column pb-10"
:class="{ 'min-height': layoutMode }"
:invert-swap="true"
class="draggable-area flex-grow-1"
:class="{
'min-height draggable-area--layout-mode pb-2': layoutMode,
'draggable-area--read-mode': !layoutMode,
'draggable-area--root': isRoot,
'draggable-area--column d-flex flex-column': direction === 'column',
'draggable-area--row d-flex flex-row flex-wrap': direction === 'row',
}"
:swap-threshold="0.65"
:inverted-swap-threshold="0.65"
@start="startDrag"
@add="finishDrag"
@update="finishDrag"
Expand All @@ -23,10 +30,16 @@
:draggable="draggingEnabled"
:disabled="disabled"
/>
<v-sheet
v-if="!layoutMode && draggableContentNodeIds.length === 0"
elevation="0"
class="content-node placeholder-node"
></v-sheet>
</draggable>

<button-nested-content-node-add
v-if="layoutMode"
class="flex-grow-0"
:layout-mode="layoutMode"
:parent-content-node="parentContentNode"
:slot-name="slotName"
Expand All @@ -53,6 +66,8 @@ export default {
slotName: { type: String, required: true },
parentContentNode: { type: Object, required: true },
disabled: { type: Boolean, default: false },
direction: { type: String, default: 'column' },
carlobeltrame marked this conversation as resolved.
Show resolved Hide resolved
isRoot: { type: Boolean, default: false },
},
data() {
return {
Expand Down Expand Up @@ -138,6 +153,24 @@ export default {
min-height: 10rem;
}

.draggable-area ::v-deep .content-node {
margin: 0 !important;
flex-grow: 1;
}

.draggable-area--row ::v-deep .content-node {
flex: 1 0 320px;
}

.draggable-area--layout-mode {
display: flex !important;
gap: 4px;
}

.draggable-area--read-mode {
gap: 1px;
}

.dragging-content-node .draggable-area {
position: relative;
z-index: 100;
Expand All @@ -151,7 +184,7 @@ export default {
left: 4px;
right: 4px;
border-radius: 5px;
border: 2px dashed map-get($blue-grey, 'base');
border: 2px dotted map-get($blue-grey, 'base');
background: map-get($blue-grey, 'lighten-4');
opacity: 40%;
content: '';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<v-menu bottom left offset-y>
<template #activator="{ on, attrs }">
<v-btn icon class="float-right mr-4 mt-3" v-bind="attrs" v-on="on">
<v-btn icon v-bind="attrs" v-on="on">
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</template>
Expand Down
4 changes: 0 additions & 4 deletions frontend/src/components/activity/ScheduleEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,6 @@ export default {
margin-bottom: 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
padding: 1.5rem 16px;

@media #{map-get($display-breakpoints, 'sm-and-down')} {
border-bottom: none;
}
}

.e-category-chip-save-icon {
Expand Down
110 changes: 73 additions & 37 deletions frontend/src/components/activity/content/ColumnLayout.vue
Original file line number Diff line number Diff line change
@@ -1,38 +1,54 @@
<template>
<v-row v-if="!contentNode.loading" no-gutters>
<resizable-column
v-for="(_, slot) in columns"
:key="slot"
:parent-content-node="contentNode"
:layout-mode="layoutMode"
:width-left="relativeColumnWidths[slot][0]"
:width="relativeColumnWidths[slot][1]"
:width-right="relativeColumnWidths[slot][2]"
:num-columns="numColumns"
:last="slot === lastColumn"
:min-width="minWidth(slot)"
:max-width="maxWidth(slot)"
:color="color"
:show-header="!isRoot"
@resizing="(newWidth) => resizeColumn(slot, newWidth)"
@resize-stop="saveColumnWidths"
>
<draggable-content-nodes
:slot-name="slot"
:layout-mode="layoutMode"
:parent-content-node="contentNode"
:disabled="disabled"
/>

<template #menu>
<LayoutCard
v-resizeobserver.debounce="onResize"
class="ec-column-layout"
:class="{ 'my-2': !isRoot && layoutMode }"
:is-root="isRoot"
:layout-mode="layoutMode"
>
<template #header>
{{ $tc('contentNode.columnLayout.name') }}
<MenuCardlessContentNode :content-node="contentNode">
<column-operations
:content-node="contentNode"
:min-column-width="minWidth(slot)"
:total-width="12"
:min-column-width="minWidth"
:total-width="totalWidth"
/>
</template>
</resizable-column>
</v-row>
</MenuCardlessContentNode>
</template>
<div
v-if="!contentNode.loading"
class="d-flex flex-wrap ec-column-layout__container"
:class="{ 'px-1 gap-4': layoutMode, 'h-full': !layoutMode }"
>
<resizable-column
v-for="(_, slot) in columns"
:key="slot"
:parent-content-node="contentNode"
:layout-mode="layoutMode"
:width-left="relativeColumnWidths[slot][0]"
:width="relativeColumnWidths[slot][1]"
:width-right="relativeColumnWidths[slot][2]"
:num-columns="numColumns"
:last="slot === lastColumn"
:min-width="minWidth"
:max-width="maxWidth(slot)"
:color="color"
:show-header="!isRoot"
:is-default-variant="isDefaultVariant"
@resizing="(newWidth) => resizeColumn(slot, newWidth)"
@resize-stop="saveColumnWidths"
>
<draggable-content-nodes
:slot-name="slot"
:layout-mode="layoutMode"
:parent-content-node="contentNode"
:disabled="disabled"
:is-root="isRoot"
/>
</resizable-column>
</div>
</LayoutCard>
</template>

<script>
Expand All @@ -43,6 +59,9 @@ import DraggableContentNodes from '@/components/activity/DraggableContentNodes.v
import ColumnOperations from '@/components/activity/content/columnLayout/ColumnOperations.vue'
import { idToColor } from '@/common/helpers/colors.js'
import { errorToMultiLineToast } from '@/components/toast/toasts'
import MenuCardlessContentNode from '@/components/activity/MenuCardlessContentNode.vue'
import LayoutCard from '@/components/activity/content/layout/LayoutCard.vue'
import camelCase from 'lodash/camelCase.js'

function cumulativeSumReducer(cumSum, nextElement) {
cumSum.push(cumSum[cumSum.length - 1] + nextElement)
Expand All @@ -52,13 +71,18 @@ function cumulativeSumReducer(cumSum, nextElement) {
export default {
name: 'ColumnLayout',
components: {
LayoutCard,
MenuCardlessContentNode,
ColumnOperations,
DraggableContentNodes,
ResizableColumn,
},
mixins: [contentNodeMixin],
data() {
return {
clientWidth: 1000,
minWidth: 3,
totalWidth: 12,
localColumnWidths: {},
}
},
Expand Down Expand Up @@ -98,6 +122,11 @@ export default {
isRoot() {
return this.contentNode._meta.self === this.contentNode.root()._meta.self
},
isDefaultVariant() {
// 260 is between 870/3 and 870/4.
// We don't want average column widths of below 260px as the readability suffers.
return this.clientWidth / this.numColumns > 260
},
},
watch: {
columns: {
Expand All @@ -108,6 +137,7 @@ export default {
},
},
methods: {
camelCase,
setLocalColumnWidths() {
this.localColumnWidths = mapValues(this.columns, 'width')
},
Expand All @@ -124,18 +154,16 @@ export default {
if (index === -1 || index === slots.length - 1) return undefined
return slots[index + 1]
},
minWidth() {
return 3
},
maxWidth(slot) {
const nextSlot = this.next(slot)
if (nextSlot === undefined) return this.localColumnWidths[slot]
return (
this.localColumnWidths[slot] +
this.localColumnWidths[nextSlot] -
this.minWidth(nextSlot)
this.localColumnWidths[slot] + this.localColumnWidths[nextSlot] - this.minWidth
)
},
onResize({ width }) {
this.clientWidth = width
},
async saveColumnWidths() {
const payload = {
data: {
Expand All @@ -154,3 +182,11 @@ export default {
},
}
</script>

<style scoped>
.ec-column-layout__container {
background-color: #ccc;
border-bottom-left-radius: 9px;
border-bottom-right-radius: 9px;
}
</style>
16 changes: 7 additions & 9 deletions frontend/src/components/activity/content/Material.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
<template>
<card-content-node v-bind="$props">
<div class="mb-3">
<material-table
:camp="camp()"
:material-node="contentNode"
:layout-mode="layoutMode"
:material-item-collection="materialItemCollection"
:disabled="disabled"
/>
</div>
<material-table
:camp="camp()"
:material-node="contentNode"
:layout-mode="layoutMode"
:material-item-collection="materialItemCollection"
:disabled="disabled"
/>
</card-content-node>
</template>

Expand Down
26 changes: 10 additions & 16 deletions frontend/src/components/activity/content/Notes.vue
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
<template>
<card-content-node v-bind="$props">
<div class="mb-3">
<api-form :entity="contentNode">
<api-richtext
fieldname="data.html"
:label="$tc('contentNode.notes.name')"
rows="4"
auto-grow
:disabled="layoutMode || disabled"
:filled="layoutMode"
/>
</api-form>
</div>
<api-richtext
:uri="contentNode._meta.self"
fieldname="data.html"
:label="$tc('contentNode.notes.name')"
rows="4"
auto-grow
:disabled="layoutMode || disabled"
:filled="layoutMode"
height="100%"
/>
</card-content-node>
</template>

<script>
import ApiForm from '@/components/form/api/ApiForm.vue'
import CardContentNode from '@/components/activity/CardContentNode.vue'
import { contentNodeMixin } from '@/mixins/contentNodeMixin.js'

export default {
name: 'Notes',
components: {
CardContentNode,
ApiForm,
},
mixins: [contentNodeMixin],
}
</script>

<style scoped></style>
Loading