Merge pull request #6645 from lasniscinote/gl_SCI_9670

Implement a link in the relationships column [SCI-9670]
This commit is contained in:
Martin Artnik 2023-11-28 09:21:33 +01:00 committed by GitHub
commit 3da2e68177
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 91 deletions

View file

@ -6,8 +6,11 @@
$(document).on('click', '.relationships-cell-wrapper', function(e) {
e.stopPropagation();
e.preventDefault();
const relationshipsUrl = $(this).attr('data-relationships-url');
window.itemRelationshipsModal.show(relationshipsUrl);
const myModuleId = $('.my-module-content').data('task-id');
// extract the href attribute from a neighboring column cell, required for sidebar to open
const repositoryRowURL = $(this).closest('tr').find('.sorting_1 a').attr('href');
window.repositoryItemSidebarComponent.toggleShowHideSidebar(repositoryRowURL, myModuleId, 'relationships-section');
});
$(document).on('click', '.record-info-link', function (e) {
@ -17,7 +20,7 @@
e.stopPropagation();
e.preventDefault();
window.repositoryItemSidebarComponent.toggleShowHideSidebar(repositoryRowURL, myModuleId);
window.repositoryItemSidebarComponent.toggleShowHideSidebar(repositoryRowURL, myModuleId, null);
});
$(document).on('click', '.print-label-button', function(e) {

View file

@ -128,7 +128,7 @@
<!-- RELATIONSHIPS -->
<section id="relationships-section" class="flex flex-col" ref="relationshipsSectionRef">
<div class="flex flex-row text-base font-semibold w-[350px] pb-4 leading-7 items-center justify-between transition-colors duration-300"
ref="relationships-label">
ref="relationships-label">
{{ i18n.t('repositories.item_card.section.relationships') }}
</div>
<template v-if="!parentsCount && !childrenCount">
@ -271,9 +271,9 @@
{ id: 'highlight-item-1', textId: 'text-item-1', labelAlias: 'information_label', label: 'information-label', sectionId: 'information-section' },
{ id: 'highlight-item-2', textId: 'text-item-2', labelAlias: 'custom_columns_label', label: 'custom-columns-label', sectionId: 'custom-columns-section' },
{ id: 'highlight-item-3', textId: 'text-item-3', labelAlias: 'relationships_label', label: 'relationships-label', sectionId: 'relationships-section' },
{ id: 'highlight-item-3', textId: 'text-item-3', labelAlias: 'assigned_label', label: 'assigned-label', sectionId: 'assigned-section' },
{ id: 'highlight-item-4', textId: 'text-item-4', labelAlias: 'QR_label', label: 'QR-label', sectionId: 'qr-section' }
]" v-show="isShowing">
{ id: 'highlight-item-4', textId: 'text-item-4', labelAlias: 'assigned_label', label: 'assigned-label', sectionId: 'assigned-section' },
{ id: 'highlight-item-5', textId: 'text-item-5', labelAlias: 'QR_label', label: 'QR-label', sectionId: 'qr-section' }
]" v-show="isShowing" :initialSectionId="this.initialSectionId">
</scroll-spy>
</div>
</div>
@ -300,7 +300,7 @@
import InlineEdit from '../shared/inline_edit.vue';
import ScrollSpy from './repository_values/ScrollSpy.vue';
import CustomColumns from './customColumns.vue';
import RepositoryItemSidebarTitle from './Title.vue'
import RepositoryItemSidebarTitle from './Title.vue';
export default {
name: 'RepositoryItemSidebar',
@ -333,7 +333,8 @@ export default {
inRepository: false,
icons: null,
relationshipDetailsState: {},
}
initialSectionId: null,
};
},
created() {
window.repositoryItemSidebarComponent = this;
@ -341,19 +342,19 @@ export default {
computed: {
repositoryRowName() {
return this.defaultColumns?.archived ? `${I18n.t('labels.archived')} ${this.defaultColumns?.name}` : this.defaultColumns?.name;
}
},
},
watch: {
parents() {
this.parents.forEach(parent => {
this.parents.forEach((parent) => {
this.$set(this.relationshipDetailsState, parent.code, false);
});
},
children() {
this.children.forEach(child => {
this.children.forEach((child) => {
this.$set(this.relationshipDetailsState, child.code, false);
});
}
},
},
mounted() {
// Add a click event listener to the document
@ -366,36 +367,37 @@ export default {
},
methods: {
handleOutsideClick(event) {
if (!this.isShowing) return
if (!this.isShowing) return;
// Check if the clicked element is not within the sidebar and it's not another item link or belogs to modals
const selectors = ['a', '.modal', '.label-printing-progress-modal', '.atwho-view'];
if (!$(event.target).parents('#repository-item-sidebar-wrapper').length &&
!selectors.some(selector => event.target.closest(selector))) {
if (!$(event.target).parents('#repository-item-sidebar-wrapper').length
&& !selectors.some((selector) => event.target.closest(selector))) {
this.toggleShowHideSidebar(null);
}
},
toggleShowHideSidebar(repositoryRowUrl, myModuleId = null) {
toggleShowHideSidebar(repositoryRowUrl, myModuleId = null, initialSectionId = null) {
if (initialSectionId) {
this.initialSectionId = initialSectionId;
} else this.initialSectionId = null;
// initial click
if (this.currentItemUrl === null) {
this.myModuleId = myModuleId;
this.isShowing = true;
this.loadRepositoryRow(repositoryRowUrl);
this.currentItemUrl = repositoryRowUrl;
return
}
// click on the same item - should just open/close it
else if (this.currentItemUrl === repositoryRowUrl) {
this.isShowing = !this.isShowing;
return
}
// explicit close (from emit)
else if (repositoryRowUrl === null) {
this.isShowing = false;
this.currentItemUrl = null;
this.myModuleId = null;
return
}
// click on a different item - if the item card is already showing should just fetch new data
else {
@ -403,11 +405,10 @@ export default {
this.myModuleId = myModuleId;
this.loadRepositoryRow(repositoryRowUrl);
this.currentItemUrl = repositoryRowUrl;
return
}
},
loadRepositoryRow(repositoryRowUrl) {
this.dataLoading = true
this.dataLoading = true;
$.ajax({
method: 'GET',
url: repositoryRowUrl,
@ -432,7 +433,7 @@ export default {
this.$nextTick(() => {
this.generateBarCode(this.defaultColumns.code);
});
}
},
});
},
reload() {
@ -450,7 +451,7 @@ export default {
const barCodeCanvas = bwipjs.toCanvas('bar-code-canvas', {
bcid: 'qrcode',
text,
scale: 3
scale: 3,
});
this.barCodeSrc = barCodeCanvas.toDataURL('image/png');
},
@ -468,7 +469,7 @@ export default {
},
}).done((response) => {
if (response) {
this.customColumns = this.customColumns.map(col => col.id === response.id ? { ...col, ...response } : col)
this.customColumns = this.customColumns.map((col) => (col.id === response.id ? { ...col, ...response } : col));
if ($('.dataTable')[0]) $('.dataTable').DataTable().ajax.reload(null, false);
}
});
@ -476,6 +477,6 @@ export default {
updateOpenState(code, isOpen) {
this.$set(this.relationshipDetailsState, code, isOpen);
},
}
}
},
};
</script>

View file

@ -26,6 +26,7 @@ export default {
props: {
itemsToCreate: Array,
initialSectionId: String || null,
},
data() {
@ -40,23 +41,21 @@ export default {
centerOfScrollThumb: null,
};
},
mounted() {
console.log('mounted');
window.addEventListener('resize', this.handleResize);
this.initializeComponent();
this.$nextTick(() => {
this.calculateAllSectionsCumulativeHeight()
this.calculateAllSectionsCumulativeHeight();
this.calculateSectionsHeight();
this.constructThresholds()
this.handleScroll()
this.constructThresholds();
this.handleScroll();
if (!this.initialSectionId) {
this.navigateToSection(this.itemsToCreate[0])
}
else {
const itemToNavigateTo = this.itemsToCreate.find((item) => item.sectionId === this.initialSectionId)
this.navigateToSection(itemToNavigateTo)
this.navigateToSection(this.itemsToCreate[0]);
} else {
const itemToNavigateTo = this.itemsToCreate.find((item) => item.sectionId === this.initialSectionId);
this.navigateToSection(itemToNavigateTo);
}
});
},
@ -65,12 +64,11 @@ export default {
window.removeEventListener('resize', this.handleResize);
this.removeScrollListener();
},
methods: {
initializeComponent() {
const bodyWrapperEl = document.getElementById('body-wrapper')
const scrollSpyContentEl = document.getElementById('scrollSpyContent')
this.bodyContainerEl = bodyWrapperEl
const bodyWrapperEl = document.getElementById('body-wrapper');
const scrollSpyContentEl = document.getElementById('scrollSpyContent');
this.bodyContainerEl = bodyWrapperEl;
this.sections = Array.from(scrollSpyContentEl.querySelectorAll('section[id]'));
this.navigationItemsStatus = Array(this.sections.length).fill(false);
this.navigationItemsStatus[0] = true;
@ -86,18 +84,18 @@ export default {
},
calculateAllSectionsCumulativeHeight() {
let totalHeight = 0
let totalHeight = 0;
this.itemsToCreate.forEach((item) => {
const sectionEl = document.getElementById(item.sectionId);
totalHeight += sectionEl.offsetHeight
})
this.allSectionsCumulativeHeight = totalHeight
totalHeight += sectionEl.offsetHeight;
});
this.allSectionsCumulativeHeight = totalHeight;
},
calculateSectionsHeight() {
// Initialize an array to store the height data for each section
this.sectionsWithHeight = this.itemsToCreate.map(item => {
this.sectionsWithHeight = this.itemsToCreate.map((item) => {
// Find the DOM element for the section
const sectionEl = document.getElementById(item.sectionId);
@ -108,8 +106,8 @@ export default {
// Return an object containing the section ID and its percentage height
return {
sectionId: item.sectionId,
heightPx: heightPx,
percentHeight: percentHeight
heightPx,
percentHeight,
};
});
},
@ -119,57 +117,55 @@ export default {
// on the % of vertical space of scrollable content that they occupy
constructThresholds() {
const scrollableArea = this.bodyContainerEl;
const deltaTravel = scrollableArea.scrollHeight - scrollableArea.clientHeight
const deltaTravel = scrollableArea.scrollHeight - scrollableArea.clientHeight;
const viewportHeight = scrollableArea.clientHeight;
const scrollableAreaHeight = scrollableArea.scrollHeight;
const scrollThumbHeight = Math.round(viewportHeight / scrollableAreaHeight * viewportHeight);
const scrollThumbCenter = Math.round(scrollThumbHeight / 2)
this.centerOfScrollThumb = scrollThumbCenter
this.scrollPosition = scrollThumbCenter
const scrollThumbCenter = Math.round(scrollThumbHeight / 2);
this.centerOfScrollThumb = scrollThumbCenter;
this.scrollPosition = scrollThumbCenter;
let prevThreshold = scrollThumbCenter
let prevThreshold = scrollThumbCenter;
for (let i = 0; i < this.sectionsWithHeight.length; i++) {
// first section
if (i === 0) {
const from = prevThreshold
const to = Math.round(deltaTravel * this.sectionsWithHeight[i].percentHeight / 100) + prevThreshold
const id = this.sectionsWithHeight[i].sectionId
prevThreshold = to + 1
const from = prevThreshold;
const to = Math.round(deltaTravel * this.sectionsWithHeight[i].percentHeight / 100) + prevThreshold;
const id = this.sectionsWithHeight[i].sectionId;
prevThreshold = to + 1;
const threshold = {
id,
index: i,
from,
to
}
this.thresholds[i] = threshold
}
// last section
else if (i === this.sectionsWithHeight.length - 1) {
const from = prevThreshold
const to = scrollableArea.scrollHeight
const id = this.sectionsWithHeight[i].sectionId
to,
};
this.thresholds[i] = threshold;
} else if (i === this.sectionsWithHeight.length - 1) {
// last section
const from = prevThreshold;
const to = scrollableArea.scrollHeight;
const id = this.sectionsWithHeight[i].sectionId;
const threshold = {
id,
index: i,
from,
to
}
this.thresholds[i] = threshold
}
else {
to,
};
this.thresholds[i] = threshold;
} else {
// other sections
const from = prevThreshold
const to = Math.round(deltaTravel * this.sectionsWithHeight[i].percentHeight / 100) + prevThreshold - 1
const id = this.sectionsWithHeight[i].sectionId
prevThreshold = to + 1
const from = prevThreshold;
const to = Math.round(deltaTravel * this.sectionsWithHeight[i].percentHeight / 100) + prevThreshold - 1;
const id = this.sectionsWithHeight[i].sectionId;
prevThreshold = to + 1;
const threshold = {
id,
index: i,
from,
to
}
this.thresholds[i] = threshold
to,
};
this.thresholds[i] = threshold;
}
}
},
@ -188,26 +184,24 @@ export default {
this.removeScrollListener();
const scrollableArea = this.bodyContainerEl;
const foundThreshold = this.thresholds.find((obj) => obj.id === navigationItem.sectionId)
const domElToScrollTo = document.getElementById(navigationItem.label)
const foundThreshold = this.thresholds.find((obj) => obj.id === navigationItem.sectionId);
const domElToScrollTo = document.getElementById(navigationItem.label);
if (foundThreshold.index === 0) {
// scroll to top
this.bodyContainerEl.scrollTo({
top: 0,
behavior: "auto"
behavior: 'auto',
});
}
else if (foundThreshold.index === this.thresholds.length - 1) {
} else if (foundThreshold.index === this.thresholds.length - 1) {
// scroll to bottom
this.bodyContainerEl.scrollTo({
top: 99999,
behavior: "auto"
behavior: 'auto',
});
}
else {
} else {
// scroll to the start of a section's threshold, adjusted for the center thumb value (true center)
scrollableArea.scrollTop = foundThreshold.from - this.centerOfScrollThumb
scrollableArea.scrollTop = foundThreshold.from - this.centerOfScrollThumb;
}
this.flashTitleColor(domElToScrollTo);
@ -216,7 +210,7 @@ export default {
},
flashTitleColor(domEl) {
if (!domEl) return
if (!domEl) return;
domEl.classList.add('text-sn-science-blue');
setTimeout(() => domEl.classList.remove('text-sn-science-blue'), 300);
@ -224,9 +218,9 @@ export default {
handleResize() {
this.$nextTick(() => {
this.calculateAllSectionsCumulativeHeight()
this.calculateAllSectionsCumulativeHeight();
this.calculateSectionsHeight();
this.constructThresholds()
this.constructThresholds();
});
},
@ -249,6 +243,6 @@ export default {
}
});
},
}
}
},
};
</script>