snapshot of https://github.com/seaweedfs/seaweedfs.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
This commit is contained in:
338
weed/admin/static/css/admin.css
Normal file
338
weed/admin/static/css/admin.css
Normal file
@@ -0,0 +1,338 @@
|
||||
/* SeaweedFS Dashboard Custom Styles */
|
||||
|
||||
:root {
|
||||
--navbar-height: 56px;
|
||||
}
|
||||
|
||||
/* Link colors - muted */
|
||||
a {
|
||||
color: #5b7c99;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #4a6a88;
|
||||
}
|
||||
|
||||
/* Sidebar Styles */
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: var(--navbar-height);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
padding: 48px 0 0;
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar-heading {
|
||||
font-size: .75rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover {
|
||||
color: #5b7c99;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active {
|
||||
color: #5b7c99;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover .feather,
|
||||
.sidebar .nav-link.active .feather {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Main content area */
|
||||
main {
|
||||
margin-left: 240px;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.sidebar {
|
||||
top: var(--navbar-height);
|
||||
padding-top: 0;
|
||||
width: 240px;
|
||||
background-color: #f8f9fa !important;
|
||||
z-index: 1050;
|
||||
}
|
||||
.sidebar.show ~ .sidebar-backdrop {
|
||||
display: block;
|
||||
}
|
||||
main {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sidebar backdrop for mobile overlay */
|
||||
.sidebar-backdrop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: var(--navbar-height);
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1040;
|
||||
}
|
||||
|
||||
/* Custom card styles */
|
||||
.border-left-primary {
|
||||
border-left: 0.25rem solid #6b8caf !important;
|
||||
}
|
||||
|
||||
.border-left-success {
|
||||
border-left: 0.25rem solid #5a8a72 !important;
|
||||
}
|
||||
|
||||
.border-left-info {
|
||||
border-left: 0.25rem solid #6a9aaa !important;
|
||||
}
|
||||
|
||||
.border-left-warning {
|
||||
border-left: 0.25rem solid #b8995e !important;
|
||||
}
|
||||
|
||||
.border-left-danger {
|
||||
border-left: 0.25rem solid #a5615c !important;
|
||||
}
|
||||
|
||||
/* Status badges */
|
||||
.badge {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* Muted badge colors - override Bootstrap defaults */
|
||||
.badge.bg-primary,
|
||||
.bg-primary {
|
||||
background-color: #6b8caf !important;
|
||||
}
|
||||
|
||||
.badge.bg-success,
|
||||
.bg-success {
|
||||
background-color: #5a8a72 !important;
|
||||
}
|
||||
|
||||
.badge.bg-info,
|
||||
.bg-info {
|
||||
background-color: #6a9aaa !important;
|
||||
}
|
||||
|
||||
.badge.bg-warning,
|
||||
.bg-warning {
|
||||
background-color: #b8995e !important;
|
||||
}
|
||||
|
||||
.badge.bg-danger,
|
||||
.bg-danger {
|
||||
background-color: #a5615c !important;
|
||||
}
|
||||
|
||||
.badge.bg-secondary,
|
||||
.bg-secondary {
|
||||
background-color: #7a7d85 !important;
|
||||
}
|
||||
|
||||
/* Muted card background colors for text-bg-* utility classes */
|
||||
.text-bg-primary,
|
||||
.card.text-bg-primary {
|
||||
background-color: #6b8caf !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.text-bg-success,
|
||||
.card.text-bg-success {
|
||||
background-color: #5a8a72 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.text-bg-info,
|
||||
.card.text-bg-info {
|
||||
background-color: #6a9aaa !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.text-bg-warning,
|
||||
.card.text-bg-warning {
|
||||
background-color: #b8995e !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.text-bg-danger,
|
||||
.card.text-bg-danger {
|
||||
background-color: #a5615c !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Muted text color utilities */
|
||||
.text-primary {
|
||||
color: #6b8caf !important;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: #5a8a72 !important;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: #6a9aaa !important;
|
||||
}
|
||||
|
||||
.text-warning {
|
||||
color: #b8995e !important;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #a5615c !important;
|
||||
}
|
||||
|
||||
/* Progress bars */
|
||||
.progress {
|
||||
background-color: #f8f9fc;
|
||||
border: 1px solid #e3e6f0;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
.table {
|
||||
color: #5a5c69;
|
||||
}
|
||||
|
||||
.table thead th {
|
||||
vertical-align: bottom;
|
||||
border-bottom: 1px solid #e3e6f0;
|
||||
font-weight: 700;
|
||||
color: #5a5c69;
|
||||
background-color: #f8f9fc;
|
||||
}
|
||||
|
||||
.table-bordered {
|
||||
border: 1px solid #e3e6f0;
|
||||
}
|
||||
|
||||
.table-bordered th,
|
||||
.table-bordered td {
|
||||
border: 1px solid #e3e6f0;
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.card {
|
||||
box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.15) !important;
|
||||
border: 1px solid #e3e6f0;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
background-color: #f8f9fc;
|
||||
border-bottom: 1px solid #e3e6f0;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn-primary {
|
||||
background-color: #6b8caf;
|
||||
border-color: #6b8caf;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #5b7c99;
|
||||
border-color: #5b7c99;
|
||||
}
|
||||
|
||||
/* Text utilities */
|
||||
.text-gray-800 {
|
||||
color: #5a5c69 !important;
|
||||
}
|
||||
|
||||
.text-gray-300 {
|
||||
color: #dddfeb !important;
|
||||
}
|
||||
|
||||
/* Animation for HTMX updates */
|
||||
.htmx-indicator {
|
||||
opacity: 0;
|
||||
transition: opacity 500ms ease-in;
|
||||
}
|
||||
|
||||
.htmx-request .htmx-indicator {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.htmx-request.htmx-indicator {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Loading spinner */
|
||||
.spinner-border-sm {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
/* Custom utilities */
|
||||
.bg-gradient-primary {
|
||||
background: linear-gradient(180deg, #6b8caf 10%, #5b7c99 100%);
|
||||
}
|
||||
|
||||
.shadow {
|
||||
box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.15) !important;
|
||||
}
|
||||
|
||||
/* Navbar user icon color */
|
||||
.navbar-toggler .fa-user {
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
}
|
||||
|
||||
/* Collapsible menu styles */
|
||||
.nav-link[data-bs-toggle="collapse"] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-link[data-bs-toggle="collapse"] .fa-chevron-down {
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.nav-link[data-bs-toggle="collapse"][aria-expanded="true"] .fa-chevron-down {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.nav-link[data-bs-toggle="collapse"]:not(.collapsed) {
|
||||
color: #5b7c99;
|
||||
}
|
||||
|
||||
.nav-link[data-bs-toggle="collapse"]:not(.collapsed) .fa-chevron-down {
|
||||
color: #5b7c99;
|
||||
}
|
||||
|
||||
/* Submenu styles */
|
||||
.nav .nav {
|
||||
border-left: 1px solid #e3e6f0;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.nav .nav .nav-link {
|
||||
font-size: 0.875rem;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.nav .nav .nav-link:hover {
|
||||
background-color: #f8f9fc;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 576px) {
|
||||
.card-body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.h5 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
9
weed/admin/static/css/fontawesome.min.css
vendored
Normal file
9
weed/admin/static/css/fontawesome.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
weed/admin/static/favicon.ico
Normal file
BIN
weed/admin/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
2286
weed/admin/static/js/admin.js
Normal file
2286
weed/admin/static/js/admin.js
Normal file
File diff suppressed because it is too large
Load Diff
7
weed/admin/static/js/bootstrap.bundle.min.js
vendored
Normal file
7
weed/admin/static/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
weed/admin/static/js/htmx.min.js
vendored
Normal file
1
weed/admin/static/js/htmx.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
83
weed/admin/static/js/iam-utils.js
Normal file
83
weed/admin/static/js/iam-utils.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Shared IAM utility functions for the SeaweedFS Admin Dashboard.
|
||||
*/
|
||||
|
||||
// URL prefix helper for subdirectory deployment
|
||||
function iamBasePath(path) {
|
||||
return (window.__BASE_PATH__ || '') + path;
|
||||
}
|
||||
|
||||
// Delete user function
|
||||
async function deleteUser(username) {
|
||||
showDeleteConfirm(username, async function () {
|
||||
try {
|
||||
const encodedUsername = encodeURIComponent(username);
|
||||
const response = await fetch(iamBasePath(`/api/users/${encodedUsername}`), {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
showAlert('User deleted successfully', 'success');
|
||||
setTimeout(() => window.location.reload(), 1000);
|
||||
} else {
|
||||
const error = await response.json().catch(() => ({}));
|
||||
showAlert('Failed to delete user: ' + (error.error || 'Unknown error'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error deleting user:', error);
|
||||
showAlert('Failed to delete user: ' + error.message, 'error');
|
||||
}
|
||||
}, 'Are you sure you want to delete this user? This action cannot be undone.');
|
||||
}
|
||||
|
||||
// Delete group function
|
||||
async function deleteGroup(name) {
|
||||
showDeleteConfirm(name, async function () {
|
||||
try {
|
||||
const encodedName = encodeURIComponent(name);
|
||||
const response = await fetch(iamBasePath(`/api/groups/${encodedName}`), {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
showAlert('Group deleted successfully', 'success');
|
||||
setTimeout(() => window.location.reload(), 1000);
|
||||
} else {
|
||||
const error = await response.json().catch(() => ({}));
|
||||
showAlert('Failed to delete group: ' + (error.error || 'Unknown error'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error deleting group:', error);
|
||||
showAlert('Failed to delete group: ' + error.message, 'error');
|
||||
}
|
||||
}, 'Are you sure you want to delete this group? This action cannot be undone.');
|
||||
}
|
||||
|
||||
// Delete access key function
|
||||
async function deleteAccessKey(username, accessKey) {
|
||||
showDeleteConfirm(accessKey, async function () {
|
||||
try {
|
||||
const encodedUsername = encodeURIComponent(username);
|
||||
const encodedAccessKey = encodeURIComponent(accessKey);
|
||||
const response = await fetch(iamBasePath(`/api/users/${encodedUsername}/access-keys/${encodedAccessKey}`), {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
showAlert('Access key deleted successfully', 'success');
|
||||
// If refreshAccessKeysList exists (in object_store_users.templ), use it
|
||||
if (typeof refreshAccessKeysList === 'function') {
|
||||
refreshAccessKeysList(username);
|
||||
} else {
|
||||
setTimeout(() => window.location.reload(), 1000);
|
||||
}
|
||||
} else {
|
||||
const error = await response.json().catch(() => ({}));
|
||||
showAlert('Failed to delete access key: ' + (error.error || 'Unknown error'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error deleting access key:', error);
|
||||
showAlert('Failed to delete access key: ' + error.message, 'error');
|
||||
}
|
||||
}, 'Are you sure you want to delete this access key?');
|
||||
}
|
||||
394
weed/admin/static/js/modal-alerts.js
Normal file
394
weed/admin/static/js/modal-alerts.js
Normal file
@@ -0,0 +1,394 @@
|
||||
/**
|
||||
* Modal Alerts - Bootstrap Modal replacement for native alert() and confirm()
|
||||
* Fixes Chrome auto-dismiss issue with native dialogs
|
||||
*
|
||||
* Usage:
|
||||
* showAlert('Message', 'success');
|
||||
* showConfirm('Delete this?', function() { });
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// Create and inject modal HTML into page if not already present
|
||||
function ensureModalsExist() {
|
||||
if (document.getElementById('globalAlertModal')) {
|
||||
return; // Already exists
|
||||
}
|
||||
|
||||
const modalsHTML = `
|
||||
<!-- Global Alert Modal -->
|
||||
<div class="modal fade" id="globalAlertModal" tabindex="-1" aria-labelledby="globalAlertModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header" id="globalAlertModalHeader">
|
||||
<h5 class="modal-title" id="globalAlertModalLabel">
|
||||
<i class="fas fa-info-circle me-2" id="globalAlertModalIcon"></i>
|
||||
<span id="globalAlertModalTitle">Notice</span>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" id="globalAlertModalBody">
|
||||
<!-- Message will be inserted here -->
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Global Confirm Modal -->
|
||||
<div class="modal fade" id="globalConfirmModal" tabindex="-1" aria-labelledby="globalConfirmModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-warning">
|
||||
<h5 class="modal-title" id="globalConfirmModalLabel">
|
||||
<i class="fas fa-question-circle me-2"></i><span id="globalConfirmModalTitleText">Confirm Action</span>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" id="globalConfirmModalBody">
|
||||
<!-- Message will be inserted here -->
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="globalConfirmCancelBtn">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" id="globalConfirmOkBtn">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Global Delete Confirm Modal -->
|
||||
<div class="modal fade" id="globalDeleteModal" tabindex="-1" aria-labelledby="globalDeleteModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger text-white">
|
||||
<h5 class="modal-title" id="globalDeleteModalLabel">
|
||||
<i class="fas fa-exclamation-triangle me-2"></i>Confirm Delete
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="mb-2" id="globalDeleteModalMessage">Are you sure you want to delete this item?</p>
|
||||
<p class="mb-0"><strong id="globalDeleteModalItemName"></strong></p>
|
||||
<p class="text-muted small mt-2 mb-0">This action cannot be undone.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" id="globalDeleteConfirmBtn">
|
||||
<i class="fas fa-trash me-1"></i>Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Inject modals at end of body
|
||||
document.body.insertAdjacentHTML('beforeend', modalsHTML);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an alert message using Bootstrap modal
|
||||
* @param {string} message - The message to display
|
||||
* @param {string|object} typeOrOptions - Type ('success', 'error', 'warning', 'info') or options object
|
||||
* @param {string} title - Optional custom title
|
||||
*/
|
||||
window.showAlert = function (message, typeOrOptions, title) {
|
||||
ensureModalsExist();
|
||||
|
||||
let type = 'info';
|
||||
let isHtml = false;
|
||||
|
||||
if (typeof typeOrOptions === 'object' && typeOrOptions !== null) {
|
||||
type = typeOrOptions.type || 'info';
|
||||
isHtml = typeOrOptions.isHtml || false;
|
||||
title = typeOrOptions.title || title;
|
||||
} else if (typeof typeOrOptions === 'string') {
|
||||
type = typeOrOptions;
|
||||
}
|
||||
|
||||
const modal = document.getElementById('globalAlertModal');
|
||||
const header = document.getElementById('globalAlertModalHeader');
|
||||
const titleEl = document.getElementById('globalAlertModalTitle');
|
||||
const bodyEl = document.getElementById('globalAlertModalBody');
|
||||
const iconEl = document.getElementById('globalAlertModalIcon');
|
||||
|
||||
// Configuration for different types
|
||||
const types = {
|
||||
'success': {
|
||||
title: 'Success',
|
||||
icon: 'fa-check-circle',
|
||||
headerClass: 'bg-success text-white',
|
||||
btnClose: 'btn-close-white'
|
||||
},
|
||||
'error': {
|
||||
title: 'Error',
|
||||
icon: 'fa-exclamation-triangle',
|
||||
headerClass: 'bg-danger text-white',
|
||||
btnClose: 'btn-close-white'
|
||||
},
|
||||
'warning': {
|
||||
title: 'Warning',
|
||||
icon: 'fa-exclamation-circle',
|
||||
headerClass: 'bg-warning text-dark',
|
||||
btnClose: ''
|
||||
},
|
||||
'info': {
|
||||
title: 'Notice',
|
||||
icon: 'fa-info-circle',
|
||||
headerClass: 'bg-info text-white',
|
||||
btnClose: 'btn-close-white'
|
||||
}
|
||||
};
|
||||
|
||||
const config = types[type] || types['info'];
|
||||
|
||||
// Update header styling
|
||||
header.className = 'modal-header ' + config.headerClass;
|
||||
const closeBtn = header.querySelector('.btn-close');
|
||||
closeBtn.className = 'btn-close ' + config.btnClose;
|
||||
|
||||
// Update icon
|
||||
iconEl.className = 'fas ' + config.icon + ' me-2';
|
||||
|
||||
// Update title
|
||||
titleEl.textContent = title || config.title;
|
||||
|
||||
// Update body - support HTML or text
|
||||
if (isHtml || message.includes('<p>') || message.includes('<ul>')) {
|
||||
bodyEl.innerHTML = message;
|
||||
} else {
|
||||
bodyEl.innerHTML = '<p class="mb-0">' + escapeHtml(message) + '</p>';
|
||||
}
|
||||
|
||||
// Show modal
|
||||
const bsModal = new bootstrap.Modal(modal);
|
||||
bsModal.show();
|
||||
};
|
||||
|
||||
/**
|
||||
* Show a transient message that does not have to be dismissed
|
||||
* @param {string} message - The message to display
|
||||
* @param {string} type - Bootstrap contextual color, defaults to 'success'
|
||||
*/
|
||||
window.showToast = function (message, type) {
|
||||
let container = document.getElementById('globalToastContainer');
|
||||
if (!container) {
|
||||
container = document.createElement('div');
|
||||
container.id = 'globalToastContainer';
|
||||
container.className = 'toast-container position-fixed top-0 end-0 p-3';
|
||||
// Above any modal, however deeply they are stacked.
|
||||
container.style.zIndex = '9999';
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
const toast = document.createElement('div');
|
||||
toast.className = 'toast align-items-center text-white bg-' + (type || 'success') + ' border-0';
|
||||
toast.setAttribute('role', 'alert');
|
||||
toast.innerHTML = '<div class="d-flex"><div class="toast-body">' + escapeHtml(message) + '</div>' +
|
||||
'<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button></div>';
|
||||
container.appendChild(toast);
|
||||
|
||||
toast.addEventListener('hidden.bs.toast', function () {
|
||||
toast.remove();
|
||||
});
|
||||
|
||||
new bootstrap.Toast(toast, { delay: 3000 }).show();
|
||||
};
|
||||
|
||||
/**
|
||||
* Show a confirmation dialog using Bootstrap modal
|
||||
* @param {string} message - The confirmation message
|
||||
* @param {function} onConfirm - Callback function if user confirms
|
||||
* @param {function|object} onCancelOrOptions - Optional callback or options object
|
||||
* @param {string} title - Optional custom title
|
||||
*/
|
||||
window.showConfirm = function (message, onConfirm, onCancelOrOptions, title) {
|
||||
ensureModalsExist();
|
||||
|
||||
let onCancel = null;
|
||||
let isHtml = false;
|
||||
|
||||
if (typeof onCancelOrOptions === 'object' && onCancelOrOptions !== null) {
|
||||
onCancel = onCancelOrOptions.onCancel;
|
||||
isHtml = onCancelOrOptions.isHtml || false;
|
||||
title = onCancelOrOptions.title || null;
|
||||
} else {
|
||||
onCancel = onCancelOrOptions;
|
||||
}
|
||||
|
||||
const modalEl = document.getElementById('globalConfirmModal');
|
||||
const bodyEl = document.getElementById('globalConfirmModalBody');
|
||||
const titleEl = document.getElementById('globalConfirmModalTitleText');
|
||||
const okBtn = document.getElementById('globalConfirmOkBtn');
|
||||
const cancelBtn = document.getElementById('globalConfirmCancelBtn');
|
||||
|
||||
// Set title
|
||||
if (title) {
|
||||
titleEl.textContent = title;
|
||||
} else {
|
||||
titleEl.textContent = 'Confirm Action';
|
||||
}
|
||||
|
||||
// Set message
|
||||
if (isHtml || message.includes('<p>') || message.includes('<ul>')) {
|
||||
bodyEl.innerHTML = message;
|
||||
} else {
|
||||
bodyEl.innerHTML = '<p class="mb-0">' + escapeHtml(message) + '</p>';
|
||||
}
|
||||
|
||||
// Remove old event listeners by cloning buttons
|
||||
const newOkBtn = okBtn.cloneNode(true);
|
||||
const newCancelBtn = cancelBtn.cloneNode(true);
|
||||
okBtn.parentNode.replaceChild(newOkBtn, okBtn);
|
||||
cancelBtn.parentNode.replaceChild(newCancelBtn, cancelBtn);
|
||||
|
||||
const modal = new bootstrap.Modal(modalEl);
|
||||
|
||||
// Add event listeners
|
||||
newOkBtn.addEventListener('click', function () {
|
||||
modal.hide();
|
||||
if (typeof onConfirm === 'function') {
|
||||
onConfirm();
|
||||
}
|
||||
});
|
||||
|
||||
newCancelBtn.addEventListener('click', function () {
|
||||
modal.hide();
|
||||
if (typeof onCancel === 'function') {
|
||||
onCancel();
|
||||
}
|
||||
});
|
||||
|
||||
modal.show();
|
||||
};
|
||||
|
||||
/**
|
||||
* Show a delete confirmation dialog
|
||||
* @param {string} itemName - Name of the item to delete
|
||||
* @param {function} onConfirm - Callback function if user confirms deletion
|
||||
* @param {string} message - Optional custom message (default: "Are you sure you want to delete this item?")
|
||||
*/
|
||||
window.showDeleteConfirm = function (itemName, onConfirm, message) {
|
||||
ensureModalsExist();
|
||||
|
||||
const modalEl = document.getElementById('globalDeleteModal');
|
||||
const messageEl = document.getElementById('globalDeleteModalMessage');
|
||||
const itemNameEl = document.getElementById('globalDeleteModalItemName');
|
||||
const confirmBtn = document.getElementById('globalDeleteConfirmBtn');
|
||||
|
||||
// Set custom message if provided
|
||||
if (message) {
|
||||
messageEl.textContent = message;
|
||||
} else {
|
||||
messageEl.textContent = 'Are you sure you want to delete this item?';
|
||||
}
|
||||
|
||||
// Set item name
|
||||
itemNameEl.textContent = itemName;
|
||||
|
||||
// Remove old event listener by cloning button
|
||||
const newConfirmBtn = confirmBtn.cloneNode(true);
|
||||
confirmBtn.parentNode.replaceChild(newConfirmBtn, confirmBtn);
|
||||
|
||||
const modal = new bootstrap.Modal(modalEl);
|
||||
|
||||
// Add new event listener
|
||||
newConfirmBtn.addEventListener('click', function () {
|
||||
modal.hide();
|
||||
if (typeof onConfirm === 'function') {
|
||||
onConfirm();
|
||||
}
|
||||
});
|
||||
|
||||
modal.show();
|
||||
};
|
||||
|
||||
/**
|
||||
* Escape HTML to prevent XSS
|
||||
*/
|
||||
function escapeHtml(text) {
|
||||
const map = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
};
|
||||
return text.replace(/[&<>"']/g, function (m) { return map[m]; });
|
||||
}
|
||||
|
||||
// Bootstrap gives every modal and backdrop the same z-index, so a modal
|
||||
// opened while another one is showing paints behind it and cannot be
|
||||
// clicked. Lift each nested modal, and its backdrop, above what is already
|
||||
// on screen.
|
||||
const MODAL_Z_INDEX = 1055;
|
||||
const MODAL_Z_INDEX_STEP = 20;
|
||||
|
||||
document.addEventListener('show.bs.modal', function (event) {
|
||||
const depth = document.querySelectorAll('.modal.show').length;
|
||||
if (depth === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const zIndex = MODAL_Z_INDEX + depth * MODAL_Z_INDEX_STEP;
|
||||
event.target.style.zIndex = zIndex;
|
||||
|
||||
// Bootstrap only creates the backdrop after this event returns.
|
||||
setTimeout(function () {
|
||||
const backdrops = document.querySelectorAll('.modal-backdrop');
|
||||
const backdrop = backdrops[backdrops.length - 1];
|
||||
if (backdrop) {
|
||||
backdrop.style.zIndex = zIndex - 1;
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
|
||||
document.addEventListener('hidden.bs.modal', function (event) {
|
||||
event.target.style.zIndex = '';
|
||||
// Closing any modal releases the scroll lock the others still need.
|
||||
if (document.querySelector('.modal.show')) {
|
||||
document.body.classList.add('modal-open');
|
||||
}
|
||||
});
|
||||
|
||||
// Auto-initialize on DOMContentLoaded
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', ensureModalsExist);
|
||||
} else {
|
||||
ensureModalsExist();
|
||||
}
|
||||
|
||||
/**
|
||||
* AUTOMATIC OVERRIDE of native alert()
|
||||
* This makes ALL existing alert() calls automatically use Bootstrap modals
|
||||
*/
|
||||
window.alert = function (message) {
|
||||
// Auto-detect message type from content
|
||||
let type = 'info';
|
||||
const msg = String(message || '');
|
||||
const msgLower = msg.toLowerCase();
|
||||
|
||||
// Refined type inference to avoid false positives
|
||||
if (msgLower.includes('success') || msgLower.includes('successfully') || msgLower.includes('created') || msgLower.includes('updated') || msgLower.includes('saved')) {
|
||||
// Avoid "not successful"
|
||||
if (!msgLower.includes('not success')) {
|
||||
type = 'success';
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'info') {
|
||||
if (msgLower.includes('error') || msgLower.includes('failed') || msgLower.includes('invalid') || msgLower.includes('exception')) {
|
||||
type = 'error';
|
||||
} else if (msgLower.includes('warning') || msgLower.includes('required') || msgLower.includes('attention')) {
|
||||
type = 'warning';
|
||||
}
|
||||
}
|
||||
|
||||
showAlert(msg, type);
|
||||
};
|
||||
|
||||
console.log('Modal Alerts library loaded - native alert() overridden');
|
||||
})();
|
||||
1003
weed/admin/static/js/policy_editor.js
Normal file
1003
weed/admin/static/js/policy_editor.js
Normal file
File diff suppressed because it is too large
Load Diff
1174
weed/admin/static/js/s3tables.js
Normal file
1174
weed/admin/static/js/s3tables.js
Normal file
File diff suppressed because it is too large
Load Diff
BIN
weed/admin/static/webfonts/fa-brands-400.woff2
Normal file
BIN
weed/admin/static/webfonts/fa-brands-400.woff2
Normal file
Binary file not shown.
BIN
weed/admin/static/webfonts/fa-regular-400.ttf
Normal file
BIN
weed/admin/static/webfonts/fa-regular-400.ttf
Normal file
Binary file not shown.
BIN
weed/admin/static/webfonts/fa-regular-400.woff2
Normal file
BIN
weed/admin/static/webfonts/fa-regular-400.woff2
Normal file
Binary file not shown.
Reference in New Issue
Block a user