Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cursor/rules/django_javascript_implementation.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ alwaysApply: true
- HTML fragments that may change throughout the page lifecycle should be created as django template files under `components/`
- Any variables within those components should be handled in the Javascript handlers/managers and passed as context objects to the Django view `RenderHTMLFragmentView` which renders the Django template files in `components/`using a context object passed into a Javascript `APIClient` call.
- Never try to render HTML fragments in Javascript.
- Where appropriate, use programmatic DOM construction through the JS DOM APIs instead of HTML template literals in Javascript. All user defined inputs should be passed to the DOM as text strings (e.g. using `textContent`, `document.createTextNode()`, `String()` when setting user defined values/attributes/text).
Original file line number Diff line number Diff line change
Expand Up @@ -629,11 +629,10 @@ def test_get_dataset_files_missing_uuid(self):
assert response.status_code == status.HTTP_404_NOT_FOUND

def test_get_dataset_files_unauthenticated_access(self):
"""Test access without authentication."""
self.client.force_authenticate(user=None)

"""Test access without API key (no forced user on test client)."""
url = reverse("api:datasets-files", kwargs={"pk": self.dataset.uuid})
response = self.client.get(url)
unauthenticated_client = APIClient()
response = unauthenticated_client.get(url)

assert response.status_code == status.HTTP_401_UNAUTHORIZED

Expand Down
13 changes: 1 addition & 12 deletions gateway/sds_gateway/static/css/components.css
Original file line number Diff line number Diff line change
Expand Up @@ -1127,21 +1127,10 @@ body {
border-radius: 0.375rem;
}

#file-tree-table {
#file-tree-root {
margin-bottom: 0;
}

#file-tree-table thead.sticky-top {
position: sticky;
top: 0;
z-index: 2;
background-color: var(--bs-white);
}

#file-tree-table tbody tr:hover {
cursor: pointer;
}

.action-buttons {
display: flex;
gap: 0.5rem;
Expand Down
110 changes: 110 additions & 0 deletions gateway/sds_gateway/static/css/spectrumx_theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,116 @@ textarea:focus-visible {
max-width: 600px;
}

.file-browser-modal {
max-width: none;
width: 100%;
}

/* Modal file picker: compact rows, hidden checkboxes, click-to-select */
.file-browser-modal #file-tree-root {
padding-left: 0;
}

.file-browser-modal .file-browser-row {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 0.5rem;
padding: 0.375rem 0.75rem;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.15s ease, color 0.15s ease;
width: 100%;
box-sizing: border-box;
}

.file-browser-modal [role="treeitem"]:focus-visible {
outline: 2px solid #005a9c;
outline-offset: 2px;
}

.file-browser-modal .file-item > .file-browser-row:hover {
background-color: rgba(0, 90, 156, 0.08);
}

.file-browser-modal .file-item.is-selected > .file-browser-row {
background-color: rgba(0, 90, 156, 0.16);
color: #003d6b;
font-weight: 500;
}

.file-browser-modal .file-item.is-selected > .file-browser-row .bi {
color: #005a9c;
}

.file-browser-modal .folder-item > .file-browser-row:hover {
background-color: #e9ecef;
}

.file-browser-modal .folder-item.is-selected > .file-browser-row {
background-color: rgba(0, 90, 156, 0.16);
color: #003d6b;
font-weight: 500;
}

.file-browser-modal .folder-expand-toggle {
display: none;
flex-shrink: 0;
line-height: 1;
color: inherit;
text-decoration: none;
}

.file-browser-modal.folder-selection-mode-active .folder-expand-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
}

.file-browser-modal .folder-expand-icon {
transition: transform 0.15s ease;
}

.file-browser-modal .folder-expand-icon.folder-expand-icon-open {
transform: rotate(90deg);
}

.file-browser-modal .file-item.readonly-row > .file-browser-row {
cursor: not-allowed;
opacity: 0.65;
}

.file-browser-modal .file-item.readonly-row > .file-browser-row:hover {
background-color: transparent;
}

.file-browser-modal .item-content {
display: flex;
align-items: center;
gap: 0.5rem;
flex: 1;
min-width: 0;
justify-content: flex-start;
}

.file-browser-modal .file-browser-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.file-browser-modal .file-checkbox {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}

.file-browser-header {
display: flex;
justify-content: space-between;
Expand Down
2 changes: 1 addition & 1 deletion gateway/sds_gateway/static/js/core/PageLifecycleManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class PageLifecycleManager {
searchFormId: "files-search-form",
searchButtonId: "search-files",
clearButtonId: "clear-files-search",
tableBodyId: "file-tree-table",
tableBodyId: "file-tree-root",
paginationContainerId: "files-pagination",
type: "files",
formHandler: this.datasetModeManager?.getHandler(),
Expand Down
10 changes: 5 additions & 5 deletions gateway/sds_gateway/static/js/dataset/DatasetCreationHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class DatasetCreationHandler extends BaseManager {
searchFormId: "files-search-form",
searchButtonId: "search-files",
clearButtonId: "clear-files-search",
tableBodyId: "file-tree-table",
tableBodyId: "file-tree-root",
paginationContainerId: "files-pagination",
confirmFileSelectionId: "confirm-file-selection",
type: "files",
Expand Down Expand Up @@ -220,7 +220,7 @@ class DatasetCreationHandler extends BaseManager {
initializeFileBrowserModal() {
// Modal file selection handlers
document.addEventListener("change", (e) => {
if (e.target.matches('#file-tree-table input[name="files"]')) {
if (e.target.matches('#file-tree-root input[name="files"]')) {
this.handleModalFileSelection(e.target)
}
})
Expand Down Expand Up @@ -344,7 +344,7 @@ class DatasetCreationHandler extends BaseManager {
*/
handleSelectAllFiles(checked) {
const checkboxes = document.querySelectorAll(
'#file-tree-table input[name="files"]',
'#file-tree-root input[name="files"]',
Comment thread
klpoland marked this conversation as resolved.
)
for (const checkbox of checkboxes) {
checkbox.checked = checked
Expand All @@ -360,7 +360,7 @@ class DatasetCreationHandler extends BaseManager {
"select-all-files-checkbox",
)
const allCheckboxes = document.querySelectorAll(
'#file-tree-table input[name="files"]',
'#file-tree-root input[name="files"]',
)

if (selectAllCheckbox && allCheckboxes.length > 0) {
Expand Down Expand Up @@ -432,7 +432,7 @@ class DatasetCreationHandler extends BaseManager {

// Uncheck all checkboxes in modal if it's open
const checkboxes = document.querySelectorAll(
'#file-tree-table input[name="files"]',
'#file-tree-root input[name="files"]',
)
for (const checkbox of checkboxes) {
checkbox.checked = false
Expand Down
17 changes: 15 additions & 2 deletions gateway/sds_gateway/static/js/dataset/DatasetEditingHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class DatasetEditingHandler extends BaseManager {
searchFormId: "files-search-form",
searchButtonId: "search-files",
clearButtonId: "clear-files-search",
tableBodyId: "file-tree-table",
tableBodyId: "file-tree-root",
paginationContainerId: "files-pagination",
confirmFileSelectionId: "confirm-file-selection",
type: "files",
Expand All @@ -87,6 +87,19 @@ class DatasetEditingHandler extends BaseManager {
this.initialFiles,
)
}

const datasetForm = document.getElementById("datasetForm")
if (datasetForm && !datasetForm.dataset.enterSubmitGuardBound) {
datasetForm.dataset.enterSubmitGuardBound = "true"
datasetForm.addEventListener("submit", (e) => {
e.preventDefault()
})
datasetForm.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
e.preventDefault()
}
Comment thread
klpoland marked this conversation as resolved.
})
}
}

/**
Expand Down Expand Up @@ -562,7 +575,7 @@ class DatasetEditingHandler extends BaseManager {

// Also mark in the search results table if visible
const searchRow = document.querySelector(
`#file-tree-table tr[data-file-id="${fileId}"]`,
`#file-tree-root li[data-file-id="${fileId}"]`,
)
if (searchRow) {
searchRow.classList.add("marked-for-removal")
Expand Down
Loading
Loading