Make navigator resizable [SCI-9318]

This commit is contained in:
Ivan Kljun 2023-10-12 14:40:13 +02:00
parent 957f539e32
commit d34d424b0f
7 changed files with 87 additions and 26 deletions

View file

@ -10,7 +10,6 @@ body.navigator-collapsed {
--breadcrumbs-navigation-height: 44px;
--left-navigation-width: 192px;
--navbar-height: calc(var(--top-navigation-height) + var(--breadcrumbs-navigation-height));
--navigator-navigation-width: 224px;
--title-row-height: 4em;
--top-navigation-height: 72px;
display: grid;
@ -108,6 +107,11 @@ body.navigator-collapsed {
}
}
.resizable-r {
cursor: url("/images/icon_small/Resize.svg") 0 0, auto !important;
padding: 0 .8rem;
}
}
.w-98 {

View file

@ -20,6 +20,9 @@ class NavigationsController < ApplicationController
def navigator_state
session[:navigator_collapsed] = params[:state] == 'collapsed'
width = params[:width].to_i
session[:navigator_width] = width if width.positive?
end
private

View file

@ -1,34 +1,49 @@
<template>
<div class="w-[208px] ml-4 h-full border rounded relative bg-sn-white flex flex-col right-0 absolute navigator-container">
<div class="px-3 py-2.5 flex items-center relative leading-4">
<i class="sn-icon sn-icon-navigator"></i>
<div class="font-bold text-base pl-3">
{{ i18n.t('navigator.title') }}
<vue-resizable
ref="vueResizable"
:max-width="600"
:min-width="208"
width="auto"
height="100%"
:active="['r']"
@resize:start="onResizeStart"
@resize:move="onResizeMove"
@resize:end="onResizeEnd"
>
<div class="ml-4 h-full border rounded relative bg-sn-white flex flex-col right-0 absolute navigator-container">
<div class="px-3 py-2.5 flex items-center relative leading-4">
<i class="sn-icon sn-icon-navigator"></i>
<div class="font-bold text-base pl-3">
{{ i18n.t('navigator.title') }}
</div>
<i @click="$emit('navigator:colapse')" class="sn-icon sn-icon-close ml-auto cursor-pointer absolute right-2.5 top-2.5"></i>
</div>
<i @click="$emit('navigator:colapse')" class="sn-icon sn-icon-close ml-auto cursor-pointer absolute right-2.5 top-2.5"></i>
<perfect-scrollbar @ps-scroll-y="onScrollY" @ps-scroll-x="onScrollX" ref="scrollContainer" class="grow py-2 relative px-2 scroll-container">
<NavigatorItem v-for="item in sortedMenuItems"
:key="item.id"
:currentItemId="currentItemId"
:item="item"
:firstLevel="true"
:reloadCurrentLevel="reloadCurrentLevel"
:paddingLeft="0"
:reloadChildrenLevel="reloadChildrenLevel"
:archived="archived" />
</perfect-scrollbar>
</div>
<perfect-scrollbar @ps-scroll-y="onScrollY" @ps-scroll-x="onScrollX" ref="scrollContainer" class="grow py-2 relative px-2 scroll-container">
<NavigatorItem v-for="item in sortedMenuItems"
:key="item.id"
:currentItemId="currentItemId"
:item="item"
:firstLevel="true"
:reloadCurrentLevel="reloadCurrentLevel"
:paddingLeft="0"
:reloadChildrenLevel="reloadChildrenLevel"
:archived="archived" />
</perfect-scrollbar>
</div>
</vue-resizable>
</template>
<script>
import NavigatorItem from './navigator_item.vue'
import VueResizable from 'vue-resizable'
import axios from '../../packs/custom_axios.js';
export default {
name : 'NavigatorContainer',
components: {
NavigatorItem
NavigatorItem,
VueResizable
},
data() {
return {
@ -70,6 +85,9 @@ export default {
}
});
},
mounted() {
this.$refs.vueResizable.style.width = this.getNavigatorWidth()
},
watch: {
archived() {
this.loadTree();
@ -89,21 +107,50 @@ export default {
this.currentItemId = $('#active_navigator_item').val();
this.archived = $('#active_navigator_archived').val() === 'true';
},
loadTree() {
async loadTree() {
if (!this.navigatorUrl) return;
$.get(this.navigatorUrl, {archived: this.archived}, (data) => {
this.menuItems = [];
this.$nextTick(() => {
this.menuItems = data.items;
try {
const { data } = await axios.get(this.navigatorUrl, {
params: { archived: this.archived }
});
})
this.menuItems = data.items;
} catch (error) {
console.error('An error occurred while fetching the data', error);
}
},
onScrollY({target}) {
this.navigatorYScroll = target.scrollTop;
},
onScrollX({target}) {
this.navigatorXScroll = target.scrollLeft;
},
getNavigatorWidth() {
const computedStyle = getComputedStyle(document.documentElement);
return computedStyle.getPropertyValue('--navigator-navigation-width').trim();
},
onResizeMove(event) {
document.documentElement.style.setProperty('--navigator-navigation-width', event.width + 'px');
},
onResizeStart() {
document.body.style.cursor = 'url(/images/icon_small/Resize.svg) 0 0, auto';
$('.sci--layout-navigation-navigator').addClass('no-transition');
$('.sci--layout').addClass('no-transition');
},
onResizeEnd(event) {
document.body.style.cursor = 'default';
$('.sci--layout-navigation-navigator').removeClass('no-transition');
$('.sci--layout').removeClass('no-transition');
this.changeNavigatorState(event.width)
},
async changeNavigatorState(newWidth) {
try {
const navigatorContainer = document.getElementById('sciNavigationNavigatorContainer');
const stateUrl = navigatorContainer.getAttribute('data-navigator-state-url');
await axios.post(stateUrl, { width: newWidth });
} catch (error) {
console.error('An error occurred while sending the request', error);
}
}
},
}

View file

@ -49,6 +49,7 @@
<%= stylesheet_link_tag 'tui_image_editor_styles' %>
<%= javascript_include_tag 'vue_navigation_navigator' %>
<%= javascript_include_tag 'vue_navigation_top_menu' %>
<style> :root { --navigator-navigation-width: <%= session[:navigator_width] || Constants::DEFAULT_NAV_WIDTH %>px; } </style>
</head>
<body
class="<%= yield :body_class %> <%= 'navigator-collapsed' if !@navigator || session[:navigator_collapsed] %> <%= 'w-[98%]' if params[:controller] == 'label_templates' && params[:action] == 'show'%>"

View file

@ -73,6 +73,8 @@ class Constants
EXPERIMENT_LONG_DESCRIPTION = 80
# Infinite scroll default elements per page
DEFAULT_ELEMENTS_PER_PAGE = 20
# Default navigator width
DEFAULT_NAV_WIDTH = 208
#=============================================================================
# File and data memory size

View file

@ -78,6 +78,7 @@
"twemoji": "^12.1.4",
"vue": "^2.6.11",
"vue-loader": "^15.9.1",
"vue-resizable": "2.1.3",
"vue-template-compiler": "^2.6.12",
"vue-turbolinks": "^2.2.1",
"vue2-perfect-scrollbar": "^1.5.56",

View file

@ -0,0 +1,3 @@
<svg width="25.33" height="10" viewBox="0 0 25.33 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.51 0.320059L13.81 1.02006L17.1 4.31006H9H8.77H1.9L5.2 1.01006L4.5 0.310059L0 4.81006L4.5 9.31006L5.2 8.61006L1.9 5.31006H8.77H9H17.1L13.8 8.61006L14.5 9.31006L19 4.81006L14.51 0.320059Z" fill="#1D2939"/>
</svg>

After

Width:  |  Height:  |  Size: 326 B