mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-06 20:05:55 +08:00
Add collapsable breadcrumbs component [SCI-11184]
This commit is contained in:
parent
8e0f0e27a7
commit
adcc401a79
7 changed files with 132 additions and 7 deletions
|
@ -8,7 +8,7 @@ class UserNotificationsController < ApplicationController
|
||||||
notifications = load_notifications
|
notifications = load_notifications
|
||||||
|
|
||||||
case params[:tab]
|
case params[:tab]
|
||||||
when 'all'
|
when 'read'
|
||||||
notifications = notifications.where.not(read_at: nil)
|
notifications = notifications.where.not(read_at: nil)
|
||||||
when 'unread'
|
when 'unread'
|
||||||
notifications = notifications.where(read_at: nil)
|
notifications = notifications.where(read_at: nil)
|
||||||
|
|
22
app/javascript/packs/vue/design_system/breadcrumbs.js
Normal file
22
app/javascript/packs/vue/design_system/breadcrumbs.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { createApp } from 'vue/dist/vue.esm-bundler.js';
|
||||||
|
import Breadcrumbs from '../../../vue/shared/breadcrumbs.vue';
|
||||||
|
import { mountWithTurbolinks } from '../helpers/turbolinks.js';
|
||||||
|
|
||||||
|
const app = createApp({
|
||||||
|
computed: {
|
||||||
|
breadcrumbs() {
|
||||||
|
return [
|
||||||
|
{ name: 'Home', url: '/' },
|
||||||
|
{ name: 'Very very very long name ', url: '' },
|
||||||
|
{ name: 'Data', url: '' },
|
||||||
|
{ name: 'Very very very very very very very very very very long name ', url: '' },
|
||||||
|
{ name: 'Very very very very very very very long name ', url: '' },
|
||||||
|
{ name: 'Very very very very very long name ', url: '' },
|
||||||
|
{ name: 'Very very very very long name ', url: '' }
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app.component('Breadcrumbs', Breadcrumbs);
|
||||||
|
app.config.globalProperties.i18n = window.I18n;
|
||||||
|
mountWithTurbolinks(app, '#breadcrumbs');
|
|
@ -16,24 +16,23 @@
|
||||||
<div v-html="notification.attributes.message" class="sci-navigation--notificaitons-flyout-notification-message"></div>
|
<div v-html="notification.attributes.message" class="sci-navigation--notificaitons-flyout-notification-message"></div>
|
||||||
</a>
|
</a>
|
||||||
<div v-if="notification.attributes.breadcrumbs" class="flex items-center flex-wrap gap-0.5">
|
<div v-if="notification.attributes.breadcrumbs" class="flex items-center flex-wrap gap-0.5">
|
||||||
<template v-for="(breadcrumb, index) in notification.attributes.breadcrumbs" :key="index">
|
<Breadcrumbs :breadcrumbs="notification.attributes.breadcrumbs" />
|
||||||
<div class="flex items-center gap-0.5">
|
|
||||||
<i v-if="index > 0" class="sn-icon sn-icon-right"></i>
|
|
||||||
<a :href="breadcrumb.url" :title="breadcrumb.name" class="truncate max-w-[20ch] inline-block">{{ breadcrumb.name }}</a>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from '../../../packs/custom_axios.js';
|
import axios from '../../../packs/custom_axios.js';
|
||||||
|
import Breadcrumbs from '../../shared/breadcrumbs.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NotificationItem',
|
name: 'NotificationItem',
|
||||||
props: {
|
props: {
|
||||||
notification: Object
|
notification: Object
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
Breadcrumbs
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
lastBreadcrumbUrl() {
|
lastBreadcrumbUrl() {
|
||||||
if (!this.notification.attributes.breadcrumbs) {
|
if (!this.notification.attributes.breadcrumbs) {
|
||||||
|
|
93
app/javascript/vue/shared/breadcrumbs.vue
Normal file
93
app/javascript/vue/shared/breadcrumbs.vue
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
<template>
|
||||||
|
<div ref="container" class="w-full flex items-center flex-wrap gap-0.5">
|
||||||
|
<template v-if="!allVisible">
|
||||||
|
<div class="flex items-center gap-0.5">
|
||||||
|
<a :href="breadcrumbs[0].url" :title="breadcrumbs[0].name" class="max-w-[200px]">
|
||||||
|
<StringWithEllipsis class="w-full" :text="breadcrumbs[0].name"></StringWithEllipsis>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-0.5">
|
||||||
|
<i class="sn-icon sn-icon-right text-sn-grey"></i>
|
||||||
|
<GeneralDropdown>
|
||||||
|
<template v-slot:field>
|
||||||
|
<a>...</a>
|
||||||
|
</template>
|
||||||
|
<template v-slot:flyout>
|
||||||
|
<div class="max-w-[600px]">
|
||||||
|
<div v-for="(breadcrumb, index) in hiddenBreadcrumbs" :key="index" class="p-2 hover:bg-sn-super-light-grey cursor-pointer">
|
||||||
|
<a :href="breadcrumb.url" :title="breadcrumb.name" class="max-w-[200px] hover:no-underline">
|
||||||
|
<StringWithEllipsis class="w-full" :text="breadcrumb.name"></StringWithEllipsis>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</GeneralDropdown>
|
||||||
|
<i class="sn-icon sn-icon-right text-sn-grey"></i>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-for="(breadcrumb, index) in visibleBreadcrumbs" :key="index" class="flex items-center gap-0.5">
|
||||||
|
<i v-if="index > 0" class="sn-icon sn-icon-right text-sn-grey"></i>
|
||||||
|
<a :href="breadcrumb.url" :title="breadcrumb.name" class="max-w-[200px]">
|
||||||
|
<StringWithEllipsis class="w-full" :text="breadcrumb.name"></StringWithEllipsis>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import StringWithEllipsis from './string_with_ellipsis.vue';
|
||||||
|
import GeneralDropdown from './general_dropdown.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Breadcrumbs',
|
||||||
|
props: {
|
||||||
|
breadcrumbs: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
StringWithEllipsis,
|
||||||
|
GeneralDropdown
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
containerSize: 0,
|
||||||
|
breadcrumbSize: 200
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
breadcrumbsVisibleCount() {
|
||||||
|
const size = Math.floor(this.containerSize / this.breadcrumbSize);
|
||||||
|
if (size < 2) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
},
|
||||||
|
allVisible() {
|
||||||
|
return this.breadcrumbs.length <= this.breadcrumbsVisibleCount;
|
||||||
|
},
|
||||||
|
hiddenBreadcrumbs() {
|
||||||
|
return this.breadcrumbs.slice(1, this.breadcrumbs.length - this.breadcrumbsVisibleCount + 1);
|
||||||
|
},
|
||||||
|
visibleBreadcrumbs() {
|
||||||
|
if (this.allVisible) {
|
||||||
|
return this.breadcrumbs;
|
||||||
|
}
|
||||||
|
return this.breadcrumbs.slice(this.breadcrumbs.length - this.breadcrumbsVisibleCount + 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setContainerSize();
|
||||||
|
window.addEventListener('resize', this.setContainerSize);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.setContainerSize);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setContainerSize() {
|
||||||
|
this.containerSize = this.$refs.container.offsetWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>;
|
8
app/views/design_elements/_breadcrumbs.html.erb
Normal file
8
app/views/design_elements/_breadcrumbs.html.erb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<div>
|
||||||
|
<h1>breadcrumbs</h1>
|
||||||
|
<div id="breadcrumbs" class="flex items-center gap-4">
|
||||||
|
<Breadcrumbs :breadcrumbs="breadcrumbs">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= javascript_include_tag 'vue_design_system_breadcrumbs' %>
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
<%= render partial: 'select' %>
|
<%= render partial: 'select' %>
|
||||||
|
|
||||||
|
<%= render partial: 'breadcrumbs' %>
|
||||||
|
|
||||||
<%= render partial: 'modals' %>
|
<%= render partial: 'modals' %>
|
||||||
|
|
||||||
<%= render partial: 'icons', locals: {icons_list: icons_list} %>
|
<%= render partial: 'icons', locals: {icons_list: icons_list} %>
|
||||||
|
|
|
@ -54,6 +54,7 @@ const entryList = {
|
||||||
vue_experiments_list: './app/javascript/packs/vue/experiments_list.js',
|
vue_experiments_list: './app/javascript/packs/vue/experiments_list.js',
|
||||||
vue_my_modules_list: './app/javascript/packs/vue/my_modules_list.js',
|
vue_my_modules_list: './app/javascript/packs/vue/my_modules_list.js',
|
||||||
vue_design_system_select: './app/javascript/packs/vue/design_system/select.js',
|
vue_design_system_select: './app/javascript/packs/vue/design_system/select.js',
|
||||||
|
vue_design_system_breadcrumbs: './app/javascript/packs/vue/design_system/breadcrumbs.js',
|
||||||
vue_protocols_list: './app/javascript/packs/vue/protocols_list.js',
|
vue_protocols_list: './app/javascript/packs/vue/protocols_list.js',
|
||||||
vue_repositories_table: './app/javascript/packs/vue/repositories_table.js',
|
vue_repositories_table: './app/javascript/packs/vue/repositories_table.js',
|
||||||
vue_import_repository_modal: './app/javascript/packs/vue/import_repository_modal.js',
|
vue_import_repository_modal: './app/javascript/packs/vue/import_repository_modal.js',
|
||||||
|
|
Loading…
Add table
Reference in a new issue