Add an expandable metadata grid
This commit is contained in:
+110
-134
@@ -1,203 +1,179 @@
|
|||||||
/* ========================================
|
/* ========================================
|
||||||
FOLDER METADATA DISPLAY STYLES
|
FOLDER METADATA STYLES
|
||||||
======================================== */
|
======================================== */
|
||||||
|
|
||||||
|
/* Folder Metadata Container */
|
||||||
.folder-metadata-container {
|
.folder-metadata-container {
|
||||||
margin: 2rem 0;
|
margin: 1rem 0;
|
||||||
padding: 1.5rem;
|
|
||||||
background: var(--card-background);
|
|
||||||
border: 1px solid var(--border-color);
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
background: var(--card-bg);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-header {
|
/* Folder Metadata Toggle Button */
|
||||||
display: flex;
|
.folder-metadata-toggle {
|
||||||
justify-content: space-between;
|
width: 100%;
|
||||||
align-items: center;
|
padding: 0.75rem 1rem;
|
||||||
margin-bottom: 1rem;
|
background: var(--card-bg);
|
||||||
padding-bottom: 0.75rem;
|
|
||||||
border-bottom: 2px solid var(--border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-metadata-title {
|
|
||||||
margin: 0;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-size: 1.25rem;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-metadata-edit-btn {
|
|
||||||
background: var(--accent-color);
|
|
||||||
color: white;
|
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 6px;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 0.9rem;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
justify-content: space-between;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
position: relative;
|
||||||
|
z-index: 10;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-edit-btn:hover {
|
.folder-metadata-toggle:hover {
|
||||||
background: var(--accent-color-dark);
|
background: var(--button-hover);
|
||||||
transform: translateY(-1px);
|
color: white;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-edit-btn:active {
|
.folder-metadata-toggle:focus {
|
||||||
transform: translateY(0);
|
outline: 2px solid var(--link-color);
|
||||||
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.folder-metadata-icon {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-metadata-label {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-metadata-arrow {
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-metadata-container.expanded .folder-metadata-arrow {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Folder Metadata Content - HIDDEN BY DEFAULT */
|
||||||
|
.folder-metadata-content {
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height 0.3s ease, opacity 0.3s ease;
|
||||||
|
background: var(--bg-color);
|
||||||
|
opacity: 0;
|
||||||
|
display: none; /* Force hide initially */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show content when expanded */
|
||||||
|
.folder-metadata-container.expanded .folder-metadata-content {
|
||||||
|
max-height: 1000px;
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
opacity: 1;
|
||||||
|
display: block; /* Show when expanded */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Folder Metadata Grid */
|
||||||
.folder-metadata-grid {
|
.folder-metadata-grid {
|
||||||
|
padding: 1rem;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
gap: 1rem;
|
gap: 0.5rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Folder Metadata Items */
|
||||||
.folder-metadata-item {
|
.folder-metadata-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
align-items: flex-start;
|
||||||
background: var(--background);
|
gap: 0.5rem;
|
||||||
border: 1px solid var(--border-color-light);
|
padding: 0.25rem 0;
|
||||||
border-radius: 6px;
|
|
||||||
padding: 1rem;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-metadata-item:hover {
|
|
||||||
background: var(--hover-background);
|
|
||||||
border-color: var(--accent-color);
|
|
||||||
transform: translateY(-1px);
|
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-key {
|
.folder-metadata-key {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--accent-color);
|
color: var(--link-color);
|
||||||
margin-bottom: 0.5rem;
|
white-space: nowrap;
|
||||||
font-size: 0.95rem;
|
min-width: fit-content;
|
||||||
text-transform: capitalize;
|
|
||||||
border-bottom: 1px solid var(--border-color-light);
|
|
||||||
padding-bottom: 0.25rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-value {
|
.folder-metadata-value {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
line-height: 1.5;
|
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-value a {
|
/* Tags for list items */
|
||||||
color: var(--accent-color);
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom: 1px dotted var(--accent-color);
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-metadata-value a:hover {
|
|
||||||
color: var(--accent-color-dark);
|
|
||||||
border-bottom-style: solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-metadata-list {
|
.folder-metadata-list {
|
||||||
margin: 0;
|
display: flex;
|
||||||
padding-left: 1.5rem;
|
flex-wrap: wrap;
|
||||||
|
gap: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-list li {
|
.folder-metadata-tag {
|
||||||
margin-bottom: 0.25rem;
|
background: var(--link-color);
|
||||||
|
color: white;
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Nested metadata */
|
||||||
.folder-metadata-nested {
|
.folder-metadata-nested {
|
||||||
background: var(--background-dark);
|
background: var(--card-bg);
|
||||||
padding: 0.75rem;
|
padding: 0.5rem;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border-left: 3px solid var(--accent-color);
|
border-left: 3px solid var(--link-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-nested-item {
|
.folder-metadata-nested-item {
|
||||||
margin-bottom: 0.5rem;
|
margin: 0.25rem 0;
|
||||||
}
|
font-size: 0.9rem;
|
||||||
|
|
||||||
.folder-metadata-nested-item:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-metadata-nested-item strong {
|
|
||||||
color: var(--accent-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-metadata-long-text {
|
|
||||||
display: inline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Long text handling */
|
||||||
.folder-metadata-expand {
|
.folder-metadata-expand {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--accent-color);
|
color: var(--link-color);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
font-size: 0.9rem;
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-expand:hover {
|
.folder-metadata-expand:hover {
|
||||||
color: var(--accent-color-dark);
|
color: var(--link-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-full-text {
|
/* Links */
|
||||||
display: none;
|
.folder-metadata-value a {
|
||||||
|
color: var(--link-color);
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive adjustments */
|
.folder-metadata-value a:hover {
|
||||||
|
color: var(--link-hover);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive design */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.folder-metadata-container {
|
|
||||||
margin: 1rem 0;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-metadata-grid {
|
.folder-metadata-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: 0.75rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-header {
|
.folder-metadata-item {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
gap: 0.25rem;
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-metadata-edit-btn {
|
.folder-metadata-key {
|
||||||
align-self: flex-end;
|
white-space: normal;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dark theme adjustments */
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
.folder-metadata-container {
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder-metadata-item:hover {
|
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animation for expanding text */
|
|
||||||
.folder-metadata-full-text.show {
|
|
||||||
display: inline;
|
|
||||||
animation: fadeIn 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,8 +3,8 @@
|
|||||||
======================================== */
|
======================================== */
|
||||||
.grid {
|
.grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||||
gap: 1.2rem;
|
gap: 0.8rem;
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
@import url('./stats.css');
|
@import url('./stats.css');
|
||||||
@import url('./comparison.css');
|
@import url('./comparison.css');
|
||||||
@import url('./metadata.css');
|
@import url('./metadata.css');
|
||||||
|
@import url('./metadata-section.css');
|
||||||
@import url('./folder-metadata.css');
|
@import url('./folder-metadata.css');
|
||||||
@import url('./export.css');
|
@import url('./export.css');
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
/* ========================================
|
||||||
|
METADATA SECTION STYLES
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* Metadata Section Container */
|
||||||
|
.metadata-section {
|
||||||
|
margin: 1rem 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: var(--card-bg);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toggle Button */
|
||||||
|
.metadata-toggle-btn {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
background: var(--card-bg);
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
position: relative;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-toggle-btn:hover {
|
||||||
|
background: var(--button-hover);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-toggle-btn:focus {
|
||||||
|
outline: 2px solid var(--link-color);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-icon {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-label {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-arrow {
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content Area - Hidden by default */
|
||||||
|
.metadata-content {
|
||||||
|
background: var(--bg-color);
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
display: none; /* Hidden by default */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grid Layout */
|
||||||
|
.metadata-grid {
|
||||||
|
padding: 1rem;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 0.5rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Metadata Items */
|
||||||
|
.metadata-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.25rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-key {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--link-color);
|
||||||
|
white-space: nowrap;
|
||||||
|
min-width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-value {
|
||||||
|
color: var(--text-color);
|
||||||
|
word-break: break-word;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tags for list items */
|
||||||
|
.metadata-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-tag {
|
||||||
|
background: var(--link-color);
|
||||||
|
color: white;
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nested metadata */
|
||||||
|
.metadata-nested {
|
||||||
|
background: var(--card-bg);
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 3px solid var(--link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-nested-item {
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Long text handling */
|
||||||
|
.metadata-expand {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: var(--link-color);
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
padding: 0;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-expand:hover {
|
||||||
|
color: var(--link-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
.metadata-value a {
|
||||||
|
color: var(--link-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-value a:hover {
|
||||||
|
color: var(--link-hover);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.metadata-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-item {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-key {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,69 +1,81 @@
|
|||||||
/**
|
/**
|
||||||
* Folder Metadata functionality for Gallery
|
* Folder Metadata functionality for Gallery
|
||||||
*
|
*
|
||||||
* Handles interactions with folder-level metadata display
|
* Handles folder metadata dropdown display and interaction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Function to toggle expansion of long metadata text
|
// Define function immediately (not waiting for DOM)
|
||||||
function toggleMetadataText(button) {
|
window.toggleFolderMetadata = function() {
|
||||||
|
console.log('toggleFolderMetadata called');
|
||||||
|
|
||||||
|
const container = document.querySelector('.folder-metadata-container');
|
||||||
|
const content = document.getElementById('folderMetadataContent');
|
||||||
|
|
||||||
|
if (!container) {
|
||||||
|
console.log('No metadata container found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
console.log('No metadata content found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isExpanded = container.classList.contains('expanded');
|
||||||
|
console.log('Current state - expanded:', isExpanded);
|
||||||
|
|
||||||
|
if (isExpanded) {
|
||||||
|
// Collapse
|
||||||
|
container.classList.remove('expanded');
|
||||||
|
content.style.display = 'none';
|
||||||
|
console.log('Collapsed dropdown');
|
||||||
|
} else {
|
||||||
|
// Expand
|
||||||
|
container.classList.add('expanded');
|
||||||
|
content.style.display = 'block';
|
||||||
|
console.log('Expanded dropdown');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save state
|
||||||
|
localStorage.setItem('folderMetadataExpanded', (!isExpanded).toString());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Also define as regular function for alternative access
|
||||||
|
function toggleFolderMetadata() {
|
||||||
|
window.toggleFolderMetadata();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle long text display
|
||||||
|
window.toggleMetadataText = function(button) {
|
||||||
const longText = button.previousElementSibling;
|
const longText = button.previousElementSibling;
|
||||||
const fullText = button.nextElementSibling;
|
const fullText = button.nextElementSibling;
|
||||||
|
|
||||||
if (fullText.style.display === 'none') {
|
if (fullText.style.display === 'none') {
|
||||||
// Show full text
|
|
||||||
longText.style.display = 'none';
|
longText.style.display = 'none';
|
||||||
fullText.style.display = 'inline';
|
fullText.style.display = 'inline';
|
||||||
fullText.classList.add('show');
|
|
||||||
button.textContent = 'Show less';
|
button.textContent = 'Show less';
|
||||||
} else {
|
} else {
|
||||||
// Show truncated text
|
|
||||||
longText.style.display = 'inline';
|
longText.style.display = 'inline';
|
||||||
fullText.style.display = 'none';
|
fullText.style.display = 'none';
|
||||||
fullText.classList.remove('show');
|
|
||||||
button.textContent = 'Show more';
|
button.textContent = 'Show more';
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Function to handle folder metadata editing (placeholder for future implementation)
|
// Initialize folder metadata on page load
|
||||||
function editFolderMetadata() {
|
|
||||||
// For now, just show an alert that this feature is coming soon
|
|
||||||
alert('Folder metadata editing functionality is coming soon!');
|
|
||||||
|
|
||||||
// Future implementation will:
|
|
||||||
// 1. Open an edit modal with form fields for each metadata key
|
|
||||||
// 2. Allow adding/removing metadata fields
|
|
||||||
// 3. Validate the input
|
|
||||||
// 4. Send updates to the server
|
|
||||||
// 5. Refresh the page or update the display dynamically
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize folder metadata functionality when DOM is loaded
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
console.log('Folder metadata functionality initialized');
|
console.log('Folder metadata script loaded');
|
||||||
|
|
||||||
// Add keyboard shortcuts for metadata editing (future feature)
|
// Make sure all containers start collapsed
|
||||||
document.addEventListener('keydown', function(e) {
|
const containers = document.querySelectorAll('.folder-metadata-container');
|
||||||
// Ctrl+M for metadata editing
|
console.log('Found', containers.length, 'metadata containers');
|
||||||
if (e.ctrlKey && e.key === 'm') {
|
|
||||||
e.preventDefault();
|
containers.forEach(container => {
|
||||||
const editBtn = document.querySelector('.folder-metadata-edit-btn');
|
const content = container.querySelector('.folder-metadata-content');
|
||||||
if (editBtn) {
|
if (content) {
|
||||||
editFolderMetadata();
|
// Force initial hidden state
|
||||||
}
|
container.classList.remove('expanded');
|
||||||
|
content.style.display = 'none';
|
||||||
|
console.log('Initialized container as collapsed');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add accessibility improvements
|
|
||||||
const metadataItems = document.querySelectorAll('.folder-metadata-item');
|
|
||||||
metadataItems.forEach(item => {
|
|
||||||
item.setAttribute('tabindex', '0');
|
|
||||||
item.setAttribute('role', 'listitem');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add ARIA labels for better accessibility
|
|
||||||
const metadataContainer = document.querySelector('.folder-metadata-container');
|
|
||||||
if (metadataContainer) {
|
|
||||||
metadataContainer.setAttribute('role', 'region');
|
|
||||||
metadataContainer.setAttribute('aria-label', 'Folder metadata information');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* Simple Metadata Section Toggle
|
||||||
|
*
|
||||||
|
* Handles showing/hiding the metadata grid with a simple button
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Global function to toggle metadata section visibility
|
||||||
|
function toggleMetadataSection() {
|
||||||
|
console.log('toggleMetadataSection called');
|
||||||
|
|
||||||
|
const content = document.getElementById('metadataContent');
|
||||||
|
const arrow = document.getElementById('metadataArrow');
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
console.log('No metadata content found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isVisible = content.style.display !== 'none';
|
||||||
|
|
||||||
|
if (isVisible) {
|
||||||
|
// Hide the content
|
||||||
|
content.style.display = 'none';
|
||||||
|
if (arrow) arrow.textContent = '▼';
|
||||||
|
console.log('Metadata hidden');
|
||||||
|
} else {
|
||||||
|
// Show the content
|
||||||
|
content.style.display = 'block';
|
||||||
|
if (arrow) arrow.textContent = '▲';
|
||||||
|
console.log('Metadata shown');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save state to localStorage
|
||||||
|
localStorage.setItem('metadataVisible', (!isVisible).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to expand long text
|
||||||
|
function expandText(button) {
|
||||||
|
const longText = button.previousElementSibling;
|
||||||
|
const fullText = button.nextElementSibling;
|
||||||
|
|
||||||
|
if (fullText.style.display === 'none') {
|
||||||
|
longText.style.display = 'none';
|
||||||
|
fullText.style.display = 'inline';
|
||||||
|
button.textContent = 'Show less';
|
||||||
|
} else {
|
||||||
|
longText.style.display = 'inline';
|
||||||
|
fullText.style.display = 'none';
|
||||||
|
button.textContent = 'Show more';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize on page load
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
console.log('Metadata section script loaded');
|
||||||
|
|
||||||
|
const content = document.getElementById('metadataContent');
|
||||||
|
if (content) {
|
||||||
|
// Check if user previously had it expanded
|
||||||
|
const wasVisible = localStorage.getItem('metadataVisible') === 'true';
|
||||||
|
|
||||||
|
if (wasVisible) {
|
||||||
|
content.style.display = 'block';
|
||||||
|
const arrow = document.getElementById('metadataArrow');
|
||||||
|
if (arrow) arrow.textContent = '▲';
|
||||||
|
} else {
|
||||||
|
content.style.display = 'none';
|
||||||
|
const arrow = document.getElementById('metadataArrow');
|
||||||
|
if (arrow) arrow.textContent = '▼';
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Metadata section initialized, visible:', wasVisible);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# Example folder metadata file
|
|
||||||
# This file should be named "meta.yaml" in a folder containing plots
|
|
||||||
|
|
||||||
# Folder-level metadata that applies to all plots in this folder
|
|
||||||
title: "Analysis Results"
|
|
||||||
description: "ttbar"
|
|
||||||
experiment: "CMS"
|
|
||||||
dataset: "Run2_2016_nano_v9"
|
|
||||||
analysis_type: "ttbar_analysis"
|
|
||||||
|
|
||||||
# Analysis parameters that apply to all plots in this folder
|
|
||||||
parameters:
|
|
||||||
luminosity: "35.9 fb^-1"
|
|
||||||
center_of_mass_energy: "13 TeV"
|
|
||||||
selection: "baseline"
|
|
||||||
|
|
||||||
# Tags for categorization
|
|
||||||
tags:
|
|
||||||
- "ttbar"
|
|
||||||
- "run2"
|
|
||||||
- "cms"
|
|
||||||
- "analysis"
|
|
||||||
|
|
||||||
# Custom styling or display options
|
|
||||||
display:
|
|
||||||
highlight: true
|
|
||||||
category: "primary_results"
|
|
||||||
order_priority: 1
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "Sample Research Project",
|
|
||||||
"description": "This folder contains plots and analysis results for our sample research project studying data visualization techniques.",
|
|
||||||
"author": "Research Team",
|
|
||||||
"created": "2025-01-15",
|
|
||||||
"project_id": "PROJ-2025-001",
|
|
||||||
"status": "Active",
|
|
||||||
"tags": ["data-science", "visualization", "research"],
|
|
||||||
"collaborators": ["Alice Smith", "Bob Johnson", "Carol Davis"],
|
|
||||||
"funding": {
|
|
||||||
"agency": "National Science Foundation",
|
|
||||||
"grant_number": "NSF-2025-12345",
|
|
||||||
"amount": "$150,000"
|
|
||||||
},
|
|
||||||
"contact": "research-team@example.com",
|
|
||||||
"repository": "https://github.com/example/sample-project",
|
|
||||||
"documentation": "https://docs.example.com/sample-project",
|
|
||||||
"notes": "This is a long note that demonstrates how the system handles lengthy text content. It should be truncated in the display and allow users to expand it to see the full content. This helps keep the interface clean while still providing access to detailed information when needed."
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "Specific Plot Analysis",
|
|
||||||
"description": "This metadata overrides folder metadata for this specific plot",
|
|
||||||
"plot_type": "histogram",
|
|
||||||
"variables": {
|
|
||||||
"x_axis": "invariant_mass",
|
|
||||||
"y_axis": "events",
|
|
||||||
"units": "GeV"
|
|
||||||
},
|
|
||||||
"selection": "signal_region",
|
|
||||||
"statistics": {
|
|
||||||
"entries": 125000,
|
|
||||||
"mean": 125.3,
|
|
||||||
"std_dev": 2.1
|
|
||||||
},
|
|
||||||
"tags": ["signal", "mass_peak", "important"],
|
|
||||||
"display": {
|
|
||||||
"highlight": true,
|
|
||||||
"featured": true,
|
|
||||||
"order_priority": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+22
-18
@@ -34,36 +34,37 @@
|
|||||||
<!-- Folder Tree -->
|
<!-- Folder Tree -->
|
||||||
<div class="folder-tree" id="folderTree"></div>
|
<div class="folder-tree" id="folderTree"></div>
|
||||||
|
|
||||||
<!-- Folder Metadata Dropdown -->
|
<!-- Folder Metadata Section -->
|
||||||
{% if folder_metadata %}
|
{% if folder_metadata %}
|
||||||
<div class="folder-metadata-container">
|
<div class="metadata-section">
|
||||||
<button class="folder-metadata-toggle" onclick="toggleFolderMetadata()">
|
<button class="metadata-toggle-btn" onclick="toggleMetadataSection()">
|
||||||
<span class="folder-metadata-icon">📋</span>
|
<span class="metadata-icon">📋</span>
|
||||||
<span class="folder-metadata-label">Folder Information</span>
|
<span class="metadata-label">Folder Information</span>
|
||||||
<span class="folder-metadata-arrow">▼</span>
|
<span class="metadata-arrow" id="metadataArrow">▼</span>
|
||||||
</button>
|
</button>
|
||||||
<div class="folder-metadata-content" id="folderMetadataContent">
|
|
||||||
<div class="folder-metadata-grid">
|
<div class="metadata-content" id="metadataContent" style="display: none;">
|
||||||
|
<div class="metadata-grid">
|
||||||
{% for key, value in folder_metadata.items() %}
|
{% for key, value in folder_metadata.items() %}
|
||||||
<div class="folder-metadata-item">
|
<div class="metadata-item">
|
||||||
<span class="folder-metadata-key">{{ key }}:</span>
|
<span class="metadata-key">{{ key }}:</span>
|
||||||
<span class="folder-metadata-value">
|
<span class="metadata-value">
|
||||||
{% if value is string and (value.startswith('http://') or value.startswith('https://')) %}
|
{% if value is string and (value.startswith('http://') or value.startswith('https://')) %}
|
||||||
<a href="{{ value }}" target="_blank" rel="noopener noreferrer">{{ value }}</a>
|
<a href="{{ value }}" target="_blank" rel="noopener noreferrer">{{ value }}</a>
|
||||||
{% elif value is string and value|length > 100 %}
|
{% elif value is string and value|length > 100 %}
|
||||||
<span class="folder-metadata-long-text">{{ value[:100] }}...</span>
|
<span class="metadata-long-text">{{ value[:100] }}...</span>
|
||||||
<button class="folder-metadata-expand" onclick="toggleMetadataText(this)">Show more</button>
|
<button class="metadata-expand" onclick="expandText(this)">Show more</button>
|
||||||
<span class="folder-metadata-full-text" style="display: none;">{{ value }}</span>
|
<span class="metadata-full-text" style="display: none;">{{ value }}</span>
|
||||||
{% elif value is iterable and value is not string and value is not mapping %}
|
{% elif value is iterable and value is not string and value is not mapping %}
|
||||||
<div class="folder-metadata-list">
|
<div class="metadata-list">
|
||||||
{% for item in value %}
|
{% for item in value %}
|
||||||
<span class="folder-metadata-tag">{{ item }}</span>
|
<span class="metadata-tag">{{ item }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% elif value is mapping %}
|
{% elif value is mapping %}
|
||||||
<div class="folder-metadata-nested">
|
<div class="metadata-nested">
|
||||||
{% for subkey, subvalue in value.items() %}
|
{% for subkey, subvalue in value.items() %}
|
||||||
<div class="folder-metadata-nested-item">
|
<div class="metadata-nested-item">
|
||||||
<strong>{{ subkey }}:</strong> {{ subvalue }}
|
<strong>{{ subkey }}:</strong> {{ subvalue }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -309,6 +310,9 @@
|
|||||||
<!-- Metadata Popup Script -->
|
<!-- Metadata Popup Script -->
|
||||||
<script src="{{ assets_path }}/js/metadata-popup.js"></script>
|
<script src="{{ assets_path }}/js/metadata-popup.js"></script>
|
||||||
|
|
||||||
|
<!-- Metadata Section Script -->
|
||||||
|
<script src="{{ assets_path }}/js/metadata-section.js"></script>
|
||||||
|
|
||||||
<!-- Folder Metadata Script -->
|
<!-- Folder Metadata Script -->
|
||||||
<script src="{{ assets_path }}/js/folder-metadata.js"></script>
|
<script src="{{ assets_path }}/js/folder-metadata.js"></script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user