style: upgrade design system to rich dark glassmorphism theme and add Whitenoise static file serving
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 33s
|
|
@ -113,8 +113,9 @@ jobs:
|
||||||
echo "DB_HOST=16.113.106.152" >> .env.beta
|
echo "DB_HOST=16.113.106.152" >> .env.beta
|
||||||
echo "DB_PORT=5432" >> .env.beta
|
echo "DB_PORT=5432" >> .env.beta
|
||||||
|
|
||||||
# ── 6. Run Database Migrations ─────────────────────────────────
|
# ── 6. Run Database Migrations & Collect Static Files ──────────
|
||||||
./venv/bin/python manage.py migrate --database=default --noinput
|
./venv/bin/python manage.py migrate --database=default --noinput
|
||||||
|
./venv/bin/python manage.py collectstatic --noinput
|
||||||
|
|
||||||
# ── 7. Configure and restart Systemd service ───────────────────
|
# ── 7. Configure and restart Systemd service ───────────────────
|
||||||
sudo mv /tmp/shippingservice-beta.service /etc/systemd/system/shippingservice-beta.service
|
sudo mv /tmp/shippingservice-beta.service /etc/systemd/system/shippingservice-beta.service
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@ Django>=5.0,<7.0
|
||||||
requests>=2.31.0
|
requests>=2.31.0
|
||||||
psycopg2-binary>=2.9.0
|
psycopg2-binary>=2.9.0
|
||||||
gunicorn>=21.0.0
|
gunicorn>=21.0.0
|
||||||
|
whitenoise>=6.0.0
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,22 @@
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700;800&display=swap');
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--bg-dark: #0f172a;
|
--bg-dark: #0a0f1d;
|
||||||
--bg-card: #1e293b;
|
--bg-card: rgba(21, 32, 54, 0.7);
|
||||||
--bg-input: #0f172a;
|
--bg-card-hover: rgba(30, 45, 74, 0.85);
|
||||||
--border-color: #334155;
|
--bg-input: #0e172a;
|
||||||
|
--border-color: rgba(255, 255, 255, 0.1);
|
||||||
|
--border-glow: rgba(6, 182, 212, 0.4);
|
||||||
--text-main: #f8fafc;
|
--text-main: #f8fafc;
|
||||||
--text-muted: #94a3b8;
|
--text-muted: #94a3b8;
|
||||||
--accent-cyan: #06b6d4;
|
--accent-cyan: #06b6d4;
|
||||||
--accent-blue: #3b82f6;
|
--accent-blue: #3b82f6;
|
||||||
|
--accent-indigo: #6366f1;
|
||||||
--accent-purple: #8b5cf6;
|
--accent-purple: #8b5cf6;
|
||||||
--accent-pink: #ec4899;
|
--accent-pink: #ec4899;
|
||||||
--accent-green: #10b981;
|
--accent-emerald: #10b981;
|
||||||
--accent-amber: #f59e0b;
|
--accent-amber: #f59e0b;
|
||||||
--accent-red: #ef4444;
|
--accent-rose: #f43f5e;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
@ -23,95 +28,115 @@
|
||||||
body {
|
body {
|
||||||
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
||||||
background-color: var(--bg-dark);
|
background-color: var(--bg-dark);
|
||||||
|
background-image:
|
||||||
|
radial-gradient(at 10% 10%, rgba(6, 182, 212, 0.12) 0px, transparent 50%),
|
||||||
|
radial-gradient(at 90% 90%, rgba(139, 92, 246, 0.12) 0px, transparent 50%),
|
||||||
|
radial-gradient(at 50% 50%, rgba(16, 185, 129, 0.05) 0px, transparent 50%);
|
||||||
|
background-attachment: fixed;
|
||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
line-height: 1.5;
|
line-height: 1.6;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Navbar */
|
/* Navbar Glassmorphism */
|
||||||
.navbar {
|
.navbar {
|
||||||
background: rgba(30, 41, 59, 0.8);
|
background: rgba(10, 15, 29, 0.85);
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(16px);
|
||||||
|
-webkit-backdrop-filter: blur(16px);
|
||||||
border-bottom: 1px solid var(--border-color);
|
border-bottom: 1px solid var(--border-color);
|
||||||
padding: 1rem 2rem;
|
padding: 1.1rem 2.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand {
|
.brand {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.75rem;
|
gap: 0.85rem;
|
||||||
font-weight: 700;
|
font-family: 'Outfit', sans-serif;
|
||||||
font-size: 1.25rem;
|
font-weight: 800;
|
||||||
background: linear-gradient(135deg, var(--accent-cyan), var(--accent-blue));
|
font-size: 1.35rem;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
background: linear-gradient(135deg, #38bdf8, #818cf8, #c084fc);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-tabs {
|
.nav-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.6rem;
|
||||||
|
background: rgba(15, 23, 42, 0.6);
|
||||||
|
padding: 0.35rem;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0.5rem 1.25rem;
|
padding: 0.55rem 1.35rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
font-weight: 5rem;
|
font-weight: 600;
|
||||||
font-size: 0.9rem;
|
font-size: 0.88rem;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.55rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link:hover {
|
.nav-link:hover {
|
||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(255, 255, 255, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link.active {
|
.nav-link.active {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: linear-gradient(135deg, rgba(6, 182, 212, 0.2), rgba(59, 130, 246, 0.2));
|
background: linear-gradient(135deg, rgba(6, 182, 212, 0.25), rgba(99, 102, 241, 0.25));
|
||||||
border: 1px solid rgba(6, 182, 212, 0.4);
|
border: 1px solid rgba(6, 182, 212, 0.4);
|
||||||
|
box-shadow: 0 4px 15px rgba(6, 182, 212, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Layout Container */
|
/* Layout Container */
|
||||||
.container {
|
.container {
|
||||||
max-width: 1400px;
|
max-width: 1440px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 2rem;
|
padding: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-title {
|
.page-title {
|
||||||
font-size: 1.75rem;
|
font-family: 'Outfit', sans-serif;
|
||||||
|
font-size: 2.1rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
|
background: linear-gradient(135deg, #ffffff, #cbd5e1);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-desc {
|
.page-desc {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.95rem;
|
font-size: 1rem;
|
||||||
|
max-width: 900px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grid & Cards */
|
/* Grid & Cards */
|
||||||
.grid-2 {
|
.grid-2 {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: 1.5rem;
|
gap: 1.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
@media (max-width: 1100px) {
|
||||||
.grid-2 {
|
.grid-2 {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
@ -119,160 +144,191 @@ body {
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
background: var(--bg-card);
|
background: var(--bg-card);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 0.75rem;
|
border-radius: 1rem;
|
||||||
padding: 1.5rem;
|
padding: 1.65rem;
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
|
||||||
|
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
border-color: rgba(255, 255, 255, 0.18);
|
||||||
|
box-shadow: 0 14px 35px rgba(0, 0, 0, 0.45);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
font-size: 1.1rem;
|
font-family: 'Outfit', sans-serif;
|
||||||
font-weight: 600;
|
font-size: 1.15rem;
|
||||||
margin-bottom: 1rem;
|
font-weight: 700;
|
||||||
|
color: #f1f5f9;
|
||||||
|
margin-bottom: 1.2rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
border-bottom: 1px solid var(--border-color);
|
border-bottom: 1px solid var(--border-color);
|
||||||
padding-bottom: 0.75rem;
|
padding-bottom: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Form Controls */
|
/* Form Controls */
|
||||||
.form-group {
|
.form-group {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1.15rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-label {
|
.form-label {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 0.85rem;
|
font-size: 0.82rem;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
margin-bottom: 0.35rem;
|
margin-bottom: 0.45rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control, .form-select {
|
.form-control, .form-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: var(--bg-input);
|
background: var(--bg-input);
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.6rem;
|
||||||
padding: 0.6rem 0.85rem;
|
padding: 0.7rem 0.95rem;
|
||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
font-size: 0.9rem;
|
font-size: 0.92rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
transition: border-color 0.2s;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control:focus, .form-select:focus {
|
.form-control:focus, .form-select:focus {
|
||||||
border-color: var(--accent-cyan);
|
border-color: var(--accent-cyan);
|
||||||
box-shadow: 0 0 0 2px rgba(6, 182, 212, 0.2);
|
box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.25);
|
||||||
|
background: #111c33;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea.form-control {
|
textarea.form-control {
|
||||||
font-family: 'Fira Code', monospace;
|
font-family: 'Fira Code', monospace;
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
line-height: 1.4;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
.btn {
|
.btn {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.5rem;
|
gap: 0.55rem;
|
||||||
padding: 0.65rem 1.25rem;
|
padding: 0.72rem 1.4rem;
|
||||||
font-size: 0.9rem;
|
font-size: 0.92rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.6rem;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
background: linear-gradient(135deg, var(--accent-cyan), var(--accent-blue));
|
background: linear-gradient(135deg, var(--accent-cyan), var(--accent-blue));
|
||||||
color: #fff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary:hover {
|
.btn-primary:hover {
|
||||||
opacity: 0.9;
|
transform: translateY(-2px);
|
||||||
transform: translateY(-1px);
|
box-shadow: 0 6px 20px rgba(6, 182, 212, 0.35);
|
||||||
|
opacity: 0.95;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-secondary {
|
.btn-secondary {
|
||||||
background: #334155;
|
background: #334155;
|
||||||
color: #fff;
|
color: #f8fafc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-secondary:hover {
|
.btn-secondary:hover {
|
||||||
background: #475569;
|
background: #475569;
|
||||||
|
transform: translateY(-2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-danger {
|
.btn-danger {
|
||||||
background: var(--accent-red);
|
background: linear-gradient(135deg, var(--accent-rose), #dc2626);
|
||||||
color: #fff;
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(244, 63, 94, 0.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* JSON Output Inspector */
|
/* JSON Output Inspector */
|
||||||
.json-viewer {
|
.json-viewer {
|
||||||
background: #090d16;
|
background: #050914;
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.6rem;
|
||||||
padding: 1rem;
|
padding: 1.1rem;
|
||||||
font-family: 'Fira Code', 'Courier New', monospace;
|
font-family: 'Fira Code', 'Courier New', monospace;
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
color: #38bdf8;
|
color: #38bdf8;
|
||||||
max-height: 400px;
|
max-height: 420px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Table */
|
/* Table */
|
||||||
.data-table {
|
.data-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: separate;
|
||||||
font-size: 0.875rem;
|
border-spacing: 0;
|
||||||
|
font-size: 0.88rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table th {
|
.data-table th {
|
||||||
background: rgba(15, 23, 42, 0.6);
|
background: rgba(15, 23, 42, 0.75);
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 0.75rem 1rem;
|
padding: 0.85rem 1.1rem;
|
||||||
border-bottom: 1px solid var(--border-color);
|
border-bottom: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table td {
|
.data-table td {
|
||||||
padding: 0.75rem 1rem;
|
padding: 0.85rem 1.1rem;
|
||||||
border-bottom: 1px solid rgba(51, 65, 85, 0.4);
|
border-bottom: 1px solid rgba(51, 65, 85, 0.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table tr:hover {
|
.data-table tr:hover {
|
||||||
background: rgba(255, 255, 255, 0.02);
|
background: rgba(255, 255, 255, 0.03);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Badges */
|
/* Badges */
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-block;
|
display: inline-flex;
|
||||||
padding: 0.2rem 0.55rem;
|
align-items: center;
|
||||||
border-radius: 0.35rem;
|
gap: 0.35rem;
|
||||||
|
padding: 0.28rem 0.65rem;
|
||||||
|
border-radius: 0.4rem;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge-success { background: rgba(16, 185, 129, 0.2); color: #34d399; border: 1px solid rgba(16, 185, 129, 0.4); }
|
.badge-success { background: rgba(16, 185, 129, 0.18); color: #34d399; border: 1px solid rgba(16, 185, 129, 0.35); }
|
||||||
.badge-error { background: rgba(239, 68, 68, 0.2); color: #f87171; border: 1px solid rgba(239, 68, 68, 0.4); }
|
.badge-error { background: rgba(244, 63, 94, 0.18); color: #fb7185; border: 1px solid rgba(244, 63, 94, 0.35); }
|
||||||
.badge-forward { background: rgba(59, 130, 246, 0.2); color: #60a5fa; border: 1px solid rgba(59, 130, 246, 0.4); }
|
.badge-forward { background: rgba(59, 130, 246, 0.18); color: #60a5fa; border: 1px solid rgba(59, 130, 246, 0.35); }
|
||||||
.badge-reverse { background: rgba(236, 72, 153, 0.2); color: #f472b6; border: 1px solid rgba(236, 72, 153, 0.4); }
|
.badge-reverse { background: rgba(236, 72, 153, 0.18); color: #f472b6; border: 1px solid rgba(236, 72, 153, 0.35); }
|
||||||
.badge-webhook { background: rgba(139, 92, 246, 0.2); color: #a78bfa; border: 1px solid rgba(139, 92, 246, 0.4); }
|
.badge-webhook { background: rgba(139, 92, 246, 0.18); color: #c084fc; border: 1px solid rgba(139, 92, 246, 0.35); }
|
||||||
|
|
||||||
/* Modal */
|
/* Modal */
|
||||||
.modal {
|
.modal {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0; left: 0; right: 0; bottom: 0;
|
top: 0; left: 0; right: 0; bottom: 0;
|
||||||
background: rgba(0, 0, 0, 0.8);
|
background: rgba(0, 0, 0, 0.82);
|
||||||
backdrop-filter: blur(4px);
|
backdrop-filter: blur(8px);
|
||||||
|
-webkit-backdrop-filter: blur(8px);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -283,12 +339,13 @@ textarea.form-control {
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content {
|
.modal-content {
|
||||||
background: var(--bg-card);
|
background: #111927;
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 0.75rem;
|
border-radius: 1rem;
|
||||||
width: 90%;
|
width: 92%;
|
||||||
max-width: 800px;
|
max-width: 850px;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 1.5rem;
|
padding: 1.8rem;
|
||||||
|
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.6);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ INSTALLED_APPS = [
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
|
@ -137,10 +138,11 @@ USE_I18N = True
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
STATIC_URL = '/static/'
|
||||||
# https://docs.djangoproject.com/en/6.1/howto/static-files/
|
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
||||||
|
STATICFILES_DIRS = [
|
||||||
STATIC_URL = 'static/'
|
os.path.join(BASE_DIR, 'shipping/static'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# Email
|
# Email
|
||||||
|
|
|
||||||
381
staticfiles/admin/css/autocomplete.css
Normal file
|
|
@ -0,0 +1,381 @@
|
||||||
|
select.admin-autocomplete {
|
||||||
|
width: 20em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container {
|
||||||
|
min-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete .select2-selection--single,
|
||||||
|
.select2-container--admin-autocomplete .select2-selection--multiple {
|
||||||
|
min-height: 30px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--focus
|
||||||
|
.select2-selection,
|
||||||
|
.select2-container--admin-autocomplete.select2-container--open
|
||||||
|
.select2-selection {
|
||||||
|
border-color: var(--body-quiet-color);
|
||||||
|
min-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--focus
|
||||||
|
.select2-selection.select2-selection--single,
|
||||||
|
.select2-container--admin-autocomplete.select2-container--open
|
||||||
|
.select2-selection.select2-selection--single {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--focus
|
||||||
|
.select2-selection.select2-selection--multiple,
|
||||||
|
.select2-container--admin-autocomplete.select2-container--open
|
||||||
|
.select2-selection.select2-selection--multiple {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete .select2-selection--single {
|
||||||
|
background-color: var(--body-bg);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--single
|
||||||
|
.select2-selection__rendered {
|
||||||
|
color: var(--body-fg);
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--single
|
||||||
|
.select2-selection__clear {
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--single
|
||||||
|
.select2-selection__placeholder {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--single
|
||||||
|
.select2-selection__arrow {
|
||||||
|
height: 26px;
|
||||||
|
position: absolute;
|
||||||
|
top: 1px;
|
||||||
|
right: 1px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--single
|
||||||
|
.select2-selection__arrow
|
||||||
|
b {
|
||||||
|
border-color: #888 transparent transparent transparent;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 5px 4px 0 4px;
|
||||||
|
height: 0;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -4px;
|
||||||
|
margin-top: -2px;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete[dir="rtl"]
|
||||||
|
.select2-selection--single
|
||||||
|
.select2-selection__clear {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete[dir="rtl"]
|
||||||
|
.select2-selection--single
|
||||||
|
.select2-selection__arrow {
|
||||||
|
left: 1px;
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--disabled
|
||||||
|
.select2-selection--single {
|
||||||
|
background-color: var(--darkened-bg);
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--disabled
|
||||||
|
.select2-selection--single
|
||||||
|
.select2-selection__clear {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--open
|
||||||
|
.select2-selection--single
|
||||||
|
.select2-selection__arrow
|
||||||
|
b {
|
||||||
|
border-color: transparent transparent #888 transparent;
|
||||||
|
border-width: 0 4px 5px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete .select2-selection--multiple {
|
||||||
|
background-color: var(--body-bg);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__rendered {
|
||||||
|
box-sizing: border-box;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 10px 5px 5px;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__rendered
|
||||||
|
li {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__placeholder {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
margin-top: 5px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__clear {
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 5px;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__choice {
|
||||||
|
background-color: var(--darkened-bg);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: default;
|
||||||
|
float: left;
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__choice__remove {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__choice__remove:hover {
|
||||||
|
color: var(--body-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete[dir="rtl"]
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__choice,
|
||||||
|
.select2-container--admin-autocomplete[dir="rtl"]
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__placeholder,
|
||||||
|
.select2-container--admin-autocomplete[dir="rtl"]
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-search--inline {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete[dir="rtl"]
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__choice {
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete[dir="rtl"]
|
||||||
|
.select2-selection--multiple
|
||||||
|
.select2-selection__choice__remove {
|
||||||
|
margin-left: 2px;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--focus
|
||||||
|
.select2-selection--multiple {
|
||||||
|
border: solid var(--body-quiet-color) 1px;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--disabled
|
||||||
|
.select2-selection--multiple {
|
||||||
|
background-color: var(--darkened-bg);
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--disabled
|
||||||
|
.select2-selection__choice__remove {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--open.select2-container--above
|
||||||
|
.select2-selection--single,
|
||||||
|
.select2-container--admin-autocomplete.select2-container--open.select2-container--above
|
||||||
|
.select2-selection--multiple {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete.select2-container--open.select2-container--below
|
||||||
|
.select2-selection--single,
|
||||||
|
.select2-container--admin-autocomplete.select2-container--open.select2-container--below
|
||||||
|
.select2-selection--multiple {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete .select2-search--dropdown {
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-search--dropdown
|
||||||
|
.select2-search__field {
|
||||||
|
background: var(--body-bg);
|
||||||
|
color: var(--body-fg);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-search--inline
|
||||||
|
.select2-search__field {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--body-fg);
|
||||||
|
border: none;
|
||||||
|
outline: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
-webkit-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results
|
||||||
|
> .select2-results__options {
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
color: var(--body-fg);
|
||||||
|
background: var(--body-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete .select2-results__option[role="group"] {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option[aria-disabled="true"] {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option[aria-selected="true"] {
|
||||||
|
background-color: var(--selected-bg);
|
||||||
|
color: var(--body-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__group {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option {
|
||||||
|
margin-left: -1em;
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option {
|
||||||
|
margin-left: -2em;
|
||||||
|
padding-left: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option {
|
||||||
|
margin-left: -3em;
|
||||||
|
padding-left: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option {
|
||||||
|
margin-left: -4em;
|
||||||
|
padding-left: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option
|
||||||
|
.select2-results__option {
|
||||||
|
margin-left: -5em;
|
||||||
|
padding-left: 6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete
|
||||||
|
.select2-results__option--highlighted[aria-selected] {
|
||||||
|
background-color: var(--primary);
|
||||||
|
color: var(--primary-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select2-container--admin-autocomplete .select2-results__group {
|
||||||
|
cursor: default;
|
||||||
|
display: block;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errors .select2-selection {
|
||||||
|
border: 1px solid var(--error-fg);
|
||||||
|
}
|
||||||
1385
staticfiles/admin/css/base.css
Normal file
318
staticfiles/admin/css/changelists.css
Normal file
|
|
@ -0,0 +1,318 @@
|
||||||
|
/* CHANGELISTS */
|
||||||
|
|
||||||
|
#changelist .changelist-form-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .changelist-form-container > div {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .changelist-form-container:not(:has(#changelist-filter)) > div {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .changelist-form-container:has(#changelist-filter) > div {
|
||||||
|
min-width: 0;
|
||||||
|
max-width: calc(100% - 270px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list .hiddenfields {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list .filtered table {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list .filtered {
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list .filtered .results,
|
||||||
|
.filtered #toolbar,
|
||||||
|
.filtered div.xfull {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list .filtered table tbody th {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-form .results {
|
||||||
|
overflow-x: auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .toplinks {
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .changelist-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px;
|
||||||
|
border-top: 1px solid var(--hairline-color);
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .changelist-footer .paginator {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
background: var(--body-bg);
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .paginator {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
background: var(--body-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .paginator ul {
|
||||||
|
padding: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CHANGELIST TABLES */
|
||||||
|
|
||||||
|
#changelist table thead th {
|
||||||
|
padding: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist table thead th.action-checkbox-column {
|
||||||
|
width: 1.5em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist table tbody td.action-checkbox {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist table tfoot {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TOOLBAR */
|
||||||
|
|
||||||
|
#toolbar {
|
||||||
|
padding: 8px 10px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
border-top: 1px solid var(--hairline-color);
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar form input {
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
padding: 5px;
|
||||||
|
color: var(--body-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar #searchbar {
|
||||||
|
height: 1.1875rem;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
padding: 2px 5px;
|
||||||
|
margin: 0;
|
||||||
|
vertical-align: top;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar #searchbar:focus {
|
||||||
|
border-color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar form input[type="submit"] {
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
padding: 4px 8px;
|
||||||
|
margin: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
background: var(--body-bg);
|
||||||
|
box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--body-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar form input[type="submit"]:focus,
|
||||||
|
#toolbar form input[type="submit"]:hover {
|
||||||
|
border-color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-search img {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-search .help {
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FILTER COLUMN */
|
||||||
|
|
||||||
|
#changelist-filter {
|
||||||
|
flex: 0 0 240px;
|
||||||
|
order: 1;
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
border-left: none;
|
||||||
|
margin: 0 0 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
#changelist-filter {
|
||||||
|
border: 1px solid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter h2 {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
padding: 5px 15px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter h3,
|
||||||
|
#changelist-filter details summary {
|
||||||
|
font-weight: 400;
|
||||||
|
padding: 0 15px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter details summary > * {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter details > summary {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter details > summary::-webkit-details-marker {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter details > summary::before {
|
||||||
|
content: "→";
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter details[open] > summary::before {
|
||||||
|
content: "↓";
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter ul {
|
||||||
|
margin: 5px 0;
|
||||||
|
padding: 0 15px 15px;
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter ul:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter li {
|
||||||
|
list-style-type: none;
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter a {
|
||||||
|
display: block;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter summary,
|
||||||
|
#changelist-filter a {
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter li.selected {
|
||||||
|
border-left: 5px solid var(--hairline-color);
|
||||||
|
padding-left: 10px;
|
||||||
|
margin-left: -15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter li.selected a {
|
||||||
|
color: var(--link-selected-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter a:focus,
|
||||||
|
#changelist-filter a:hover,
|
||||||
|
#changelist-filter li.selected a:focus,
|
||||||
|
#changelist-filter li.selected a:hover {
|
||||||
|
color: var(--link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter #changelist-filter-extra-actions {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DATE DRILLDOWN */
|
||||||
|
|
||||||
|
.change-list .toplinks {
|
||||||
|
display: flex;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 3px 17px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list .toplinks a,
|
||||||
|
.change-list .toplinks span {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list .toplinks .date-back {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list .toplinks .date-back:focus,
|
||||||
|
.change-list .toplinks .date-back:hover {
|
||||||
|
color: var(--link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ACTIONS */
|
||||||
|
|
||||||
|
.filtered .actions {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist table input {
|
||||||
|
margin: 0;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Once the :has() pseudo-class is supported by all browsers, the tr.selected
|
||||||
|
selector and the JS adding the class can be removed. */
|
||||||
|
#changelist tbody tr.selected {
|
||||||
|
background-color: var(--selected-row);
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist tbody tr:has(.action-select:checked) {
|
||||||
|
background-color: var(--selected-row);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
#changelist tbody tr.selected {
|
||||||
|
background-color: SelectedItem;
|
||||||
|
}
|
||||||
|
#changelist tbody tr:has(.action-select:checked) {
|
||||||
|
background-color: SelectedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
145
staticfiles/admin/css/dark_mode.css
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--primary: #264b5d;
|
||||||
|
--primary-fg: #f7f7f7;
|
||||||
|
|
||||||
|
--body-fg: #eeeeee;
|
||||||
|
--body-bg: #121212;
|
||||||
|
--body-quiet-color: #d0d0d0;
|
||||||
|
--body-medium-color: #e0e0e0;
|
||||||
|
--body-loud-color: #ffffff;
|
||||||
|
|
||||||
|
--breadcrumbs-link-fg: #e0e0e0;
|
||||||
|
--breadcrumbs-bg: var(--primary);
|
||||||
|
|
||||||
|
--link-fg: #81d4fa;
|
||||||
|
--link-hover-color: #4ac1f7;
|
||||||
|
--link-selected-fg: #6f94c6;
|
||||||
|
|
||||||
|
--hairline-color: #272727;
|
||||||
|
--border-color: #353535;
|
||||||
|
|
||||||
|
--error-fg: #e35f5f;
|
||||||
|
|
||||||
|
--message-debug-bg: #4e4e4e;
|
||||||
|
--message-debug-icon: url(../img/icon-debug-dark.svg);
|
||||||
|
--message-info-bg: #265895;
|
||||||
|
--message-info-icon: url(../img/icon-info-dark.svg);
|
||||||
|
--message-success-bg: #006b1b;
|
||||||
|
--message-success-icon: url(../img/icon-yes-dark.svg);
|
||||||
|
--message-warning-bg: #583305;
|
||||||
|
--message-warning-icon: url(../img/icon-alert-dark.svg);
|
||||||
|
--message-error-bg: #570808;
|
||||||
|
--message-error-icon: url(../img/icon-no-dark.svg);
|
||||||
|
|
||||||
|
--darkened-bg: #212121;
|
||||||
|
--selected-bg: #1b1b1b;
|
||||||
|
--selected-row: #00363a;
|
||||||
|
|
||||||
|
--close-button-bg: #333333;
|
||||||
|
--close-button-hover-bg: #666666;
|
||||||
|
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="dark"] {
|
||||||
|
--primary: #264b5d;
|
||||||
|
--primary-fg: #f7f7f7;
|
||||||
|
|
||||||
|
--body-fg: #eeeeee;
|
||||||
|
--body-bg: #121212;
|
||||||
|
--body-quiet-color: #d0d0d0;
|
||||||
|
--body-medium-color: #e0e0e0;
|
||||||
|
--body-loud-color: #ffffff;
|
||||||
|
|
||||||
|
--breadcrumbs-link-fg: #e0e0e0;
|
||||||
|
--breadcrumbs-bg: var(--primary);
|
||||||
|
|
||||||
|
--link-fg: #81d4fa;
|
||||||
|
--link-hover-color: #4ac1f7;
|
||||||
|
--link-selected-fg: #6f94c6;
|
||||||
|
|
||||||
|
--hairline-color: #272727;
|
||||||
|
--border-color: #353535;
|
||||||
|
|
||||||
|
--error-fg: #e35f5f;
|
||||||
|
|
||||||
|
--message-debug-bg: #4e4e4e;
|
||||||
|
--message-debug-icon: url(../img/icon-debug-dark.svg);
|
||||||
|
--message-info-bg: #265895;
|
||||||
|
--message-info-icon: url(../img/icon-info-dark.svg);
|
||||||
|
--message-success-bg: #006b1b;
|
||||||
|
--message-success-icon: url(../img/icon-yes-dark.svg);
|
||||||
|
--message-warning-bg: #583305;
|
||||||
|
--message-warning-icon: url(../img/icon-alert-dark.svg);
|
||||||
|
--message-error-bg: #570808;
|
||||||
|
--message-error-icon: url(../img/icon-no-dark.svg);
|
||||||
|
|
||||||
|
--darkened-bg: #212121;
|
||||||
|
--selected-bg: #1b1b1b;
|
||||||
|
--selected-row: #00363a;
|
||||||
|
|
||||||
|
--close-button-bg: #333333;
|
||||||
|
--close-button-hover-bg: #666666;
|
||||||
|
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* THEME SWITCH */
|
||||||
|
.theme-toggle {
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-inline-start: 5px;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle svg {
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 1.5rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Fully hide screen reader text so we only show the one matching the current
|
||||||
|
theme.
|
||||||
|
*/
|
||||||
|
.theme-toggle .visually-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="auto"] .theme-toggle .theme-label-when-auto {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="dark"] .theme-toggle .theme-label-when-dark {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="light"] .theme-toggle .theme-label-when-light {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ICONS */
|
||||||
|
.theme-toggle svg.theme-icon-when-auto,
|
||||||
|
.theme-toggle svg.theme-icon-when-dark,
|
||||||
|
.theme-toggle svg.theme-icon-when-light {
|
||||||
|
fill: var(--header-link-color);
|
||||||
|
color: var(--header-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="auto"] .theme-toggle svg.theme-icon-when-auto {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="dark"] .theme-toggle svg.theme-icon-when-dark {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="light"] .theme-toggle svg.theme-icon-when-light {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
30
staticfiles/admin/css/dashboard.css
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
/* DASHBOARD */
|
||||||
|
.dashboard td,
|
||||||
|
.dashboard th {
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard .module table th {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard .module table td {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard .module table td a {
|
||||||
|
display: block;
|
||||||
|
padding-right: 0.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RECENT ACTIONS MODULE */
|
||||||
|
|
||||||
|
.module ul.actionlist {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.actionlist li {
|
||||||
|
list-style-type: none;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
482
staticfiles/admin/css/forms.css
Normal file
|
|
@ -0,0 +1,482 @@
|
||||||
|
/* FORM ROWS */
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row img,
|
||||||
|
.form-row input {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row label input[type="checkbox"] {
|
||||||
|
margin-top: 0;
|
||||||
|
vertical-align: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row select option:checked {
|
||||||
|
background-color: var(--selected-row);
|
||||||
|
color: var(--body-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-row p {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-container div.checkbox {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-multiline {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FORM LABELS */
|
||||||
|
|
||||||
|
legend,
|
||||||
|
label {
|
||||||
|
font-weight: normal;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.required legend,
|
||||||
|
legend.required,
|
||||||
|
.required label,
|
||||||
|
label.required {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RADIO BUTTONS */
|
||||||
|
|
||||||
|
form div.radiolist div {
|
||||||
|
padding-right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form div.radiolist.inline div {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
form div.radiolist label {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form div.radiolist input[type="radio"] {
|
||||||
|
margin: -2px 4px 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form ul.inline {
|
||||||
|
margin-left: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form ul.inline li {
|
||||||
|
float: left;
|
||||||
|
padding-right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIELDSETS */
|
||||||
|
|
||||||
|
fieldset .fieldset-heading,
|
||||||
|
fieldset .inline-heading,
|
||||||
|
:not(.inline-related) .collapse summary {
|
||||||
|
border: 1px solid var(--header-bg);
|
||||||
|
margin: 0;
|
||||||
|
padding: 8px;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
background: var(--header-bg);
|
||||||
|
color: var(--header-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ALIGNED FIELDSETS */
|
||||||
|
|
||||||
|
.aligned fieldset {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned fieldset > div {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned legend {
|
||||||
|
float: inline-start;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned label + p,
|
||||||
|
.aligned .checkbox-row + div.help,
|
||||||
|
.aligned label + div.readonly {
|
||||||
|
padding: 6px 0;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned ul label {
|
||||||
|
display: inline;
|
||||||
|
float: none;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned .form-row input {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colMS .aligned .vLargeTextField,
|
||||||
|
.colMS .aligned .vXMLLargeTextField {
|
||||||
|
width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .aligned div.radiolist {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .aligned fieldset div.help {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .aligned p.help:last-child,
|
||||||
|
form .aligned div.help:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .aligned ul li {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .aligned div.help ul {
|
||||||
|
padding-left: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .aligned table p {
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned .vCheckboxLabel {
|
||||||
|
padding: 1px 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned .vCheckboxLabel + p.help,
|
||||||
|
.aligned .vCheckboxLabel + div.help {
|
||||||
|
margin-top: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colM .aligned .vLargeTextField,
|
||||||
|
.colM .aligned .vXMLLargeTextField {
|
||||||
|
width: 610px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* COLLAPSIBLE FIELDSETS */
|
||||||
|
|
||||||
|
.collapse summary .fieldset-heading,
|
||||||
|
.collapse summary .inline-heading {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: currentColor;
|
||||||
|
display: inline;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MONOSPACE TEXTAREAS */
|
||||||
|
|
||||||
|
fieldset.monospace textarea {
|
||||||
|
font-family: var(--font-family-monospace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SUBMIT ROW */
|
||||||
|
|
||||||
|
.submit-row {
|
||||||
|
padding: 12px 14px 12px;
|
||||||
|
margin: 0 0 20px;
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
border: 1px solid var(--hairline-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.popup .submit-row {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row input {
|
||||||
|
height: 2.1875rem;
|
||||||
|
line-height: 0.9375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row input,
|
||||||
|
.submit-row a {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row input.default {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row a.deletelink {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row a.deletelink {
|
||||||
|
display: block;
|
||||||
|
background: var(--delete-button-bg);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.625rem 0.9375rem;
|
||||||
|
height: 0.9375rem;
|
||||||
|
line-height: 0.9375rem;
|
||||||
|
color: var(--button-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row a.closelink {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--close-button-bg);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
height: 0.9375rem;
|
||||||
|
line-height: 0.9375rem;
|
||||||
|
color: var(--button-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row a.deletelink:focus,
|
||||||
|
.submit-row a.deletelink:hover,
|
||||||
|
.submit-row a.deletelink:active {
|
||||||
|
background: var(--delete-button-hover-bg);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row a.closelink:focus,
|
||||||
|
.submit-row a.closelink:hover,
|
||||||
|
.submit-row a.closelink:active {
|
||||||
|
background: var(--close-button-hover-bg);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CUSTOM FORM FIELDS */
|
||||||
|
|
||||||
|
.vSelectMultipleField {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vCheckboxField {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vDateField,
|
||||||
|
.vTimeField {
|
||||||
|
margin-right: 2px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vDateField {
|
||||||
|
min-width: 6.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vTimeField {
|
||||||
|
min-width: 4.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vURLField {
|
||||||
|
width: 30em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vLargeTextField,
|
||||||
|
.vXMLLargeTextField {
|
||||||
|
width: 48em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-flatpages.model-flatpage #id_content {
|
||||||
|
height: 40.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module table .vPositiveSmallIntegerField {
|
||||||
|
width: 2.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vIntegerField {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vBigIntegerField {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vForeignKeyRawIdAdminField {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vTextField,
|
||||||
|
.vUUIDField {
|
||||||
|
width: 20em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* INLINES */
|
||||||
|
|
||||||
|
.inline-group {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group thead th {
|
||||||
|
padding: 8px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group .aligned label {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-related {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-related h4,
|
||||||
|
.inline-related:not(.tabular) .collapse summary {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--body-medium-color);
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
border: 1px solid var(--hairline-color);
|
||||||
|
border-left-color: var(--darkened-bg);
|
||||||
|
border-right-color: var(--darkened-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-related h3 span.delete {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-related h3 span.delete label {
|
||||||
|
margin-left: 2px;
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-related fieldset {
|
||||||
|
margin: 0;
|
||||||
|
background: var(--body-bg);
|
||||||
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group .tabular fieldset.module {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-related.tabular div.wrapper {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-related.tabular fieldset.module table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.last-related fieldset {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group .tabular tr.has_original td {
|
||||||
|
padding-top: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group .tabular tr td.original {
|
||||||
|
padding: 2px 0 0 0;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group .tabular th.original {
|
||||||
|
width: 0px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group .tabular td {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group .tabular td.original p {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
height: 1.2em;
|
||||||
|
padding: 2px 9px;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group div.add-row,
|
||||||
|
.inline-group .tabular tr.add-row td {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group .tabular tr.add-row td {
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group div.add-row a,
|
||||||
|
.inline-group .tabular tr.add-row td a {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-form {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RELATED FIELD ADD ONE / LOOKUP */
|
||||||
|
|
||||||
|
.related-lookup {
|
||||||
|
margin-left: 5px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-lookup {
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
background-image: url(../img/search.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
form .related-widget-wrapper ul {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .related-widget-wrapper a.change-related img {
|
||||||
|
transform: scale(0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
form .related-widget-wrapper a.view-related img {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearable-file-input input {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
62
staticfiles/admin/css/login.css
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* LOGIN FORM */
|
||||||
|
|
||||||
|
.login {
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #header {
|
||||||
|
height: auto;
|
||||||
|
padding: 15px 16px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #header h1 {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #header h1 a {
|
||||||
|
color: var(--header-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #content {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #container {
|
||||||
|
background: var(--body-bg);
|
||||||
|
border: 1px solid var(--hairline-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 28em;
|
||||||
|
min-width: 300px;
|
||||||
|
margin: 100px auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .form-row {
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .form-row label {
|
||||||
|
display: block;
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .form-row #id_username,
|
||||||
|
.login .form-row #id_password {
|
||||||
|
padding: 8px;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .submit-row {
|
||||||
|
padding: 1em 0 0 0;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .password-reset-link {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
151
staticfiles/admin/css/nav_sidebar.css
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
.sticky {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
max-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-nav-sidebar {
|
||||||
|
z-index: 20;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 0 0 23px;
|
||||||
|
width: 23px;
|
||||||
|
border: 0;
|
||||||
|
border-right: 1px solid var(--hairline-color);
|
||||||
|
background-color: var(--body-bg);
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: var(--link-fg);
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .toggle-nav-sidebar {
|
||||||
|
border-left: 1px solid var(--hairline-color);
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-nav-sidebar:hover,
|
||||||
|
.toggle-nav-sidebar:focus {
|
||||||
|
background-color: var(--darkened-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-sidebar {
|
||||||
|
z-index: 15;
|
||||||
|
flex: 0 0 275px;
|
||||||
|
left: -276px;
|
||||||
|
margin-left: -276px;
|
||||||
|
border-top: 1px solid transparent;
|
||||||
|
border-right: 1px solid var(--hairline-color);
|
||||||
|
background-color: var(--body-bg);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] #nav-sidebar {
|
||||||
|
border-left: 1px solid var(--hairline-color);
|
||||||
|
border-right: 0;
|
||||||
|
left: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
right: -276px;
|
||||||
|
margin-right: -276px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-nav-sidebar::before {
|
||||||
|
content: "\00BB";
|
||||||
|
}
|
||||||
|
|
||||||
|
.main.shifted .toggle-nav-sidebar::before {
|
||||||
|
content: "\00AB";
|
||||||
|
}
|
||||||
|
|
||||||
|
.main > #nav-sidebar {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main.shifted > #nav-sidebar {
|
||||||
|
margin-left: 0;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .main.shifted > #nav-sidebar {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-sidebar .module th {
|
||||||
|
width: 100%;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-sidebar .module th,
|
||||||
|
#nav-sidebar .module caption {
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-sidebar .module td {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] #nav-sidebar .module th,
|
||||||
|
[dir="rtl"] #nav-sidebar .module caption {
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-sidebar .current-app .section:link,
|
||||||
|
#nav-sidebar .current-app .section:visited {
|
||||||
|
color: var(--header-color);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-sidebar .current-model {
|
||||||
|
background: var(--selected-row);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
#nav-sidebar .current-model {
|
||||||
|
background-color: SelectedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main > #nav-sidebar + .content {
|
||||||
|
max-width: calc(100% - 23px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main.shifted > #nav-sidebar + .content {
|
||||||
|
max-width: calc(100% - 299px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
#nav-sidebar,
|
||||||
|
#toggle-nav-sidebar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main > #nav-sidebar + .content,
|
||||||
|
.main.shifted > #nav-sidebar + .content {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-filter {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 2px 5px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
background-color: var(--darkened-bg);
|
||||||
|
color: var(--body-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-filter:focus {
|
||||||
|
border-color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-filter.no-results {
|
||||||
|
background: var(--message-error-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-sidebar table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
857
staticfiles/admin/css/responsive.css
Normal file
|
|
@ -0,0 +1,857 @@
|
||||||
|
/* Tablets */
|
||||||
|
|
||||||
|
input[type="submit"],
|
||||||
|
button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
/* Basic */
|
||||||
|
|
||||||
|
html {
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Layout */
|
||||||
|
|
||||||
|
#container {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
padding: 15px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.breadcrumbs {
|
||||||
|
padding: 10px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
|
||||||
|
#header {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 15px 30px;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#site-name {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#user-tools {
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.85;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#user-tools a {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dashboard */
|
||||||
|
|
||||||
|
.dashboard #content {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content-related {
|
||||||
|
margin-right: -290px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colSM #content-related {
|
||||||
|
margin-left: -290px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colMS {
|
||||||
|
margin-right: 290px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colSM {
|
||||||
|
margin-left: 290px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard .module table td a {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td .changelink,
|
||||||
|
td .addlink {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Changelist */
|
||||||
|
|
||||||
|
#toolbar {
|
||||||
|
border: none;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-search > div {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
max-width: 480px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-search label {
|
||||||
|
line-height: 1.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar form #searchbar {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
width: 0;
|
||||||
|
height: 1.375rem;
|
||||||
|
margin: 0 10px 0 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar form input[type="submit"] {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-search .quiet {
|
||||||
|
width: 0;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
margin: 5px 0 0 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions label {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions select {
|
||||||
|
background: var(--body-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions .button {
|
||||||
|
min-width: 48px;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions span.all,
|
||||||
|
.actions span.clear,
|
||||||
|
.actions span.question,
|
||||||
|
.actions span.action-counter {
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
margin: 0 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter {
|
||||||
|
flex-basis: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list .filtered .results,
|
||||||
|
.change-list .filtered .paginator,
|
||||||
|
.filtered #toolbar,
|
||||||
|
.filtered .actions,
|
||||||
|
#changelist .paginator {
|
||||||
|
border-top-color: var(--hairline-color); /* XXX Is this used at all? */
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .results + .paginator {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms */
|
||||||
|
|
||||||
|
legend,
|
||||||
|
label {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Minifiers remove the default (text) "type" attribute from "input" HTML
|
||||||
|
tags. Add input:not([type]) to make the CSS stylesheet work the same.
|
||||||
|
*/
|
||||||
|
.form-row input:not([type]),
|
||||||
|
.form-row input[type="text"],
|
||||||
|
.form-row input[type="password"],
|
||||||
|
.form-row input[type="email"],
|
||||||
|
.form-row input[type="url"],
|
||||||
|
.form-row input[type="tel"],
|
||||||
|
.form-row input[type="number"],
|
||||||
|
.form-row textarea,
|
||||||
|
.form-row select,
|
||||||
|
.form-row .vTextField {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 6px 8px;
|
||||||
|
min-height: 2.25rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row select {
|
||||||
|
height: 2.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row select[multiple] {
|
||||||
|
height: auto;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned label {
|
||||||
|
padding-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned .related-lookup,
|
||||||
|
.aligned .datetimeshortcuts,
|
||||||
|
.aligned .related-lookup + strong {
|
||||||
|
align-self: center;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .aligned div.radiolist {
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row a.deletelink {
|
||||||
|
padding: 10px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button,
|
||||||
|
input[type="submit"],
|
||||||
|
input[type="button"],
|
||||||
|
.submit-row input,
|
||||||
|
a.button {
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Selector */
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-filter {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-filter input {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-available,
|
||||||
|
.selector-chosen {
|
||||||
|
width: auto;
|
||||||
|
flex: 1 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector select {
|
||||||
|
width: 100%;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-chooseall,
|
||||||
|
.selector-clearall {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked {
|
||||||
|
flex-direction: column;
|
||||||
|
max-width: 480px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked > * {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked select {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-available,
|
||||||
|
.stacked .selector-chosen {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked ul.selector-chooser {
|
||||||
|
padding: 0 2px;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-chooser li {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-tooltip,
|
||||||
|
.selector .help-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetime input {
|
||||||
|
width: 50%;
|
||||||
|
max-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetime span {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetime .timezonewarning {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimeshortcuts {
|
||||||
|
color: var(
|
||||||
|
--border-color
|
||||||
|
); /* XXX Redundant, .datetime span also sets #ccc */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row .datetime input.vDateField,
|
||||||
|
.form-row .datetime input.vTimeField {
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Messages */
|
||||||
|
|
||||||
|
ul.messagelist li {
|
||||||
|
padding: 10px 10px 10px 55px;
|
||||||
|
background-position-x: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login */
|
||||||
|
|
||||||
|
.login #header {
|
||||||
|
padding: 15px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #site-name {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GIS */
|
||||||
|
|
||||||
|
div.olMap {
|
||||||
|
max-width: calc(100vw - 30px);
|
||||||
|
max-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.olMap + .clear_features {
|
||||||
|
display: block;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Docs */
|
||||||
|
|
||||||
|
.module table.xfull {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.literal-block {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile */
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
/* Layout */
|
||||||
|
|
||||||
|
#header,
|
||||||
|
#content {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.breadcrumbs {
|
||||||
|
padding: 10px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dashboard */
|
||||||
|
|
||||||
|
.colMS,
|
||||||
|
.colSM {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content-related,
|
||||||
|
.colSM #content-related {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content-related .module {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content-related .module h2 {
|
||||||
|
padding: 10px 15px;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Changelist */
|
||||||
|
|
||||||
|
#changelist .changelist-form-container {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist .changelist-form-container:has(#changelist-filter) > div {
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions label {
|
||||||
|
flex: 1 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions select {
|
||||||
|
flex: 1 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions span {
|
||||||
|
flex: 1 0 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms */
|
||||||
|
|
||||||
|
.titles-and-tools {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object-tools {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
padding: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned .form-row,
|
||||||
|
.aligned .form-row > div {
|
||||||
|
max-width: 100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned .form-row > div {
|
||||||
|
width: calc(100vw - 30px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-container {
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vURLField {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned .form-row input,
|
||||||
|
.aligned .form-row select,
|
||||||
|
.aligned .form-row textarea {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned .checkbox-row input {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned .vCheckboxLabel {
|
||||||
|
flex: 1 0;
|
||||||
|
padding: 1px 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aligned p.file-upload {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.clearable-file-input {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.clearable-file-input label {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .aligned div.radiolist:not(.inline) div + div {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Related widget */
|
||||||
|
|
||||||
|
.related-widget-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-widget-wrapper .selector {
|
||||||
|
order: 1;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-widget-wrapper > a {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-widget-wrapper .radiolist ~ a {
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-widget-wrapper > select ~ a {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Selector */
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-available,
|
||||||
|
.selector-chosen {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector select {
|
||||||
|
max-height: 96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector ul.selector-chooser {
|
||||||
|
display: flex;
|
||||||
|
width: 60px;
|
||||||
|
height: 30px;
|
||||||
|
padding: 0 2px;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector ul.selector-chooser li {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-remove {
|
||||||
|
background-position: 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-remove:focus,
|
||||||
|
:enabled.selector-remove:hover {
|
||||||
|
background-position: 0 -24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-add {
|
||||||
|
background-position: 0 -48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-add:focus,
|
||||||
|
:enabled.selector-add:hover {
|
||||||
|
background-position: 0 -72px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inlines */
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"] .inline-related {
|
||||||
|
border: 1px solid var(--hairline-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 15px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"] .inline-related > * {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"] .inline-related .module {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"]
|
||||||
|
.inline-related
|
||||||
|
.module
|
||||||
|
.form-row {
|
||||||
|
border-top: 1px solid var(--hairline-color);
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"]
|
||||||
|
.inline-related
|
||||||
|
.module
|
||||||
|
.form-row:first-child {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"] .inline-related h3 {
|
||||||
|
padding: 10px;
|
||||||
|
border-top-width: 0;
|
||||||
|
border-bottom-width: 2px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"] .inline-related h3 .inline_label {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"] .inline-related h3 span.delete {
|
||||||
|
float: none;
|
||||||
|
flex: 1 1 100%;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"]
|
||||||
|
.aligned
|
||||||
|
.form-row
|
||||||
|
> div:not([class]) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"] .aligned label {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group[data-inline-type="stacked"] div.add-row {
|
||||||
|
margin-top: 15px;
|
||||||
|
border: 1px solid var(--hairline-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group div.add-row,
|
||||||
|
.inline-group .tabular tr.add-row td {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group div.add-row a,
|
||||||
|
.inline-group .tabular tr.add-row td a {
|
||||||
|
display: block;
|
||||||
|
padding: 8px 10px 8px 26px;
|
||||||
|
background-position: 8px 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Submit row */
|
||||||
|
|
||||||
|
.submit-row {
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 0 15px;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row input,
|
||||||
|
.submit-row input.default,
|
||||||
|
.submit-row a {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row a.closelink {
|
||||||
|
padding: 10px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row a.deletelink {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Messages */
|
||||||
|
|
||||||
|
ul.messagelist li {
|
||||||
|
padding: 10px 10px 10px 40px;
|
||||||
|
background-position-x: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Paginator */
|
||||||
|
|
||||||
|
.paginator .this-page,
|
||||||
|
.paginator a:link,
|
||||||
|
.paginator a:visited {
|
||||||
|
padding: 4px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login */
|
||||||
|
|
||||||
|
body.login {
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #container {
|
||||||
|
width: auto;
|
||||||
|
max-width: 480px;
|
||||||
|
margin: 50px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #header,
|
||||||
|
.login #content {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #content-main {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .form-row {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .form-row + .form-row {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .form-row label {
|
||||||
|
margin: 0 0 5px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .submit-row {
|
||||||
|
padding: 15px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login br {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .submit-row input {
|
||||||
|
margin: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errornote {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calendar and clock */
|
||||||
|
|
||||||
|
.calendarbox,
|
||||||
|
.clockbox {
|
||||||
|
position: fixed !important;
|
||||||
|
top: 50% !important;
|
||||||
|
left: 50% !important;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarbox > *,
|
||||||
|
.clockbox > * {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarbox > div:first-child {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarbox .calendar,
|
||||||
|
.clockbox h2 {
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarbox .calendar-cancel,
|
||||||
|
.clockbox .calendar-cancel {
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-shortcuts {
|
||||||
|
padding: 10px 0;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-shortcuts a {
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timelist a {
|
||||||
|
background: var(--body-bg);
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-cancel {
|
||||||
|
padding: 8px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clockbox h2 {
|
||||||
|
padding: 8px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar caption {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarbox .calendarnav-previous,
|
||||||
|
.calendarbox .calendarnav-next {
|
||||||
|
z-index: 1;
|
||||||
|
top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* History */
|
||||||
|
|
||||||
|
table#change-history tbody th,
|
||||||
|
table#change-history tbody td {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
table#change-history tbody th {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Docs */
|
||||||
|
|
||||||
|
table.model tbody th,
|
||||||
|
table.model tbody td {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
82
staticfiles/admin/css/responsive_rtl.css
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* TABLETS */
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
[dir="rtl"] .colMS {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] #user-tools {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .actions label {
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .actions select {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .change-list .filtered .results,
|
||||||
|
[dir="rtl"] .change-list .filtered .paginator,
|
||||||
|
[dir="rtl"] .filtered #toolbar,
|
||||||
|
[dir="rtl"] .filtered div.xfull,
|
||||||
|
[dir="rtl"] .filtered .actions,
|
||||||
|
[dir="rtl"] #changelist-filter {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .inline-group div.add-row a,
|
||||||
|
[dir="rtl"] .inline-group .tabular tr.add-row td a {
|
||||||
|
padding: 8px 26px 8px 10px;
|
||||||
|
background-position: calc(100% - 8px) 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .dashboard .module table td a {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] ul.messagelist li {
|
||||||
|
padding: 10px 55px 10px 10px;
|
||||||
|
background-position-x: calc(100% - 30px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MOBILE */
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
[dir="rtl"] #changelist-filter {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .aligned .vCheckboxLabel {
|
||||||
|
padding: 1px 5px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .selector-remove {
|
||||||
|
background-position: 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] :enabled.selector-remove:focus,
|
||||||
|
:enabled.selector-remove:hover {
|
||||||
|
background-position: 0 -24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .selector-add {
|
||||||
|
background-position: 0 -48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] :enabled.selector-add:focus,
|
||||||
|
:enabled.selector-add:hover {
|
||||||
|
background-position: 0 -72px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] ul.messagelist li {
|
||||||
|
padding: 10px 40px 10px 10px;
|
||||||
|
background-position-x: calc(100% - 15px);
|
||||||
|
}
|
||||||
|
}
|
||||||
245
staticfiles/admin/css/rtl.css
Normal file
|
|
@ -0,0 +1,245 @@
|
||||||
|
/* GLOBAL */
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module h2,
|
||||||
|
.module caption {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module ul,
|
||||||
|
.module ol {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewlink,
|
||||||
|
.addlink,
|
||||||
|
.changelink,
|
||||||
|
.hidelink {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 16px;
|
||||||
|
background-position-x: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deletelink {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 16px;
|
||||||
|
background-position: 100% 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object-tools li + li {
|
||||||
|
margin-right: 15px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead th:first-child,
|
||||||
|
tfoot td:first-child {
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LAYOUT */
|
||||||
|
|
||||||
|
#user-tools {
|
||||||
|
right: auto;
|
||||||
|
left: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.breadcrumbs {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content-main {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content-related {
|
||||||
|
float: left;
|
||||||
|
margin-left: -300px;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colMS {
|
||||||
|
margin-left: 300px;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SORTABLE TABLES */
|
||||||
|
|
||||||
|
table thead th.sorted .sortoptions {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead th.sorted .text {
|
||||||
|
padding-right: 0;
|
||||||
|
padding-left: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dashboard styles */
|
||||||
|
|
||||||
|
.dashboard .module table td a {
|
||||||
|
padding-left: 0.6em;
|
||||||
|
padding-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* changelists styles */
|
||||||
|
|
||||||
|
.change-list .filtered table {
|
||||||
|
border-left: none;
|
||||||
|
border-right: 0px none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter {
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist-filter li.selected {
|
||||||
|
border-left: none;
|
||||||
|
padding-left: 10px;
|
||||||
|
margin-left: 0;
|
||||||
|
border-right: 5px solid var(--hairline-color);
|
||||||
|
padding-right: 10px;
|
||||||
|
margin-right: -15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#changelist table tbody td:first-child,
|
||||||
|
#changelist table tbody th:first-child {
|
||||||
|
border-right: none;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginator ul {
|
||||||
|
margin-left: 6px;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginator input {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FORMS */
|
||||||
|
|
||||||
|
form .aligned ul {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form ul.inline li {
|
||||||
|
float: right;
|
||||||
|
padding-right: 0;
|
||||||
|
padding-left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-row {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WIDGETS */
|
||||||
|
|
||||||
|
.calendarnav-previous {
|
||||||
|
top: 0;
|
||||||
|
left: auto;
|
||||||
|
right: 10px;
|
||||||
|
background: url(../img/calendar-icons.svg) 0 -15px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarnav-next {
|
||||||
|
top: 0;
|
||||||
|
right: auto;
|
||||||
|
left: 10px;
|
||||||
|
background: url(../img/calendar-icons.svg) 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar caption,
|
||||||
|
.calendarbox h2 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-filter {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-add {
|
||||||
|
background: url(../img/selector-icons.svg) 0 -96px no-repeat;
|
||||||
|
background-size: 24px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-add:focus,
|
||||||
|
:enabled.selector-add:hover {
|
||||||
|
background-position: 0 -120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-remove {
|
||||||
|
background: url(../img/selector-icons.svg) 0 -144px no-repeat;
|
||||||
|
background-size: 24px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-remove:focus,
|
||||||
|
:enabled.selector-remove:hover {
|
||||||
|
background-position: 0 -168px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-chooseall:focus,
|
||||||
|
:enabled.selector-chooseall:hover {
|
||||||
|
background-position: 100% -144px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-clearall:focus,
|
||||||
|
:enabled.selector-clearall:hover {
|
||||||
|
background-position: 0 -176px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-deletelink {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-row p.datetime {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-widget-wrapper {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MISC */
|
||||||
|
|
||||||
|
.inline-related h2,
|
||||||
|
.inline-group h2 {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-related h3 span.delete {
|
||||||
|
padding-right: 20px;
|
||||||
|
padding-left: inherit;
|
||||||
|
left: 10px;
|
||||||
|
right: inherit;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-related h3 span.delete label {
|
||||||
|
margin-left: inherit;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group .tabular td.original p {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-chooser {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.messagelist li {
|
||||||
|
padding: 10px 65px 10px 10px;
|
||||||
|
background-position-x: calc(100% - 40px);
|
||||||
|
}
|
||||||
21
staticfiles/admin/css/unusable_password_field.css
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
/* Hide warnings fields if usable password is selected */
|
||||||
|
form:has(#id_usable_password input[value="true"]:checked) .messagelist {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide password fields if unusable password is selected */
|
||||||
|
form:has(#id_usable_password input[value="false"]:checked) .field-password1,
|
||||||
|
form:has(#id_usable_password input[value="false"]:checked) .field-password2 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select appropriate submit button */
|
||||||
|
form:has(#id_usable_password input[value="true"]:checked)
|
||||||
|
input[type="submit"].unset-password {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
form:has(#id_usable_password input[value="false"]:checked)
|
||||||
|
input[type="submit"].set-password {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
21
staticfiles/admin/css/vendor/select2/LICENSE-SELECT2.md
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
481
staticfiles/admin/css/vendor/select2/select2.css
vendored
Normal file
|
|
@ -0,0 +1,481 @@
|
||||||
|
.select2-container {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle; }
|
||||||
|
.select2-container .select2-selection--single {
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
height: 28px;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none; }
|
||||||
|
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||||
|
display: block;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap; }
|
||||||
|
.select2-container .select2-selection--single .select2-selection__clear {
|
||||||
|
position: relative; }
|
||||||
|
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
|
||||||
|
padding-right: 8px;
|
||||||
|
padding-left: 20px; }
|
||||||
|
.select2-container .select2-selection--multiple {
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
min-height: 32px;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none; }
|
||||||
|
.select2-container .select2-selection--multiple .select2-selection__rendered {
|
||||||
|
display: inline-block;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-left: 8px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap; }
|
||||||
|
.select2-container .select2-search--inline {
|
||||||
|
float: left; }
|
||||||
|
.select2-container .select2-search--inline .select2-search__field {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: none;
|
||||||
|
font-size: 100%;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 0; }
|
||||||
|
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
|
||||||
|
-webkit-appearance: none; }
|
||||||
|
|
||||||
|
.select2-dropdown {
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: -100000px;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 1051; }
|
||||||
|
|
||||||
|
.select2-results {
|
||||||
|
display: block; }
|
||||||
|
|
||||||
|
.select2-results__options {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0; }
|
||||||
|
|
||||||
|
.select2-results__option {
|
||||||
|
padding: 6px;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none; }
|
||||||
|
.select2-results__option[aria-selected] {
|
||||||
|
cursor: pointer; }
|
||||||
|
|
||||||
|
.select2-container--open .select2-dropdown {
|
||||||
|
left: 0; }
|
||||||
|
|
||||||
|
.select2-container--open .select2-dropdown--above {
|
||||||
|
border-bottom: none;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0; }
|
||||||
|
|
||||||
|
.select2-container--open .select2-dropdown--below {
|
||||||
|
border-top: none;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0; }
|
||||||
|
|
||||||
|
.select2-search--dropdown {
|
||||||
|
display: block;
|
||||||
|
padding: 4px; }
|
||||||
|
.select2-search--dropdown .select2-search__field {
|
||||||
|
padding: 4px;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
|
||||||
|
-webkit-appearance: none; }
|
||||||
|
.select2-search--dropdown.select2-search--hide {
|
||||||
|
display: none; }
|
||||||
|
|
||||||
|
.select2-close-mask {
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
min-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 99;
|
||||||
|
background-color: #fff;
|
||||||
|
filter: alpha(opacity=0); }
|
||||||
|
|
||||||
|
.select2-hidden-accessible {
|
||||||
|
border: 0 !important;
|
||||||
|
clip: rect(0 0 0 0) !important;
|
||||||
|
-webkit-clip-path: inset(50%) !important;
|
||||||
|
clip-path: inset(50%) !important;
|
||||||
|
height: 1px !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
position: absolute !important;
|
||||||
|
width: 1px !important;
|
||||||
|
white-space: nowrap !important; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-selection--single {
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 4px; }
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||||
|
color: #444;
|
||||||
|
line-height: 28px; }
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
font-weight: bold; }
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||||
|
color: #999; }
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||||
|
height: 26px;
|
||||||
|
position: absolute;
|
||||||
|
top: 1px;
|
||||||
|
right: 1px;
|
||||||
|
width: 20px; }
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__arrow b {
|
||||||
|
border-color: #888 transparent transparent transparent;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 5px 4px 0 4px;
|
||||||
|
height: 0;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -4px;
|
||||||
|
margin-top: -2px;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
width: 0; }
|
||||||
|
|
||||||
|
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||||
|
float: left; }
|
||||||
|
|
||||||
|
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||||
|
left: 1px;
|
||||||
|
right: auto; }
|
||||||
|
|
||||||
|
.select2-container--default.select2-container--disabled .select2-selection--single {
|
||||||
|
background-color: #eee;
|
||||||
|
cursor: default; }
|
||||||
|
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
|
||||||
|
display: none; }
|
||||||
|
|
||||||
|
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||||
|
border-color: transparent transparent #888 transparent;
|
||||||
|
border-width: 0 4px 5px 4px; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-selection--multiple {
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: text; }
|
||||||
|
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
|
||||||
|
box-sizing: border-box;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 5px;
|
||||||
|
width: 100%; }
|
||||||
|
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
|
||||||
|
list-style: none; }
|
||||||
|
.select2-container--default .select2-selection--multiple .select2-selection__clear {
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 1px; }
|
||||||
|
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||||
|
background-color: #e4e4e4;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: default;
|
||||||
|
float: left;
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 0 5px; }
|
||||||
|
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||||
|
color: #999;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 2px; }
|
||||||
|
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||||
|
color: #333; }
|
||||||
|
|
||||||
|
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
|
||||||
|
float: right; }
|
||||||
|
|
||||||
|
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: auto; }
|
||||||
|
|
||||||
|
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||||
|
margin-left: 2px;
|
||||||
|
margin-right: auto; }
|
||||||
|
|
||||||
|
.select2-container--default.select2-container--focus .select2-selection--multiple {
|
||||||
|
border: solid black 1px;
|
||||||
|
outline: 0; }
|
||||||
|
|
||||||
|
.select2-container--default.select2-container--disabled .select2-selection--multiple {
|
||||||
|
background-color: #eee;
|
||||||
|
cursor: default; }
|
||||||
|
|
||||||
|
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
|
||||||
|
display: none; }
|
||||||
|
|
||||||
|
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0; }
|
||||||
|
|
||||||
|
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-search--dropdown .select2-search__field {
|
||||||
|
border: 1px solid #aaa; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-search--inline .select2-search__field {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
outline: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
-webkit-appearance: textfield; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-results > .select2-results__options {
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-results__option[role=group] {
|
||||||
|
padding: 0; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-results__option[aria-disabled=true] {
|
||||||
|
color: #999; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-results__option[aria-selected=true] {
|
||||||
|
background-color: #ddd; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-results__option .select2-results__option {
|
||||||
|
padding-left: 1em; }
|
||||||
|
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
|
||||||
|
padding-left: 0; }
|
||||||
|
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
|
||||||
|
margin-left: -1em;
|
||||||
|
padding-left: 2em; }
|
||||||
|
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||||
|
margin-left: -2em;
|
||||||
|
padding-left: 3em; }
|
||||||
|
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||||
|
margin-left: -3em;
|
||||||
|
padding-left: 4em; }
|
||||||
|
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||||
|
margin-left: -4em;
|
||||||
|
padding-left: 5em; }
|
||||||
|
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||||
|
margin-left: -5em;
|
||||||
|
padding-left: 6em; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||||
|
background-color: #5897fb;
|
||||||
|
color: white; }
|
||||||
|
|
||||||
|
.select2-container--default .select2-results__group {
|
||||||
|
cursor: default;
|
||||||
|
display: block;
|
||||||
|
padding: 6px; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-selection--single {
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 4px;
|
||||||
|
outline: 0;
|
||||||
|
background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||||
|
background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||||
|
background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||||
|
.select2-container--classic .select2-selection--single:focus {
|
||||||
|
border: 1px solid #5897fb; }
|
||||||
|
.select2-container--classic .select2-selection--single .select2-selection__rendered {
|
||||||
|
color: #444;
|
||||||
|
line-height: 28px; }
|
||||||
|
.select2-container--classic .select2-selection--single .select2-selection__clear {
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 10px; }
|
||||||
|
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
|
||||||
|
color: #999; }
|
||||||
|
.select2-container--classic .select2-selection--single .select2-selection__arrow {
|
||||||
|
background-color: #ddd;
|
||||||
|
border: none;
|
||||||
|
border-left: 1px solid #aaa;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
height: 26px;
|
||||||
|
position: absolute;
|
||||||
|
top: 1px;
|
||||||
|
right: 1px;
|
||||||
|
width: 20px;
|
||||||
|
background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||||
|
background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); }
|
||||||
|
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
|
||||||
|
border-color: #888 transparent transparent transparent;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 5px 4px 0 4px;
|
||||||
|
height: 0;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -4px;
|
||||||
|
margin-top: -2px;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
width: 0; }
|
||||||
|
|
||||||
|
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||||
|
float: left; }
|
||||||
|
|
||||||
|
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||||
|
border: none;
|
||||||
|
border-right: 1px solid #aaa;
|
||||||
|
border-radius: 0;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
left: 1px;
|
||||||
|
right: auto; }
|
||||||
|
|
||||||
|
.select2-container--classic.select2-container--open .select2-selection--single {
|
||||||
|
border: 1px solid #5897fb; }
|
||||||
|
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
|
||||||
|
background: transparent;
|
||||||
|
border: none; }
|
||||||
|
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||||
|
border-color: transparent transparent #888 transparent;
|
||||||
|
border-width: 0 4px 5px 4px; }
|
||||||
|
|
||||||
|
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
|
||||||
|
border-top: none;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||||
|
background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||||
|
background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||||
|
|
||||||
|
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
|
||||||
|
border-bottom: none;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||||
|
background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-selection--multiple {
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: text;
|
||||||
|
outline: 0; }
|
||||||
|
.select2-container--classic .select2-selection--multiple:focus {
|
||||||
|
border: 1px solid #5897fb; }
|
||||||
|
.select2-container--classic .select2-selection--multiple .select2-selection__rendered {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 5px; }
|
||||||
|
.select2-container--classic .select2-selection--multiple .select2-selection__clear {
|
||||||
|
display: none; }
|
||||||
|
.select2-container--classic .select2-selection--multiple .select2-selection__choice {
|
||||||
|
background-color: #e4e4e4;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: default;
|
||||||
|
float: left;
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 0 5px; }
|
||||||
|
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
|
||||||
|
color: #888;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 2px; }
|
||||||
|
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||||
|
color: #555; }
|
||||||
|
|
||||||
|
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||||
|
float: right;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: auto; }
|
||||||
|
|
||||||
|
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||||
|
margin-left: 2px;
|
||||||
|
margin-right: auto; }
|
||||||
|
|
||||||
|
.select2-container--classic.select2-container--open .select2-selection--multiple {
|
||||||
|
border: 1px solid #5897fb; }
|
||||||
|
|
||||||
|
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||||
|
border-top: none;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0; }
|
||||||
|
|
||||||
|
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||||
|
border-bottom: none;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-search--dropdown .select2-search__field {
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
outline: 0; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-search--inline .select2-search__field {
|
||||||
|
outline: 0;
|
||||||
|
box-shadow: none; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-dropdown {
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid transparent; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-dropdown--above {
|
||||||
|
border-bottom: none; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-dropdown--below {
|
||||||
|
border-top: none; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-results > .select2-results__options {
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-results__option[role=group] {
|
||||||
|
padding: 0; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-results__option[aria-disabled=true] {
|
||||||
|
color: grey; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-results__option--highlighted[aria-selected] {
|
||||||
|
background-color: #3875d7;
|
||||||
|
color: white; }
|
||||||
|
|
||||||
|
.select2-container--classic .select2-results__group {
|
||||||
|
cursor: default;
|
||||||
|
display: block;
|
||||||
|
padding: 6px; }
|
||||||
|
|
||||||
|
.select2-container--classic.select2-container--open .select2-dropdown {
|
||||||
|
border-color: #5897fb; }
|
||||||
1
staticfiles/admin/css/vendor/select2/select2.min.css
vendored
Normal file
654
staticfiles/admin/css/widgets.css
Normal file
|
|
@ -0,0 +1,654 @@
|
||||||
|
/* SELECTOR (FILTER INTERFACE) */
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
gap: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector select {
|
||||||
|
height: 17.2em;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
overflow: scroll;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-available,
|
||||||
|
.selector-chosen {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-available-title,
|
||||||
|
.selector-chosen-title {
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .helptext {
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-chosen .list-footer-display {
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-top: none;
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
padding: 8px;
|
||||||
|
text-align: center;
|
||||||
|
background: var(--primary);
|
||||||
|
color: var(--header-link-color);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.selector-chosen .list-footer-display__clear {
|
||||||
|
color: var(--breadcrumbs-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-chosen-title {
|
||||||
|
background: var(--secondary);
|
||||||
|
color: var(--header-link-color);
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-chosen-title label {
|
||||||
|
color: var(--header-link-color);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-available-title {
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-available-title label {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-filter {
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-width: 0 1px;
|
||||||
|
padding: 8px;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
font-size: 0.625rem;
|
||||||
|
margin: 0;
|
||||||
|
text-align: left;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-filter label,
|
||||||
|
.inline-group .aligned .selector .selector-filter label {
|
||||||
|
float: left;
|
||||||
|
margin: 7px 0 0;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 1;
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-filter input {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector ul.selector-chooser {
|
||||||
|
align-self: center;
|
||||||
|
width: 30px;
|
||||||
|
background-color: var(--selected-bg);
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
transform: translateY(-17px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-chooser li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 3px;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector select {
|
||||||
|
padding: 0 10px;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
}
|
||||||
|
.selector .selector-chosen--with-filtered select {
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 14em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector
|
||||||
|
.selector-chosen:not(.selector-chosen--with-filtered)
|
||||||
|
.list-footer-display {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-add,
|
||||||
|
.selector-remove {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
display: block;
|
||||||
|
text-indent: -3000px;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: default;
|
||||||
|
opacity: 0.55;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-add,
|
||||||
|
:enabled.selector-remove {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-add:hover,
|
||||||
|
:enabled.selector-remove:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-add {
|
||||||
|
background: url(../img/selector-icons.svg) 0 -144px no-repeat;
|
||||||
|
background-size: 24px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-add:focus,
|
||||||
|
:enabled.selector-add:hover {
|
||||||
|
background-position: 0 -168px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-remove {
|
||||||
|
background: url(../img/selector-icons.svg) 0 -96px no-repeat;
|
||||||
|
background-size: 24px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-remove:focus,
|
||||||
|
:enabled.selector-remove:hover {
|
||||||
|
background-position: 0 -120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-chooseall,
|
||||||
|
.selector-clearall {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: left;
|
||||||
|
padding: 4px 5px;
|
||||||
|
margin: 0 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
color: var(--button-fg);
|
||||||
|
background-color: var(--button-bg);
|
||||||
|
text-decoration: none;
|
||||||
|
opacity: 0.55;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-chooseall:focus,
|
||||||
|
:enabled.selector-clearall:focus,
|
||||||
|
:enabled.selector-chooseall:hover,
|
||||||
|
:enabled.selector-clearall:hover {
|
||||||
|
background-color: var(--button-hover-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-chooseall,
|
||||||
|
:enabled.selector-clearall {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-chooseall:hover,
|
||||||
|
:enabled.selector-clearall:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-chooseall:focus,
|
||||||
|
:enabled.selector-chooseall:hover {
|
||||||
|
background-position: 100% -176px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:enabled.selector-clearall:focus,
|
||||||
|
:enabled.selector-clearall:hover {
|
||||||
|
background-position: 0 -144px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STACKED SELECTORS */
|
||||||
|
|
||||||
|
.stacked {
|
||||||
|
float: left;
|
||||||
|
width: 490px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked select {
|
||||||
|
width: 480px;
|
||||||
|
height: 10.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-available,
|
||||||
|
.stacked .selector-chosen {
|
||||||
|
width: 480px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-available {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-available input {
|
||||||
|
width: 422px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked ul.selector-chooser {
|
||||||
|
display: flex;
|
||||||
|
height: 30px;
|
||||||
|
width: 64px;
|
||||||
|
margin: 0 0 10px 40%;
|
||||||
|
background-color: #eee;
|
||||||
|
border-radius: 10px;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-chooser li {
|
||||||
|
float: left;
|
||||||
|
padding: 3px 3px 3px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-chooseall,
|
||||||
|
.stacked .selector-clearall {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-add {
|
||||||
|
background: url(../img/selector-icons.svg) 0 -48px no-repeat;
|
||||||
|
background-size: 24px auto;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked :enabled.selector-add {
|
||||||
|
background-position: 0 -48px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked :enabled.selector-add:focus,
|
||||||
|
.stacked :enabled.selector-add:hover {
|
||||||
|
background-position: 0 -72px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-remove {
|
||||||
|
background: url(../img/selector-icons.svg) 0 0 no-repeat;
|
||||||
|
background-size: 24px auto;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked :enabled.selector-remove {
|
||||||
|
background-position: 0 0px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked :enabled.selector-remove:focus,
|
||||||
|
.stacked :enabled.selector-remove:hover {
|
||||||
|
background-position: 0 -24px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .help-icon {
|
||||||
|
background: url(../img/icon-unknown.svg) 0 0 no-repeat;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: -2px 0 0 2px;
|
||||||
|
width: 13px;
|
||||||
|
height: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-chosen .help-icon {
|
||||||
|
background: url(../img/icon-unknown-alt.svg) 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .search-label-icon {
|
||||||
|
background: url(../img/search.svg) 0 0 no-repeat;
|
||||||
|
display: inline-block;
|
||||||
|
height: 1.125rem;
|
||||||
|
width: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DATE AND TIME */
|
||||||
|
|
||||||
|
p.datetime {
|
||||||
|
line-height: 20px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.datetime label {
|
||||||
|
display: block;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetime span {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetime input,
|
||||||
|
.form-row .datetime input.vDateField,
|
||||||
|
.form-row .datetime input.vTimeField {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table p.datetime {
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimeshortcuts button {
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimeshortcuts .clock-icon,
|
||||||
|
.datetimeshortcuts .date-icon {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimeshortcuts .clock-icon {
|
||||||
|
background: url(../img/icon-clock.svg) 0 0 no-repeat;
|
||||||
|
background-size: 24px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimeshortcuts button:focus .clock-icon,
|
||||||
|
.datetimeshortcuts button:hover .clock-icon {
|
||||||
|
background-position: 0 -24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimeshortcuts .date-icon {
|
||||||
|
background: url(../img/icon-calendar.svg) 0 0 no-repeat;
|
||||||
|
background-size: 24px auto;
|
||||||
|
top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimeshortcuts button:focus .date-icon,
|
||||||
|
.datetimeshortcuts button:hover .date-icon {
|
||||||
|
background-position: 0 -24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timezonewarning {
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* URL */
|
||||||
|
|
||||||
|
p.url {
|
||||||
|
line-height: 20px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.url a {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FILE UPLOADS */
|
||||||
|
|
||||||
|
p.file-upload {
|
||||||
|
line-height: 20px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-upload a {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-upload .deletelink {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.clearable-file-input label {
|
||||||
|
color: var(--body-fg);
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
display: inline;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CALENDARS & CLOCKS */
|
||||||
|
|
||||||
|
.calendarbox,
|
||||||
|
.clockbox {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
width: 19em;
|
||||||
|
text-align: center;
|
||||||
|
background: var(--body-bg);
|
||||||
|
color: var(--body-fg);
|
||||||
|
border: 1px solid var(--hairline-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarbox::backdrop,
|
||||||
|
.clockbox::backdrop {
|
||||||
|
background: rgba(0, 0, 0, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar table {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
background: white;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar caption,
|
||||||
|
.calendarbox h2 {
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
border-top: none;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: #333;
|
||||||
|
background: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar th {
|
||||||
|
padding: 8px 5px;
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar td {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
|
border-top: 1px solid var(--hairline-color);
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar td.selected a {
|
||||||
|
background: var(--secondary);
|
||||||
|
color: var(--button-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar td.nonday {
|
||||||
|
background: var(--darkened-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar td.today a {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar td a,
|
||||||
|
.timelist a {
|
||||||
|
display: block;
|
||||||
|
font-weight: 400;
|
||||||
|
padding: 6px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar td a:focus,
|
||||||
|
.timelist a:focus,
|
||||||
|
.calendar td a:hover,
|
||||||
|
.timelist a:hover {
|
||||||
|
background: var(--primary);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar td a:active,
|
||||||
|
.timelist a:active {
|
||||||
|
background: var(--header-bg);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarnav {
|
||||||
|
font-size: 0.625rem;
|
||||||
|
text-align: center;
|
||||||
|
color: #ccc;
|
||||||
|
margin: 0;
|
||||||
|
padding: 1px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarnav a:link,
|
||||||
|
#calendarnav a:visited,
|
||||||
|
#calendarnav a:focus,
|
||||||
|
#calendarnav a:hover {
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-shortcuts {
|
||||||
|
background: var(--body-bg);
|
||||||
|
color: var(--body-quiet-color);
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
line-height: 0.6875rem;
|
||||||
|
border-top: 1px solid var(--hairline-color);
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarbox .calendarnav-previous,
|
||||||
|
.calendarbox .calendarnav-next {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
text-indent: -9999px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarnav-previous {
|
||||||
|
left: 10px;
|
||||||
|
background: url(../img/calendar-icons.svg) 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendarnav-next {
|
||||||
|
right: 10px;
|
||||||
|
background: url(../img/calendar-icons.svg) 0 -15px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-cancel {
|
||||||
|
margin: 0;
|
||||||
|
padding: 4px 0;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
background: var(--close-button-bg);
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
color: var(--button-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-cancel:focus,
|
||||||
|
.calendar-cancel:hover {
|
||||||
|
background: var(--close-button-hover-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-cancel a {
|
||||||
|
color: var(--button-fg);
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.timelist,
|
||||||
|
.timelist li {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timelist a {
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EDIT INLINE */
|
||||||
|
|
||||||
|
.inline-deletelink {
|
||||||
|
float: right;
|
||||||
|
text-indent: -9999px;
|
||||||
|
background: url(../img/inline-delete.svg) center center no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
border: 0px none;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-deletelink:focus,
|
||||||
|
.inline-deletelink:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RELATED WIDGET WRAPPER */
|
||||||
|
.related-widget-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 0 10px;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-widget-wrapper:has(select:not([multiple])) {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-widget-wrapper-link {
|
||||||
|
opacity: 0.6;
|
||||||
|
filter: grayscale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-widget-wrapper-link:link {
|
||||||
|
opacity: 1;
|
||||||
|
filter: grayscale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GIS MAPS */
|
||||||
|
.dj_map {
|
||||||
|
width: 600px;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
80
staticfiles/admin/img/README.md
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
# Information about icons in this directory
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
All icons in this directory are provided by
|
||||||
|
[Font Awesome Free](https://fontawesome.com), version 6.7.2.
|
||||||
|
|
||||||
|
- The icons are licensed under the [Creative Commons Attribution 4.0
|
||||||
|
International (CC-BY-4.0)](https://creativecommons.org/licenses/by/4.0/)
|
||||||
|
license.
|
||||||
|
- This license allows you to use, modify, and distribute the icons, provided
|
||||||
|
proper attribution is given.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
- You may use, modify, and distribute the icons in this repository in
|
||||||
|
compliance with the [Creative Commons Attribution 4.0 International
|
||||||
|
(CC-BY-4.0)](https://creativecommons.org/licenses/by/4.0/) license.
|
||||||
|
|
||||||
|
## Modifications
|
||||||
|
|
||||||
|
- These icons have been resized, recolored, or otherwise modified to fit the
|
||||||
|
requirements of this project.
|
||||||
|
|
||||||
|
- These modifications alter the appearance of the original icons but remain
|
||||||
|
covered under the terms of the
|
||||||
|
[CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) license.
|
||||||
|
|
||||||
|
## Contributing SVG Icons
|
||||||
|
|
||||||
|
To ensure visual consistency, traceability, and proper license attribution,
|
||||||
|
follow these guidelines. This applies when adding or modifying icons.
|
||||||
|
|
||||||
|
## ⚠️ Important: Changing Font Awesome Version
|
||||||
|
|
||||||
|
If you update to a different Font Awesome version, you must **update all SVG
|
||||||
|
files** and **comments inside the files** to reflect the new version number and
|
||||||
|
licensing URL accordingly. For example:
|
||||||
|
|
||||||
|
* Original:
|
||||||
|
```xml
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
```
|
||||||
|
* Updated:
|
||||||
|
```xml
|
||||||
|
<!--!Font Awesome Free X.Y.Z by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright YYYY Fonticons, Inc.-->
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding a new icon
|
||||||
|
|
||||||
|
1. Use only [Font Awesome Free Icons](https://fontawesome.com/icons).
|
||||||
|
2. Save the icon as an .svg file in this directory.
|
||||||
|
3. Include the following attribution comment at the top of the file (do not
|
||||||
|
change it):
|
||||||
|
```xml
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
```
|
||||||
|
4. Right before the `<path>` element, add the following metadata comment with
|
||||||
|
the appropriate values:
|
||||||
|
```xml
|
||||||
|
<!--
|
||||||
|
Icon Name: [icon-name]
|
||||||
|
Icon Family: [classic | sharp | brands | etc.]
|
||||||
|
Icon Style: [solid | regular | light | thin | duotone | etc.]
|
||||||
|
-->
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example SVG Structure
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: plus
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#5fa225" stroke="#5fa225" stroke-width="30" d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"/>
|
||||||
|
</svg>
|
||||||
|
```
|
||||||
44
staticfiles/admin/img/calendar-icons.svg
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<svg
|
||||||
|
width="15"
|
||||||
|
height="30"
|
||||||
|
viewBox="0 0 512 1024"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<defs id="defs2">
|
||||||
|
<g id="previous">
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-chevron-left
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path
|
||||||
|
d="M512 256A256 256 0 1 0 0 256a256 256 0 1 0 512 0zM271 135c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-87 87 87 87c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0L167 273c-9.4-9.4-9.4-24.6 0-33.9L271 135z"
|
||||||
|
id="path2" />
|
||||||
|
</g>
|
||||||
|
<g id="next">
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-chevron-right
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path
|
||||||
|
d="M0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM241 377c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l87-87-87-87c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0L345 239c9.4 9.4 9.4 24.6 0 33.9L241 377z"
|
||||||
|
id="path1" />
|
||||||
|
</g>
|
||||||
|
</defs>
|
||||||
|
<use
|
||||||
|
xlink:href="#next"
|
||||||
|
x="0"
|
||||||
|
y="512"
|
||||||
|
fill="#000000"
|
||||||
|
id="use5" />
|
||||||
|
<use
|
||||||
|
xlink:href="#previous"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
fill="#333333"
|
||||||
|
id="use2" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
9
staticfiles/admin/img/icon-addlink.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: plus
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#5fa225" stroke="#5fa225" stroke-width="30" d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 593 B |
9
staticfiles/admin/img/icon-alert-dark.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="14" height="14">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: triangle-exclamation
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#efb80b" d="M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480L40 480c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 684 B |
9
staticfiles/admin/img/icon-alert.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="14" height="14">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: triangle-exclamation
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#b78b02" d="M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480L40 480c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 684 B |
15
staticfiles/admin/img/icon-calendar.svg
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<svg width="16" height="32" viewBox="0 0 448 1024" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<defs>
|
||||||
|
<g id="icon">
|
||||||
|
<!--
|
||||||
|
Icon Name: calendar-days
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: regular
|
||||||
|
-->
|
||||||
|
<path d="M152 24c0-13.3-10.7-24-24-24s-24 10.7-24 24l0 40L64 64C28.7 64 0 92.7 0 128l0 16 0 48L0 448c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-256 0-48 0-16c0-35.3-28.7-64-64-64l-40 0 0-40c0-13.3-10.7-24-24-24s-24 10.7-24 24l0 40L152 64l0-40zM48 192l80 0 0 56-80 0 0-56zm0 104l80 0 0 64-80 0 0-64zm128 0l96 0 0 64-96 0 0-64zm144 0l80 0 0 64-80 0 0-64zm80-48l-80 0 0-56 80 0 0 56zm0 160l0 40c0 8.8-7.2 16-16 16l-64 0 0-56 80 0zm-128 0l0 56-96 0 0-56 96 0zm-144 0l0 56-64 0c-8.8 0-16-7.2-16-16l0-40 80 0zM272 248l-96 0 0-56 96 0 0 56z"/>
|
||||||
|
</g>
|
||||||
|
</defs>
|
||||||
|
<use xlink:href="#icon" x="0" y="0" fill="#447e9b" />
|
||||||
|
<use xlink:href="#icon" x="0" y="512" fill="#003366" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
9
staticfiles/admin/img/icon-changelink.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: pencil
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#b48c08" d="M410.3 231l11.3-11.3-33.9-33.9-62.1-62.1L291.7 89.8l-11.3 11.3-22.6 22.6L58.6 322.9c-10.4 10.4-18 23.3-22.2 37.4L1 480.7c-2.5 8.4-.2 17.5 6.1 23.7s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L387.7 253.7 410.3 231zM160 399.4l-9.1 22.7c-4 3.1-8.5 5.4-13.3 6.9L59.4 452l23-78.1c1.4-4.9 3.8-9.4 6.9-13.3l22.7-9.1 0 32c0 8.8 7.2 16 16 16l32 0zM362.7 18.7L348.3 33.2 325.7 55.8 314.3 67.1l33.9 33.9 62.1 62.1 33.9 33.9 11.3-11.3 22.6-22.6 14.5-14.5c25-25 25-65.5 0-90.5L453.3 18.7c-25-25-65.5-25-90.5 0zm-47.4 168l-144 144c-6.2 6.2-16.4 6.2-22.6 0s-6.2-16.4 0-22.6l144-144c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 978 B |
15
staticfiles/admin/img/icon-clock.svg
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<svg width="16" height="32" viewBox="0 0 512 1024" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<defs>
|
||||||
|
<g id="icon">
|
||||||
|
<!--
|
||||||
|
Icon Name: clock
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: regular
|
||||||
|
-->
|
||||||
|
<path d="M464 256A208 208 0 1 1 48 256a208 208 0 1 1 416 0zM0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM232 120l0 136c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2 280 120c0-13.3-10.7-24-24-24s-24 10.7-24 24z"/>
|
||||||
|
</g>
|
||||||
|
</defs>
|
||||||
|
<use xlink:href="#icon" x="0" y="0" fill="#447e9b"/>
|
||||||
|
<use xlink:href="#icon" x="0" y="512" fill="#003366" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 805 B |
9
staticfiles/admin/img/icon-debug-dark.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc. -->
|
||||||
|
<!--
|
||||||
|
Icon Name: bug
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#bfbfbf" d="M256 0c53 0 96 43 96 96l0 3.6c0 15.7-12.7 28.4-28.4 28.4l-135.1 0c-15.7 0-28.4-12.7-28.4-28.4l0-3.6c0-53 43-96 96-96zM41.4 105.4c12.5-12.5 32.8-12.5 45.3 0l64 64c.7 .7 1.3 1.4 1.9 2.1c14.2-7.3 30.4-11.4 47.5-11.4l112 0c17.1 0 33.2 4.1 47.5 11.4c.6-.7 1.2-1.4 1.9-2.1l64-64c12.5-12.5 32.8-12.5 45.3 0s12.5 32.8 0 45.3l-64 64c-.7 .7-1.4 1.3-2.1 1.9c6.2 12 10.1 25.3 11.1 39.5l64.3 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-64 0c0 24.6-5.5 47.8-15.4 68.6c2.2 1.3 4.2 2.9 6 4.8l64 64c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0l-63.1-63.1c-24.5 21.8-55.8 36.2-90.3 39.6L272 240c0-8.8-7.2-16-16-16s-16 7.2-16 16l0 239.2c-34.5-3.4-65.8-17.8-90.3-39.6L86.6 502.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l64-64c1.9-1.9 3.9-3.4 6-4.8C101.5 367.8 96 344.6 96 320l-64 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l64.3 0c1.1-14.1 5-27.5 11.1-39.5c-.7-.6-1.4-1.2-2.1-1.9l-64-64c-12.5-12.5-12.5-32.8 0-45.3z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
9
staticfiles/admin/img/icon-debug.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc. -->
|
||||||
|
<!--
|
||||||
|
Icon Name: bug
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#808080" d="M256 0c53 0 96 43 96 96l0 3.6c0 15.7-12.7 28.4-28.4 28.4l-135.1 0c-15.7 0-28.4-12.7-28.4-28.4l0-3.6c0-53 43-96 96-96zM41.4 105.4c12.5-12.5 32.8-12.5 45.3 0l64 64c.7 .7 1.3 1.4 1.9 2.1c14.2-7.3 30.4-11.4 47.5-11.4l112 0c17.1 0 33.2 4.1 47.5 11.4c.6-.7 1.2-1.4 1.9-2.1l64-64c12.5-12.5 32.8-12.5 45.3 0s12.5 32.8 0 45.3l-64 64c-.7 .7-1.4 1.3-2.1 1.9c6.2 12 10.1 25.3 11.1 39.5l64.3 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-64 0c0 24.6-5.5 47.8-15.4 68.6c2.2 1.3 4.2 2.9 6 4.8l64 64c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0l-63.1-63.1c-24.5 21.8-55.8 36.2-90.3 39.6L272 240c0-8.8-7.2-16-16-16s-16 7.2-16 16l0 239.2c-34.5-3.4-65.8-17.8-90.3-39.6L86.6 502.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l64-64c1.9-1.9 3.9-3.4 6-4.8C101.5 367.8 96 344.6 96 320l-64 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l64.3 0c1.1-14.1 5-27.5 11.1-39.5c-.7-.6-1.4-1.2-2.1-1.9l-64-64c-12.5-12.5-12.5-32.8 0-45.3z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
11
staticfiles/admin/img/icon-deletelink.svg
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<svg width="14" height="14" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<g>
|
||||||
|
<!--
|
||||||
|
Icon Name: xmark
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#dd4646" stroke="#dd4646" stroke-width="30" d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 707 B |
9
staticfiles/admin/img/icon-hidelink.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: eye-slash
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#2b70bf" d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c8.4-19.3 10.6-41.4 4.8-63.3c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zM373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5L373 389.9z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
9
staticfiles/admin/img/icon-info-dark.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc. -->
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-info
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#63b4eb" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336l24 0 0-64-24 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l48 0c13.3 0 24 10.7 24 24l0 88 8 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 630 B |
9
staticfiles/admin/img/icon-info.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc. -->
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-info
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#3f8cc1" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336l24 0 0-64-24 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l48 0c13.3 0 24 10.7 24 24l0 88 8 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 630 B |
9
staticfiles/admin/img/icon-no-dark.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-xmark
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#f15f5f" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 645 B |
9
staticfiles/admin/img/icon-no.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-xmark
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#c63d3d" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 645 B |
9
staticfiles/admin/img/icon-unknown-alt.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-question
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#ffffff" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM169.8 165.3c7.9-22.3 29.1-37.3 52.8-37.3l58.3 0c34.9 0 63.1 28.3 63.1 63.1c0 22.6-12.1 43.5-31.7 54.8L280 264.4c-.2 13-10.9 23.6-24 23.6c-13.3 0-24-10.7-24-24l0-13.5c0-8.6 4.6-16.5 12.1-20.8l44.3-25.4c4.7-2.7 7.6-7.7 7.6-13.1c0-8.4-6.8-15.1-15.1-15.1l-58.3 0c-3.4 0-6.4 2.1-7.5 5.3l-.4 1.2c-4.4 12.5-18.2 19-30.6 14.6s-19-18.2-14.6-30.6l.4-1.2zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 806 B |
9
staticfiles/admin/img/icon-unknown.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-question
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#666666" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM169.8 165.3c7.9-22.3 29.1-37.3 52.8-37.3l58.3 0c34.9 0 63.1 28.3 63.1 63.1c0 22.6-12.1 43.5-31.7 54.8L280 264.4c-.2 13-10.9 23.6-24 23.6c-13.3 0-24-10.7-24-24l0-13.5c0-8.6 4.6-16.5 12.1-20.8l44.3-25.4c4.7-2.7 7.6-7.7 7.6-13.1c0-8.4-6.8-15.1-15.1-15.1l-58.3 0c-3.4 0-6.4 2.1-7.5 5.3l-.4 1.2c-4.4 12.5-18.2 19-30.6 14.6s-19-18.2-14.6-30.6l.4-1.2zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 806 B |
9
staticfiles/admin/img/icon-viewlink.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: eye
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#2b70bf" d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 928 B |
9
staticfiles/admin/img/icon-yes-dark.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-check
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#73c12f" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 558 B |
9
staticfiles/admin/img/icon-yes.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-check
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#649c35" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 558 B |
9
staticfiles/admin/img/inline-delete.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-xmark
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#999999" d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 651 B |
9
staticfiles/admin/img/search.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="15" height="15" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: magnifying-glass
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#555555" d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 607 B |
45
staticfiles/admin/img/selector-icons.svg
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<svg width="16" height="128" viewBox="0 0 512 4096" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<defs>
|
||||||
|
<g id="up">
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-arrow-up
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM385 215c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-71-71L280 392c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-214.1-71 71c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9L239 103c9.4-9.4 24.6-9.4 33.9 0L385 215z"/>
|
||||||
|
</g>
|
||||||
|
<g id="down">
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-arrow-down
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path d="M256 0a256 256 0 1 0 0 512A256 256 0 1 0 256 0zM127 297c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l71 71L232 120c0-13.3 10.7-24 24-24s24 10.7 24 24l0 214.1 71-71c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9L273 409c-9.4 9.4-24.6 9.4-33.9 0L127 297z"/>
|
||||||
|
</g>
|
||||||
|
<g id="right">
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-arrow-right
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path d="M0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM297 385c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l71-71L120 280c-13.3 0-24-10.7-24-24s10.7-24 24-24l214.1 0-71-71c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0L409 239c9.4 9.4 9.4 24.6 0 33.9L297 385z"/>
|
||||||
|
</g>
|
||||||
|
<g id="left">
|
||||||
|
<!--
|
||||||
|
Icon Name: circle-arrow-left
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path d="M512 256A256 256 0 1 0 0 256a256 256 0 1 0 512 0zM215 127c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-71 71L392 232c13.3 0 24 10.7 24 24s-10.7 24-24 24l-214.1 0 71 71c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0L103 273c-9.4-9.4-9.4-24.6 0-33.9L215 127z"/>
|
||||||
|
</g>
|
||||||
|
</defs>
|
||||||
|
<use xlink:href="#up" x="0" y="0" fill="#666666" />
|
||||||
|
<use xlink:href="#up" x="0" y="512" fill="#447e9b" />
|
||||||
|
<use xlink:href="#down" x="0" y="1024" fill="#666666" />
|
||||||
|
<use xlink:href="#down" x="0" y="1536" fill="#447e9b" />
|
||||||
|
<use xlink:href="#left" x="0" y="2048" fill="#666666" />
|
||||||
|
<use xlink:href="#left" x="0" y="2560" fill="#447e9b" />
|
||||||
|
<use xlink:href="#right" x="0" y="3072" fill="#666666" />
|
||||||
|
<use xlink:href="#right" x="0" y="3584" fill="#447e9b" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
35
staticfiles/admin/img/sorting-icons.svg
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<svg width="14" height="84" viewBox="0 0 512 3072" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<defs>
|
||||||
|
<g id="sort">
|
||||||
|
<!--
|
||||||
|
Icon Name: sort
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8L32 224c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8l256 0c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"/>
|
||||||
|
</g>
|
||||||
|
<g id="ascending">
|
||||||
|
<!--
|
||||||
|
Icon Name: sort-up
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path d="M182.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8l256 0c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z"/>
|
||||||
|
</g>
|
||||||
|
<g id="descending">
|
||||||
|
<!--
|
||||||
|
Icon Name: sort-down
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path d="M182.6 470.6c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8l256 0c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128z"/>
|
||||||
|
</g>
|
||||||
|
</defs>
|
||||||
|
<use xlink:href="#sort" x="0" y="0" fill="#999999" />
|
||||||
|
<use xlink:href="#sort" x="0" y="512" fill="#447e9b" />
|
||||||
|
<use xlink:href="#ascending" x="0" y="1024" fill="#999999" />
|
||||||
|
<use xlink:href="#ascending" x="0" y="1536" fill="#447e9b" />
|
||||||
|
<use xlink:href="#descending" x="0" y="2048" fill="#999999" />
|
||||||
|
<use xlink:href="#descending" x="0" y="2560" fill="#447e9b" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
9
staticfiles/admin/img/tooltag-add.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: plus
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#ffffff" stroke="#ffffff" stroke-width="30" d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 593 B |
9
staticfiles/admin/img/tooltag-arrowright.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
|
||||||
|
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||||
|
<!--
|
||||||
|
Icon Name: chevron-right
|
||||||
|
Icon Family: classic
|
||||||
|
Icon Style: solid
|
||||||
|
-->
|
||||||
|
<path fill="#ffffff" stroke="#ffffff" stroke-width="30" d="M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 569 B |
177
staticfiles/admin/js/SelectBox.js
Normal file
|
|
@ -0,0 +1,177 @@
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const getOptionGroupName = (option) => option.parentElement.label;
|
||||||
|
const SelectBox = {
|
||||||
|
cache: {},
|
||||||
|
init: function (id) {
|
||||||
|
const box = document.getElementById(id);
|
||||||
|
SelectBox.cache[id] = [];
|
||||||
|
const cache = SelectBox.cache[id];
|
||||||
|
for (const node of box.options) {
|
||||||
|
const group = getOptionGroupName(node);
|
||||||
|
cache.push({
|
||||||
|
group,
|
||||||
|
value: node.value,
|
||||||
|
text: node.text,
|
||||||
|
displayed: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Only sort if there are any groups (to preserve existing behavior for non-grouped selects)
|
||||||
|
if (cache.some((item) => item.group)) {
|
||||||
|
SelectBox.sort(id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
redisplay: function (id) {
|
||||||
|
// Repopulate HTML select box from cache
|
||||||
|
const box = document.getElementById(id);
|
||||||
|
const scroll_value_from_top = box.scrollTop;
|
||||||
|
box.innerHTML = "";
|
||||||
|
let node = box;
|
||||||
|
let currentOptgroup = null;
|
||||||
|
for (const option of SelectBox.cache[id]) {
|
||||||
|
if (option.displayed) {
|
||||||
|
// Create a new optgroup when the group changes
|
||||||
|
if (option.group && option.group !== currentOptgroup) {
|
||||||
|
currentOptgroup = option.group;
|
||||||
|
node = document.createElement("optgroup");
|
||||||
|
node.setAttribute("label", option.group);
|
||||||
|
box.appendChild(node);
|
||||||
|
} else if (!option.group && currentOptgroup !== null) {
|
||||||
|
// Back to ungrouped options
|
||||||
|
currentOptgroup = null;
|
||||||
|
node = box;
|
||||||
|
}
|
||||||
|
const new_option = new Option(
|
||||||
|
option.text,
|
||||||
|
option.value,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
// Shows a tooltip when hovering over the option
|
||||||
|
new_option.title = option.text;
|
||||||
|
node.appendChild(new_option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
box.scrollTop = scroll_value_from_top;
|
||||||
|
},
|
||||||
|
filter: function (id, text) {
|
||||||
|
// Redisplay the HTML select box, displaying only the choices containing ALL
|
||||||
|
// the words in text. (It's an AND search.)
|
||||||
|
const tokens = text.toLowerCase().split(/\s+/);
|
||||||
|
for (const node of SelectBox.cache[id]) {
|
||||||
|
node.displayed = 1;
|
||||||
|
const node_text = node.text.toLowerCase();
|
||||||
|
for (const token of tokens) {
|
||||||
|
if (!node_text.includes(token)) {
|
||||||
|
node.displayed = 0;
|
||||||
|
break; // Once the first token isn't found we're done
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SelectBox.redisplay(id);
|
||||||
|
},
|
||||||
|
get_hidden_node_count(id) {
|
||||||
|
const cache = SelectBox.cache[id] || [];
|
||||||
|
return cache.filter((node) => node.displayed === 0).length;
|
||||||
|
},
|
||||||
|
delete_from_cache: function (id, value) {
|
||||||
|
let delete_index = null;
|
||||||
|
const cache = SelectBox.cache[id];
|
||||||
|
for (const [i, node] of cache.entries()) {
|
||||||
|
if (node.value === value) {
|
||||||
|
delete_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache.splice(delete_index, 1);
|
||||||
|
},
|
||||||
|
add_to_cache: function (id, option) {
|
||||||
|
SelectBox.cache[id].push({
|
||||||
|
group: option.group,
|
||||||
|
value: option.value,
|
||||||
|
text: option.text,
|
||||||
|
displayed: 1,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
cache_contains: function (id, value) {
|
||||||
|
// Check if an item is contained in the cache
|
||||||
|
for (const node of SelectBox.cache[id]) {
|
||||||
|
if (node.value === value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
move: function (from, to) {
|
||||||
|
const from_box = document.getElementById(from);
|
||||||
|
for (const option of from_box.options) {
|
||||||
|
const option_value = option.value;
|
||||||
|
if (
|
||||||
|
option.selected &&
|
||||||
|
SelectBox.cache_contains(from, option_value)
|
||||||
|
) {
|
||||||
|
const group = getOptionGroupName(option);
|
||||||
|
SelectBox.add_to_cache(to, {
|
||||||
|
group,
|
||||||
|
value: option_value,
|
||||||
|
text: option.text,
|
||||||
|
displayed: 1,
|
||||||
|
});
|
||||||
|
SelectBox.delete_from_cache(from, option_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Only sort if there are any groups (to preserve existing behavior for non-grouped selects)
|
||||||
|
if (SelectBox.cache[to].some((item) => item.group)) {
|
||||||
|
SelectBox.sort(to);
|
||||||
|
}
|
||||||
|
SelectBox.redisplay(from);
|
||||||
|
SelectBox.redisplay(to);
|
||||||
|
},
|
||||||
|
move_all: function (from, to) {
|
||||||
|
const from_box = document.getElementById(from);
|
||||||
|
for (const option of from_box.options) {
|
||||||
|
const option_value = option.value;
|
||||||
|
if (SelectBox.cache_contains(from, option_value)) {
|
||||||
|
const group = getOptionGroupName(option);
|
||||||
|
SelectBox.add_to_cache(to, {
|
||||||
|
group,
|
||||||
|
value: option_value,
|
||||||
|
text: option.text,
|
||||||
|
displayed: 1,
|
||||||
|
});
|
||||||
|
SelectBox.delete_from_cache(from, option_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Only sort if there are any groups (to preserve existing behavior for non-grouped selects)
|
||||||
|
if (SelectBox.cache[to].some((item) => item.group)) {
|
||||||
|
SelectBox.sort(to);
|
||||||
|
}
|
||||||
|
SelectBox.redisplay(from);
|
||||||
|
SelectBox.redisplay(to);
|
||||||
|
},
|
||||||
|
sort: function (id) {
|
||||||
|
SelectBox.cache[id].sort(function (a, b) {
|
||||||
|
a =
|
||||||
|
((a.group && a.group.toLowerCase()) || "") +
|
||||||
|
a.text.toLowerCase();
|
||||||
|
b =
|
||||||
|
((b.group && b.group.toLowerCase()) || "") +
|
||||||
|
b.text.toLowerCase();
|
||||||
|
if (a > b) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (a < b) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
select_all: function (id) {
|
||||||
|
const box = document.getElementById(id);
|
||||||
|
for (const option of box.options) {
|
||||||
|
option.selected = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
window.SelectBox = SelectBox;
|
||||||
|
}
|
||||||
523
staticfiles/admin/js/SelectFilter2.js
Normal file
|
|
@ -0,0 +1,523 @@
|
||||||
|
/*global SelectBox, gettext, ngettext, interpolate, quickElement, SelectFilter*/
|
||||||
|
/*
|
||||||
|
SelectFilter2 - Turns a multiple-select box into a filter interface.
|
||||||
|
|
||||||
|
Requires core.js and SelectBox.js.
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
window.SelectFilter = {
|
||||||
|
init: function (field_id, field_name, is_stacked) {
|
||||||
|
if (field_id.match(/__prefix__/)) {
|
||||||
|
// Don't initialize on empty forms.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const from_box = document.getElementById(field_id);
|
||||||
|
from_box.id += "_from"; // change its ID
|
||||||
|
from_box.className = "filtered";
|
||||||
|
from_box.setAttribute("aria-labelledby", field_id + "_from_label");
|
||||||
|
from_box.setAttribute(
|
||||||
|
"aria-describedby",
|
||||||
|
`${field_id}_helptext ${field_id}_choose_helptext`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// <div class="selector"> or <div class="selector stacked">
|
||||||
|
const selector_div = quickElement("div", from_box.parentNode);
|
||||||
|
// Make sure the selector div appears between the label and the add link.
|
||||||
|
from_box.parentNode.insertBefore(
|
||||||
|
selector_div,
|
||||||
|
from_box.nextSibling,
|
||||||
|
);
|
||||||
|
selector_div.className = is_stacked
|
||||||
|
? "selector stacked"
|
||||||
|
: "selector";
|
||||||
|
|
||||||
|
// <div class="selector-available">
|
||||||
|
const selector_available = quickElement("div", selector_div);
|
||||||
|
selector_available.className = "selector-available";
|
||||||
|
const selector_available_title = quickElement(
|
||||||
|
"div",
|
||||||
|
selector_available,
|
||||||
|
);
|
||||||
|
selector_available_title.id = field_id + "_from_title";
|
||||||
|
selector_available_title.className = "selector-available-title";
|
||||||
|
quickElement(
|
||||||
|
"label",
|
||||||
|
selector_available_title,
|
||||||
|
interpolate(gettext("Available %s") + " ", [field_name]),
|
||||||
|
"id",
|
||||||
|
field_id + "_from_label",
|
||||||
|
"for",
|
||||||
|
field_id + "_from",
|
||||||
|
);
|
||||||
|
quickElement(
|
||||||
|
"p",
|
||||||
|
selector_available_title,
|
||||||
|
interpolate(
|
||||||
|
gettext(
|
||||||
|
'Choose %s by selecting them and then select the "Choose" arrow button.',
|
||||||
|
),
|
||||||
|
[field_name],
|
||||||
|
),
|
||||||
|
"id",
|
||||||
|
`${field_id}_choose_helptext`,
|
||||||
|
"class",
|
||||||
|
"helptext",
|
||||||
|
);
|
||||||
|
|
||||||
|
const filter_p = quickElement(
|
||||||
|
"p",
|
||||||
|
selector_available,
|
||||||
|
"",
|
||||||
|
"id",
|
||||||
|
field_id + "_filter",
|
||||||
|
);
|
||||||
|
filter_p.className = "selector-filter";
|
||||||
|
|
||||||
|
const search_filter_label = quickElement(
|
||||||
|
"label",
|
||||||
|
filter_p,
|
||||||
|
"",
|
||||||
|
"for",
|
||||||
|
field_id + "_input",
|
||||||
|
);
|
||||||
|
|
||||||
|
quickElement(
|
||||||
|
"span",
|
||||||
|
search_filter_label,
|
||||||
|
"",
|
||||||
|
"class",
|
||||||
|
"help-tooltip search-label-icon",
|
||||||
|
"aria-label",
|
||||||
|
interpolate(
|
||||||
|
gettext(
|
||||||
|
"Type into this box to filter down the list of available %s.",
|
||||||
|
),
|
||||||
|
[field_name],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
filter_p.appendChild(document.createTextNode(" "));
|
||||||
|
|
||||||
|
const filter_input = quickElement(
|
||||||
|
"input",
|
||||||
|
filter_p,
|
||||||
|
"",
|
||||||
|
"type",
|
||||||
|
"text",
|
||||||
|
"placeholder",
|
||||||
|
gettext("Filter"),
|
||||||
|
);
|
||||||
|
filter_input.id = field_id + "_input";
|
||||||
|
|
||||||
|
selector_available.appendChild(from_box);
|
||||||
|
const choose_all = quickElement(
|
||||||
|
"button",
|
||||||
|
selector_available,
|
||||||
|
interpolate(gettext("Choose all %s"), [field_name]),
|
||||||
|
"id",
|
||||||
|
field_id + "_add_all",
|
||||||
|
"class",
|
||||||
|
"selector-chooseall",
|
||||||
|
"type",
|
||||||
|
"button",
|
||||||
|
);
|
||||||
|
|
||||||
|
// <ul class="selector-chooser">
|
||||||
|
const selector_chooser = quickElement("ul", selector_div);
|
||||||
|
selector_chooser.className = "selector-chooser";
|
||||||
|
const add_button = quickElement(
|
||||||
|
"button",
|
||||||
|
quickElement("li", selector_chooser),
|
||||||
|
interpolate(gettext("Choose selected %s"), [field_name]),
|
||||||
|
"id",
|
||||||
|
field_id + "_add",
|
||||||
|
"class",
|
||||||
|
"selector-add",
|
||||||
|
"type",
|
||||||
|
"button",
|
||||||
|
);
|
||||||
|
const remove_button = quickElement(
|
||||||
|
"button",
|
||||||
|
quickElement("li", selector_chooser),
|
||||||
|
interpolate(gettext("Remove selected %s"), [field_name]),
|
||||||
|
"id",
|
||||||
|
field_id + "_remove",
|
||||||
|
"class",
|
||||||
|
"selector-remove",
|
||||||
|
"type",
|
||||||
|
"button",
|
||||||
|
);
|
||||||
|
|
||||||
|
// <div class="selector-chosen">
|
||||||
|
const selector_chosen = quickElement(
|
||||||
|
"div",
|
||||||
|
selector_div,
|
||||||
|
"",
|
||||||
|
"id",
|
||||||
|
field_id + "_selector_chosen",
|
||||||
|
);
|
||||||
|
selector_chosen.className = "selector-chosen";
|
||||||
|
const selector_chosen_title = quickElement("div", selector_chosen);
|
||||||
|
selector_chosen_title.className = "selector-chosen-title";
|
||||||
|
selector_chosen_title.id = field_id + "_to_title";
|
||||||
|
quickElement(
|
||||||
|
"label",
|
||||||
|
selector_chosen_title,
|
||||||
|
interpolate(gettext("Chosen %s") + " ", [field_name]),
|
||||||
|
"id",
|
||||||
|
field_id + "_to_label",
|
||||||
|
"for",
|
||||||
|
field_id + "_to",
|
||||||
|
);
|
||||||
|
quickElement(
|
||||||
|
"p",
|
||||||
|
selector_chosen_title,
|
||||||
|
interpolate(
|
||||||
|
gettext(
|
||||||
|
'Remove %s by selecting them and then select the "Remove" arrow button.',
|
||||||
|
),
|
||||||
|
[field_name],
|
||||||
|
),
|
||||||
|
"id",
|
||||||
|
`${field_id}_remove_helptext`,
|
||||||
|
"class",
|
||||||
|
"helptext",
|
||||||
|
);
|
||||||
|
|
||||||
|
const filter_selected_p = quickElement(
|
||||||
|
"p",
|
||||||
|
selector_chosen,
|
||||||
|
"",
|
||||||
|
"id",
|
||||||
|
field_id + "_filter_selected",
|
||||||
|
);
|
||||||
|
filter_selected_p.className = "selector-filter";
|
||||||
|
|
||||||
|
const search_filter_selected_label = quickElement(
|
||||||
|
"label",
|
||||||
|
filter_selected_p,
|
||||||
|
"",
|
||||||
|
"for",
|
||||||
|
field_id + "_selected_input",
|
||||||
|
);
|
||||||
|
|
||||||
|
quickElement(
|
||||||
|
"span",
|
||||||
|
search_filter_selected_label,
|
||||||
|
"",
|
||||||
|
"class",
|
||||||
|
"help-tooltip search-label-icon",
|
||||||
|
"aria-label",
|
||||||
|
interpolate(
|
||||||
|
gettext(
|
||||||
|
"Type into this box to filter down the list of selected %s.",
|
||||||
|
),
|
||||||
|
[field_name],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
filter_selected_p.appendChild(document.createTextNode(" "));
|
||||||
|
|
||||||
|
const filter_selected_input = quickElement(
|
||||||
|
"input",
|
||||||
|
filter_selected_p,
|
||||||
|
"",
|
||||||
|
"type",
|
||||||
|
"text",
|
||||||
|
"placeholder",
|
||||||
|
gettext("Filter"),
|
||||||
|
);
|
||||||
|
filter_selected_input.id = field_id + "_selected_input";
|
||||||
|
|
||||||
|
quickElement(
|
||||||
|
"select",
|
||||||
|
selector_chosen,
|
||||||
|
"",
|
||||||
|
"id",
|
||||||
|
field_id + "_to",
|
||||||
|
"multiple",
|
||||||
|
"",
|
||||||
|
"size",
|
||||||
|
from_box.size,
|
||||||
|
"name",
|
||||||
|
from_box.name,
|
||||||
|
"aria-labelledby",
|
||||||
|
field_id + "_to_label",
|
||||||
|
"aria-describedby",
|
||||||
|
`${field_id}_helptext ${field_id}_remove_helptext`,
|
||||||
|
"class",
|
||||||
|
"filtered",
|
||||||
|
);
|
||||||
|
const warning_footer = quickElement(
|
||||||
|
"div",
|
||||||
|
selector_chosen,
|
||||||
|
"",
|
||||||
|
"class",
|
||||||
|
"list-footer-display",
|
||||||
|
);
|
||||||
|
quickElement(
|
||||||
|
"span",
|
||||||
|
warning_footer,
|
||||||
|
"",
|
||||||
|
"id",
|
||||||
|
field_id + "_list-footer-display-text",
|
||||||
|
);
|
||||||
|
quickElement(
|
||||||
|
"span",
|
||||||
|
warning_footer,
|
||||||
|
" " + gettext("(click to clear)"),
|
||||||
|
"class",
|
||||||
|
"list-footer-display__clear",
|
||||||
|
);
|
||||||
|
const clear_all = quickElement(
|
||||||
|
"button",
|
||||||
|
selector_chosen,
|
||||||
|
interpolate(gettext("Remove all %s"), [field_name]),
|
||||||
|
"id",
|
||||||
|
field_id + "_remove_all",
|
||||||
|
"class",
|
||||||
|
"selector-clearall",
|
||||||
|
"type",
|
||||||
|
"button",
|
||||||
|
);
|
||||||
|
|
||||||
|
from_box.name = from_box.name + "_old";
|
||||||
|
|
||||||
|
// Set up the JavaScript event handlers for the select box filter interface
|
||||||
|
const move_selection = function (e, elem, move_func, from, to) {
|
||||||
|
if (!elem.hasAttribute("disabled")) {
|
||||||
|
move_func(from, to);
|
||||||
|
SelectFilter.refresh_icons(field_id);
|
||||||
|
SelectFilter.refresh_filtered_selects(field_id);
|
||||||
|
SelectFilter.refresh_filtered_warning(field_id);
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
choose_all.addEventListener("click", function (e) {
|
||||||
|
move_selection(
|
||||||
|
e,
|
||||||
|
this,
|
||||||
|
SelectBox.move_all,
|
||||||
|
field_id + "_from",
|
||||||
|
field_id + "_to",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
add_button.addEventListener("click", function (e) {
|
||||||
|
move_selection(
|
||||||
|
e,
|
||||||
|
this,
|
||||||
|
SelectBox.move,
|
||||||
|
field_id + "_from",
|
||||||
|
field_id + "_to",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
remove_button.addEventListener("click", function (e) {
|
||||||
|
move_selection(
|
||||||
|
e,
|
||||||
|
this,
|
||||||
|
SelectBox.move,
|
||||||
|
field_id + "_to",
|
||||||
|
field_id + "_from",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
clear_all.addEventListener("click", function (e) {
|
||||||
|
move_selection(
|
||||||
|
e,
|
||||||
|
this,
|
||||||
|
SelectBox.move_all,
|
||||||
|
field_id + "_to",
|
||||||
|
field_id + "_from",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
warning_footer.addEventListener("click", function (e) {
|
||||||
|
filter_selected_input.value = "";
|
||||||
|
SelectBox.filter(field_id + "_to", "");
|
||||||
|
SelectFilter.refresh_filtered_warning(field_id);
|
||||||
|
SelectFilter.refresh_icons(field_id);
|
||||||
|
});
|
||||||
|
filter_input.addEventListener("keypress", function (e) {
|
||||||
|
SelectFilter.filter_key_press(e, field_id, "_from", "_to");
|
||||||
|
});
|
||||||
|
filter_input.addEventListener("keyup", function (e) {
|
||||||
|
SelectFilter.filter_key_up(e, field_id, "_from");
|
||||||
|
});
|
||||||
|
filter_input.addEventListener("keydown", function (e) {
|
||||||
|
SelectFilter.filter_key_down(e, field_id, "_from", "_to");
|
||||||
|
});
|
||||||
|
filter_selected_input.addEventListener("keypress", function (e) {
|
||||||
|
SelectFilter.filter_key_press(e, field_id, "_to", "_from");
|
||||||
|
});
|
||||||
|
filter_selected_input.addEventListener("keyup", function (e) {
|
||||||
|
SelectFilter.filter_key_up(
|
||||||
|
e,
|
||||||
|
field_id,
|
||||||
|
"_to",
|
||||||
|
"_selected_input",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
filter_selected_input.addEventListener("keydown", function (e) {
|
||||||
|
SelectFilter.filter_key_down(e, field_id, "_to", "_from");
|
||||||
|
});
|
||||||
|
selector_div.addEventListener("change", function (e) {
|
||||||
|
if (e.target.tagName === "SELECT") {
|
||||||
|
SelectFilter.refresh_icons(field_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
selector_div.addEventListener("dblclick", function (e) {
|
||||||
|
if (e.target.tagName === "OPTION") {
|
||||||
|
if (e.target.closest("select").id === field_id + "_to") {
|
||||||
|
SelectBox.move(field_id + "_to", field_id + "_from");
|
||||||
|
} else {
|
||||||
|
SelectBox.move(field_id + "_from", field_id + "_to");
|
||||||
|
}
|
||||||
|
SelectFilter.refresh_icons(field_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
from_box.closest("form").addEventListener("submit", function () {
|
||||||
|
SelectBox.filter(field_id + "_to", "");
|
||||||
|
SelectBox.select_all(field_id + "_to");
|
||||||
|
});
|
||||||
|
SelectBox.init(field_id + "_from");
|
||||||
|
SelectBox.init(field_id + "_to");
|
||||||
|
// Move selected from_box options to to_box
|
||||||
|
SelectBox.move(field_id + "_from", field_id + "_to");
|
||||||
|
|
||||||
|
// Initial icon refresh
|
||||||
|
SelectFilter.refresh_icons(field_id);
|
||||||
|
},
|
||||||
|
any_selected: function (field) {
|
||||||
|
// Temporarily add the required attribute and check validity.
|
||||||
|
field.required = true;
|
||||||
|
const any_selected = field.checkValidity();
|
||||||
|
field.required = false;
|
||||||
|
return any_selected;
|
||||||
|
},
|
||||||
|
refresh_filtered_warning: function (field_id) {
|
||||||
|
const count = SelectBox.get_hidden_node_count(field_id + "_to");
|
||||||
|
const selector = document.getElementById(
|
||||||
|
field_id + "_selector_chosen",
|
||||||
|
);
|
||||||
|
const warning = document.getElementById(
|
||||||
|
field_id + "_list-footer-display-text",
|
||||||
|
);
|
||||||
|
selector.className = selector.className.replace(
|
||||||
|
"selector-chosen--with-filtered",
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
warning.textContent = interpolate(
|
||||||
|
ngettext(
|
||||||
|
"%s selected option not visible",
|
||||||
|
"%s selected options not visible",
|
||||||
|
count,
|
||||||
|
),
|
||||||
|
[count],
|
||||||
|
);
|
||||||
|
if (count > 0) {
|
||||||
|
selector.className += " selector-chosen--with-filtered";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
refresh_filtered_selects: function (field_id) {
|
||||||
|
SelectBox.filter(
|
||||||
|
field_id + "_from",
|
||||||
|
document.getElementById(field_id + "_input").value,
|
||||||
|
);
|
||||||
|
SelectBox.filter(
|
||||||
|
field_id + "_to",
|
||||||
|
document.getElementById(field_id + "_selected_input").value,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
refresh_icons: function (field_id) {
|
||||||
|
const from = document.getElementById(field_id + "_from");
|
||||||
|
const to = document.getElementById(field_id + "_to");
|
||||||
|
// Disabled if no items are selected.
|
||||||
|
document.getElementById(field_id + "_add").disabled =
|
||||||
|
!SelectFilter.any_selected(from);
|
||||||
|
document.getElementById(field_id + "_remove").disabled =
|
||||||
|
!SelectFilter.any_selected(to);
|
||||||
|
// Disabled if the corresponding box is empty.
|
||||||
|
document.getElementById(field_id + "_add_all").disabled =
|
||||||
|
!from.querySelector("option");
|
||||||
|
document.getElementById(field_id + "_remove_all").disabled =
|
||||||
|
!to.querySelector("option");
|
||||||
|
},
|
||||||
|
filter_key_press: function (event, field_id, source, target) {
|
||||||
|
const source_box = document.getElementById(field_id + source);
|
||||||
|
// don't submit form if user pressed Enter
|
||||||
|
if (
|
||||||
|
(event.which && event.which === 13) ||
|
||||||
|
(event.keyCode && event.keyCode === 13)
|
||||||
|
) {
|
||||||
|
source_box.selectedIndex = 0;
|
||||||
|
SelectBox.move(field_id + source, field_id + target);
|
||||||
|
source_box.selectedIndex = 0;
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filter_key_up: function (event, field_id, source, filter_input) {
|
||||||
|
const input = filter_input || "_input";
|
||||||
|
const source_box = document.getElementById(field_id + source);
|
||||||
|
const temp = source_box.selectedIndex;
|
||||||
|
SelectBox.filter(
|
||||||
|
field_id + source,
|
||||||
|
document.getElementById(field_id + input).value,
|
||||||
|
);
|
||||||
|
source_box.selectedIndex = temp;
|
||||||
|
SelectFilter.refresh_filtered_warning(field_id);
|
||||||
|
SelectFilter.refresh_icons(field_id);
|
||||||
|
},
|
||||||
|
filter_key_down: function (event, field_id, source, target) {
|
||||||
|
const source_box = document.getElementById(field_id + source);
|
||||||
|
// right key (39) or left key (37)
|
||||||
|
const direction = source === "_from" ? 39 : 37;
|
||||||
|
// right arrow -- move across
|
||||||
|
if (
|
||||||
|
(event.which && event.which === direction) ||
|
||||||
|
(event.keyCode && event.keyCode === direction)
|
||||||
|
) {
|
||||||
|
const old_index = source_box.selectedIndex;
|
||||||
|
SelectBox.move(field_id + source, field_id + target);
|
||||||
|
SelectFilter.refresh_filtered_selects(field_id);
|
||||||
|
SelectFilter.refresh_filtered_warning(field_id);
|
||||||
|
source_box.selectedIndex =
|
||||||
|
old_index === source_box.length
|
||||||
|
? source_box.length - 1
|
||||||
|
: old_index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// down arrow -- wrap around
|
||||||
|
if (
|
||||||
|
(event.which && event.which === 40) ||
|
||||||
|
(event.keyCode && event.keyCode === 40)
|
||||||
|
) {
|
||||||
|
source_box.selectedIndex =
|
||||||
|
source_box.length === source_box.selectedIndex + 1
|
||||||
|
? 0
|
||||||
|
: source_box.selectedIndex + 1;
|
||||||
|
}
|
||||||
|
// up arrow -- wrap around
|
||||||
|
if (
|
||||||
|
(event.which && event.which === 38) ||
|
||||||
|
(event.keyCode && event.keyCode === 38)
|
||||||
|
) {
|
||||||
|
source_box.selectedIndex =
|
||||||
|
source_box.selectedIndex === 0
|
||||||
|
? source_box.length - 1
|
||||||
|
: source_box.selectedIndex - 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("load", function (e) {
|
||||||
|
document
|
||||||
|
.querySelectorAll("select.selectfilter, select.selectfilterstacked")
|
||||||
|
.forEach(function (el) {
|
||||||
|
const data = el.dataset;
|
||||||
|
SelectFilter.init(
|
||||||
|
el.id,
|
||||||
|
data.fieldName,
|
||||||
|
parseInt(data.isStacked, 10),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
246
staticfiles/admin/js/actions.js
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
/*global gettext, interpolate, ngettext, Actions*/
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
function show(selector) {
|
||||||
|
document.querySelectorAll(selector).forEach(function (el) {
|
||||||
|
el.classList.remove("hidden");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide(selector) {
|
||||||
|
document.querySelectorAll(selector).forEach(function (el) {
|
||||||
|
el.classList.add("hidden");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showQuestion(options) {
|
||||||
|
hide(options.acrossClears);
|
||||||
|
show(options.acrossQuestions);
|
||||||
|
hide(options.allContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showClear(options) {
|
||||||
|
show(options.acrossClears);
|
||||||
|
hide(options.acrossQuestions);
|
||||||
|
document
|
||||||
|
.querySelector(options.actionContainer)
|
||||||
|
.classList.remove(options.selectedClass);
|
||||||
|
show(options.allContainer);
|
||||||
|
hide(options.counterContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset(options) {
|
||||||
|
hide(options.acrossClears);
|
||||||
|
hide(options.acrossQuestions);
|
||||||
|
hide(options.allContainer);
|
||||||
|
show(options.counterContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearAcross(options) {
|
||||||
|
reset(options);
|
||||||
|
const acrossInputs = document.querySelectorAll(options.acrossInput);
|
||||||
|
acrossInputs.forEach(function (acrossInput) {
|
||||||
|
acrossInput.value = 0;
|
||||||
|
});
|
||||||
|
document
|
||||||
|
.querySelector(options.actionContainer)
|
||||||
|
.classList.remove(options.selectedClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checker(actionCheckboxes, options, checked) {
|
||||||
|
if (checked) {
|
||||||
|
showQuestion(options);
|
||||||
|
} else {
|
||||||
|
reset(options);
|
||||||
|
}
|
||||||
|
actionCheckboxes.forEach(function (el) {
|
||||||
|
el.checked = checked;
|
||||||
|
el.closest("tr").classList.toggle(options.selectedClass, checked);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCounter(actionCheckboxes, options) {
|
||||||
|
const sel = Array.from(actionCheckboxes).filter(function (el) {
|
||||||
|
return el.checked;
|
||||||
|
}).length;
|
||||||
|
const counter = document.querySelector(options.counterContainer);
|
||||||
|
// data-actions-icnt is defined in the generated HTML
|
||||||
|
// and contains the total amount of objects in the queryset
|
||||||
|
const actions_icnt = Number(counter.dataset.actionsIcnt);
|
||||||
|
counter.textContent = interpolate(
|
||||||
|
ngettext(
|
||||||
|
"%(sel)s of %(cnt)s selected",
|
||||||
|
"%(sel)s of %(cnt)s selected",
|
||||||
|
sel,
|
||||||
|
),
|
||||||
|
{
|
||||||
|
sel: sel,
|
||||||
|
cnt: actions_icnt,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
const allToggle = document.getElementById(options.allToggleId);
|
||||||
|
allToggle.checked = sel === actionCheckboxes.length;
|
||||||
|
if (allToggle.checked) {
|
||||||
|
showQuestion(options);
|
||||||
|
} else {
|
||||||
|
clearAcross(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
actionContainer: "div.actions",
|
||||||
|
counterContainer: "span.action-counter",
|
||||||
|
allContainer: "div.actions span.all",
|
||||||
|
acrossInput: "div.actions input.select-across",
|
||||||
|
acrossQuestions: "div.actions span.question",
|
||||||
|
acrossClears: "div.actions span.clear",
|
||||||
|
allToggleId: "action-toggle",
|
||||||
|
selectedClass: "selected",
|
||||||
|
};
|
||||||
|
|
||||||
|
window.Actions = function (actionCheckboxes, options) {
|
||||||
|
options = Object.assign({}, defaults, options);
|
||||||
|
let list_editable_changed = false;
|
||||||
|
let lastChecked = null;
|
||||||
|
let shiftPressed = false;
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (event) => {
|
||||||
|
shiftPressed = event.shiftKey;
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("keyup", (event) => {
|
||||||
|
shiftPressed = event.shiftKey;
|
||||||
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.getElementById(options.allToggleId)
|
||||||
|
.addEventListener("click", function (event) {
|
||||||
|
checker(actionCheckboxes, options, this.checked);
|
||||||
|
updateCounter(actionCheckboxes, options);
|
||||||
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll(options.acrossQuestions + " a")
|
||||||
|
.forEach(function (el) {
|
||||||
|
el.addEventListener("click", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const acrossInputs = document.querySelectorAll(
|
||||||
|
options.acrossInput,
|
||||||
|
);
|
||||||
|
acrossInputs.forEach(function (acrossInput) {
|
||||||
|
acrossInput.value = 1;
|
||||||
|
});
|
||||||
|
showClear(options);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll(options.acrossClears + " a")
|
||||||
|
.forEach(function (el) {
|
||||||
|
el.addEventListener("click", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
document.getElementById(options.allToggleId).checked =
|
||||||
|
false;
|
||||||
|
clearAcross(options);
|
||||||
|
checker(actionCheckboxes, options, false);
|
||||||
|
updateCounter(actionCheckboxes, options);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function affectedCheckboxes(target, withModifier) {
|
||||||
|
const multiSelect =
|
||||||
|
lastChecked && withModifier && lastChecked !== target;
|
||||||
|
if (!multiSelect) {
|
||||||
|
return [target];
|
||||||
|
}
|
||||||
|
const checkboxes = Array.from(actionCheckboxes);
|
||||||
|
const targetIndex = checkboxes.findIndex((el) => el === target);
|
||||||
|
const lastCheckedIndex = checkboxes.findIndex(
|
||||||
|
(el) => el === lastChecked,
|
||||||
|
);
|
||||||
|
const startIndex = Math.min(targetIndex, lastCheckedIndex);
|
||||||
|
const endIndex = Math.max(targetIndex, lastCheckedIndex);
|
||||||
|
const filtered = checkboxes.filter(
|
||||||
|
(el, index) => startIndex <= index && index <= endIndex,
|
||||||
|
);
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.from(document.getElementById("result_list").tBodies).forEach(
|
||||||
|
function (el) {
|
||||||
|
el.addEventListener("change", function (event) {
|
||||||
|
const target = event.target;
|
||||||
|
if (target.classList.contains("action-select")) {
|
||||||
|
const checkboxes = affectedCheckboxes(
|
||||||
|
target,
|
||||||
|
shiftPressed,
|
||||||
|
);
|
||||||
|
checker(checkboxes, options, target.checked);
|
||||||
|
updateCounter(actionCheckboxes, options);
|
||||||
|
lastChecked = target;
|
||||||
|
} else {
|
||||||
|
list_editable_changed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector("#changelist-form button[name=index]")
|
||||||
|
.addEventListener("click", function (event) {
|
||||||
|
if (list_editable_changed) {
|
||||||
|
const confirmed = confirm(
|
||||||
|
gettext(
|
||||||
|
"You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (!confirmed) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const el = document.querySelector("#changelist-form input[name=_save]");
|
||||||
|
// The button does not exist if no fields are editable.
|
||||||
|
if (el) {
|
||||||
|
el.addEventListener("click", function (event) {
|
||||||
|
if (document.querySelector("[name=action]").value) {
|
||||||
|
const text = list_editable_changed
|
||||||
|
? gettext(
|
||||||
|
"You have selected an action, but you haven’t saved your changes to individual fields yet. Please click OK to save. You’ll need to re-run the action.",
|
||||||
|
)
|
||||||
|
: gettext(
|
||||||
|
"You have selected an action, and you haven’t made any changes on individual fields. You’re probably looking for the Run button rather than the Save button.",
|
||||||
|
);
|
||||||
|
if (!confirm(text)) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Sync counter when navigating to the page, such as through the back
|
||||||
|
// button.
|
||||||
|
window.addEventListener("pageshow", (event) =>
|
||||||
|
updateCounter(actionCheckboxes, options),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call function fn when the DOM is loaded and ready. If it is already
|
||||||
|
// loaded, call the function now.
|
||||||
|
// http://youmightnotneedjquery.com/#ready
|
||||||
|
function ready(fn) {
|
||||||
|
if (document.readyState !== "loading") {
|
||||||
|
fn();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ready(function () {
|
||||||
|
const actionsEls = document.querySelectorAll("tr input.action-select");
|
||||||
|
if (actionsEls.length > 0) {
|
||||||
|
Actions(actionsEls);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
682
staticfiles/admin/js/admin/DateTimeShortcuts.js
Normal file
|
|
@ -0,0 +1,682 @@
|
||||||
|
/*global Calendar, CalendarNamespace, findPosX, findPosY, get_format, gettext, gettext_noop, interpolate, ngettext, quickElement*/
|
||||||
|
// Inserts shortcut buttons after all of the following:
|
||||||
|
// <input type="text" class="vDateField">
|
||||||
|
// <input type="text" class="vTimeField">
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const DateTimeShortcuts = {
|
||||||
|
calendars: [],
|
||||||
|
calendarInputs: [],
|
||||||
|
clockInputs: [],
|
||||||
|
clockHours: {
|
||||||
|
default_: [
|
||||||
|
[gettext_noop("Now"), -1],
|
||||||
|
[gettext_noop("Midnight"), 0],
|
||||||
|
[gettext_noop("6 a.m."), 6],
|
||||||
|
[gettext_noop("Noon"), 12],
|
||||||
|
[gettext_noop("6 p.m."), 18],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
dismissClockFunc: [],
|
||||||
|
dismissCalendarFunc: [],
|
||||||
|
calendarDivName1: "calendarbox", // name of calendar <div> that gets toggled
|
||||||
|
calendarDivName2: "calendarin", // name of <div> that contains calendar
|
||||||
|
calendarLinkName: "calendarlink", // name of the link that is used to toggle
|
||||||
|
clockDivName: "clockbox", // name of clock <div> that gets toggled
|
||||||
|
clockLinkName: "clocklink", // name of the link that is used to toggle
|
||||||
|
shortCutsClass: "datetimeshortcuts", // class of the clock and cal shortcuts
|
||||||
|
timezoneWarningClass: "timezonewarning", // class of the warning for timezone mismatch
|
||||||
|
timezoneOffset: 0,
|
||||||
|
init: function () {
|
||||||
|
const serverOffset = document.body.dataset.adminUtcOffset;
|
||||||
|
if (serverOffset) {
|
||||||
|
const localOffset = new Date().getTimezoneOffset() * -60;
|
||||||
|
DateTimeShortcuts.timezoneOffset = localOffset - serverOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const inp of document.getElementsByTagName("input")) {
|
||||||
|
if (
|
||||||
|
inp.type === "text" &&
|
||||||
|
inp.classList.contains("vTimeField")
|
||||||
|
) {
|
||||||
|
DateTimeShortcuts.addClock(inp);
|
||||||
|
DateTimeShortcuts.addTimezoneWarning(inp);
|
||||||
|
} else if (
|
||||||
|
inp.type === "text" &&
|
||||||
|
inp.classList.contains("vDateField")
|
||||||
|
) {
|
||||||
|
DateTimeShortcuts.addCalendar(inp);
|
||||||
|
DateTimeShortcuts.addTimezoneWarning(inp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Return the current time while accounting for the server timezone.
|
||||||
|
now: function () {
|
||||||
|
return CalendarNamespace.serverToday();
|
||||||
|
},
|
||||||
|
// Add a warning when the time zone in the browser and backend do not match.
|
||||||
|
addTimezoneWarning: function (inp) {
|
||||||
|
const warningClass = DateTimeShortcuts.timezoneWarningClass;
|
||||||
|
let timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600;
|
||||||
|
|
||||||
|
// Only warn if there is a time zone mismatch.
|
||||||
|
if (!timezoneOffset) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if warning is already there.
|
||||||
|
if (
|
||||||
|
inp.parentNode.parentNode.querySelectorAll("." + warningClass)
|
||||||
|
.length
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverTimezone =
|
||||||
|
document.body.dataset.adminServerTimezone || gettext("server");
|
||||||
|
let message;
|
||||||
|
if (timezoneOffset > 0) {
|
||||||
|
message = ngettext(
|
||||||
|
"Note: Enter times in the %(timezone)s timezone. " +
|
||||||
|
"(You are %(offset)s hour ahead.)",
|
||||||
|
"Note: Enter times in the %(timezone)s timezone. " +
|
||||||
|
"(You are %(offset)s hours ahead.)",
|
||||||
|
timezoneOffset,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
timezoneOffset *= -1;
|
||||||
|
message = ngettext(
|
||||||
|
"Note: Enter times in the %(timezone)s timezone. " +
|
||||||
|
"(You are %(offset)s hour behind.)",
|
||||||
|
"Note: Enter times in the %(timezone)s timezone. " +
|
||||||
|
"(You are %(offset)s hours behind.)",
|
||||||
|
timezoneOffset,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
message = interpolate(
|
||||||
|
message,
|
||||||
|
{ timezone: serverTimezone, offset: timezoneOffset },
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
const warning = document.createElement("div");
|
||||||
|
const id = inp.id;
|
||||||
|
const field_id = inp.closest("p.datetime")
|
||||||
|
? id.slice(0, id.lastIndexOf("_"))
|
||||||
|
: id;
|
||||||
|
warning.classList.add("help", warningClass);
|
||||||
|
warning.id = `${field_id}_timezone_warning_helptext`;
|
||||||
|
warning.textContent = message;
|
||||||
|
const errorList =
|
||||||
|
inp.parentNode.parentNode.querySelector("ul.errorlist");
|
||||||
|
if (errorList) {
|
||||||
|
errorList.before(warning);
|
||||||
|
} else {
|
||||||
|
inp.parentNode.before(warning);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Add clock widget to a given field
|
||||||
|
addClock: function (inp) {
|
||||||
|
const num = DateTimeShortcuts.clockInputs.length;
|
||||||
|
DateTimeShortcuts.clockInputs[num] = inp;
|
||||||
|
DateTimeShortcuts.dismissClockFunc[num] = function () {
|
||||||
|
DateTimeShortcuts.dismissClock(num);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shortcut links (clock icon and "Now" link)
|
||||||
|
const shortcuts_span = document.createElement("span");
|
||||||
|
shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
|
||||||
|
inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
|
||||||
|
const now_link = document.createElement("a");
|
||||||
|
now_link.href = "#";
|
||||||
|
now_link.textContent = gettext("Now");
|
||||||
|
now_link.role = "button";
|
||||||
|
now_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.handleClockQuicklink(num, -1);
|
||||||
|
});
|
||||||
|
const clock_link = document.createElement("button");
|
||||||
|
clock_link.type = "button";
|
||||||
|
clock_link.id = DateTimeShortcuts.clockLinkName + num;
|
||||||
|
clock_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
// avoid triggering the document click handler to dismiss the clock
|
||||||
|
e.stopPropagation();
|
||||||
|
DateTimeShortcuts.openClock(num);
|
||||||
|
});
|
||||||
|
|
||||||
|
const clockIconId = DateTimeShortcuts.clockLinkName + num + "_icon";
|
||||||
|
quickElement(
|
||||||
|
"span",
|
||||||
|
clock_link,
|
||||||
|
"",
|
||||||
|
"id",
|
||||||
|
clockIconId,
|
||||||
|
"class",
|
||||||
|
"clock-icon",
|
||||||
|
"title",
|
||||||
|
gettext("Choose a Time"),
|
||||||
|
);
|
||||||
|
clock_link.setAttribute("aria-labelledby", clockIconId);
|
||||||
|
shortcuts_span.appendChild(document.createTextNode("\u00A0"));
|
||||||
|
shortcuts_span.appendChild(now_link);
|
||||||
|
shortcuts_span.appendChild(
|
||||||
|
document.createTextNode("\u00A0|\u00A0"),
|
||||||
|
);
|
||||||
|
shortcuts_span.appendChild(clock_link);
|
||||||
|
|
||||||
|
// Create clock link div
|
||||||
|
//
|
||||||
|
// Markup looks like:
|
||||||
|
// <dialog id="clockbox1" class="clockbox module" role="dialog"
|
||||||
|
// aria-label="Choose a time">
|
||||||
|
// <h2>Choose a time</h2>
|
||||||
|
// <ul class="timelist">
|
||||||
|
// <li><a href="#" role="button">Now</a></li>
|
||||||
|
// <li><a href="#" role="button">Midnight</a></li>
|
||||||
|
// <li><a href="#" role="button">6 a.m.</a></li>
|
||||||
|
// <li><a href="#" role="button">Noon</a></li>
|
||||||
|
// <li><a href="#" role="button">6 p.m.</a></li>
|
||||||
|
// </ul>
|
||||||
|
// <p class="calendar-cancel">
|
||||||
|
// <a href="#" role="button" aria-label="Close Clock">Cancel</a>
|
||||||
|
// </p>
|
||||||
|
// </dialog>
|
||||||
|
|
||||||
|
const clock_box = document.createElement("dialog");
|
||||||
|
clock_box.className = "clockbox module";
|
||||||
|
clock_box.id = DateTimeShortcuts.clockDivName + num;
|
||||||
|
clock_box.setAttribute("role", "dialog");
|
||||||
|
clock_box.setAttribute("aria-labelledby", clockIconId);
|
||||||
|
document.body.appendChild(clock_box);
|
||||||
|
clock_box.addEventListener("click", function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
quickElement("h2", clock_box, gettext("Choose a time"));
|
||||||
|
const time_list = quickElement("ul", clock_box);
|
||||||
|
time_list.className = "timelist";
|
||||||
|
// The list of choices can be overridden in JavaScript like this:
|
||||||
|
// DateTimeShortcuts.clockHours.name = [['3 a.m.', 3]];
|
||||||
|
// where name is the name attribute of the <input>.
|
||||||
|
const name =
|
||||||
|
typeof DateTimeShortcuts.clockHours[inp.name] === "undefined"
|
||||||
|
? "default_"
|
||||||
|
: inp.name;
|
||||||
|
DateTimeShortcuts.clockHours[name].forEach(function (element) {
|
||||||
|
const time_link = quickElement(
|
||||||
|
"a",
|
||||||
|
quickElement("li", time_list),
|
||||||
|
gettext(element[0]),
|
||||||
|
"role",
|
||||||
|
"button",
|
||||||
|
"href",
|
||||||
|
"#",
|
||||||
|
);
|
||||||
|
time_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.handleClockQuicklink(num, element[1]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const cancel_p = quickElement("p", clock_box);
|
||||||
|
cancel_p.className = "calendar-cancel";
|
||||||
|
const cancel_link = quickElement(
|
||||||
|
"a",
|
||||||
|
cancel_p,
|
||||||
|
gettext("Cancel"),
|
||||||
|
"role",
|
||||||
|
"button",
|
||||||
|
"href",
|
||||||
|
"#",
|
||||||
|
);
|
||||||
|
cancel_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.dismissClock(num);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("keyup", function (event) {
|
||||||
|
if (event.key === "Escape") {
|
||||||
|
// ESC key closes popup
|
||||||
|
DateTimeShortcuts.dismissClock(num);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
openClock: function (num) {
|
||||||
|
const clock_box = document.getElementById(
|
||||||
|
DateTimeShortcuts.clockDivName + num,
|
||||||
|
);
|
||||||
|
const clock_link = document.getElementById(
|
||||||
|
DateTimeShortcuts.clockLinkName + num,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Recalculate the clockbox position
|
||||||
|
// is it left-to-right or right-to-left layout ?
|
||||||
|
if (window.getComputedStyle(document.body).direction !== "rtl") {
|
||||||
|
clock_box.style.left = findPosX(clock_link) + 17 + "px";
|
||||||
|
} else {
|
||||||
|
// since style's width is in em, it'd be tough to calculate
|
||||||
|
// px value of it. let's use an estimated px for now
|
||||||
|
clock_box.style.right = findPosX(clock_link) - 110 + "px";
|
||||||
|
}
|
||||||
|
clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + "px";
|
||||||
|
|
||||||
|
// Show the clock box
|
||||||
|
clock_box.showModal();
|
||||||
|
},
|
||||||
|
dismissClock: function (num) {
|
||||||
|
document
|
||||||
|
.getElementById(DateTimeShortcuts.clockDivName + num)
|
||||||
|
.close();
|
||||||
|
},
|
||||||
|
handleClockQuicklink: function (num, val) {
|
||||||
|
let d;
|
||||||
|
if (val === -1) {
|
||||||
|
d = DateTimeShortcuts.now();
|
||||||
|
} else {
|
||||||
|
d = new Date(1970, 1, 1, val, 0, 0, 0);
|
||||||
|
}
|
||||||
|
DateTimeShortcuts.clockInputs[num].value = d.strftime(
|
||||||
|
get_format("TIME_INPUT_FORMATS")[0],
|
||||||
|
);
|
||||||
|
DateTimeShortcuts.clockInputs[num].focus();
|
||||||
|
DateTimeShortcuts.dismissClock(num);
|
||||||
|
},
|
||||||
|
// Add calendar widget to a given field.
|
||||||
|
addCalendar: function (inp) {
|
||||||
|
const num = DateTimeShortcuts.calendars.length;
|
||||||
|
|
||||||
|
DateTimeShortcuts.calendarInputs[num] = inp;
|
||||||
|
DateTimeShortcuts.dismissCalendarFunc[num] = function () {
|
||||||
|
DateTimeShortcuts.dismissCalendar(num);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getFormattedDate(offset) {
|
||||||
|
const d = DateTimeShortcuts.now();
|
||||||
|
d.setDate(d.getDate() + offset);
|
||||||
|
return CalendarNamespace.formatDate(
|
||||||
|
d.getDate(),
|
||||||
|
d.getMonth() + 1,
|
||||||
|
d.getFullYear(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Shortcut links (calendar icon and "Today" link)
|
||||||
|
const shortcuts_span = document.createElement("span");
|
||||||
|
shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
|
||||||
|
inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
|
||||||
|
const today_link = document.createElement("a");
|
||||||
|
today_link.href = "#";
|
||||||
|
today_link.role = "button";
|
||||||
|
today_link.appendChild(document.createTextNode(gettext("Today")));
|
||||||
|
today_link.setAttribute(
|
||||||
|
"aria-label",
|
||||||
|
interpolate(
|
||||||
|
gettext("Today (%(date)s)"),
|
||||||
|
{ date: getFormattedDate(0) },
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
today_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.handleCalendarQuickLink(num, 0);
|
||||||
|
});
|
||||||
|
const cal_link = document.createElement("button");
|
||||||
|
cal_link.type = "button";
|
||||||
|
cal_link.id = DateTimeShortcuts.calendarLinkName + num;
|
||||||
|
cal_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
// avoid triggering the document click handler to dismiss the calendar
|
||||||
|
e.stopPropagation();
|
||||||
|
DateTimeShortcuts.openCalendar(num);
|
||||||
|
});
|
||||||
|
const calIconId =
|
||||||
|
DateTimeShortcuts.calendarLinkName + num + "_icon";
|
||||||
|
quickElement(
|
||||||
|
"span",
|
||||||
|
cal_link,
|
||||||
|
"",
|
||||||
|
"id",
|
||||||
|
calIconId,
|
||||||
|
"class",
|
||||||
|
"date-icon",
|
||||||
|
"title",
|
||||||
|
gettext("Choose a Date"),
|
||||||
|
);
|
||||||
|
cal_link.setAttribute("aria-labelledby", calIconId);
|
||||||
|
shortcuts_span.appendChild(document.createTextNode("\u00A0"));
|
||||||
|
shortcuts_span.appendChild(today_link);
|
||||||
|
shortcuts_span.appendChild(
|
||||||
|
document.createTextNode("\u00A0|\u00A0"),
|
||||||
|
);
|
||||||
|
shortcuts_span.appendChild(cal_link);
|
||||||
|
|
||||||
|
// Create calendarbox div.
|
||||||
|
//
|
||||||
|
// Markup looks like:
|
||||||
|
//
|
||||||
|
// <dialog id="calendarbox3" class="calendarbox module"
|
||||||
|
// role="dialog" aria-label="Choose a Date">
|
||||||
|
// <div>
|
||||||
|
// <a href="#" class="calendarnav-previous"
|
||||||
|
// aria-label="Previous May">‹</a>
|
||||||
|
// <a href="#" class="calendarnav-next"
|
||||||
|
// aria-label="Next July">›</a>
|
||||||
|
// </div>
|
||||||
|
// <div class="calendar" id="calendarin3">
|
||||||
|
// <!-- (cal) -->
|
||||||
|
// </div>
|
||||||
|
// <div class="calendar-shortcuts">
|
||||||
|
// <a href="#" role="button"
|
||||||
|
// aria-label="Yesterday (June 14, 2025)">Yesterday</a>
|
||||||
|
// |
|
||||||
|
// <a href="#" role="button"
|
||||||
|
// aria-label="Today (June 15, 2025)">Today</a>
|
||||||
|
// |
|
||||||
|
// <a href="#" role="button"
|
||||||
|
// aria-label="Tomorrow (June 16, 2025)">Tomorrow</a>
|
||||||
|
// </div>
|
||||||
|
// <p class="calendar-cancel">
|
||||||
|
// <a href="#" role="button" aria-label="Close Calendar">Cancel</a>
|
||||||
|
// </p>
|
||||||
|
// </dialog>
|
||||||
|
const cal_box = document.createElement("dialog");
|
||||||
|
cal_box.className = "calendarbox module";
|
||||||
|
cal_box.id = DateTimeShortcuts.calendarDivName1 + num;
|
||||||
|
cal_box.setAttribute("role", "dialog");
|
||||||
|
cal_box.setAttribute("aria-labelledby", calIconId);
|
||||||
|
document.body.appendChild(cal_box);
|
||||||
|
cal_box.addEventListener("click", function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
// Handle arrow key navigation within the calendar
|
||||||
|
cal_box.addEventListener("keydown", function (event) {
|
||||||
|
const focused = cal_box.querySelector("a:focus");
|
||||||
|
if (!focused) return;
|
||||||
|
const cells = Array.from(cal_box.querySelectorAll("td a"));
|
||||||
|
const currentIndex = cells.indexOf(focused);
|
||||||
|
if (currentIndex === -1) return;
|
||||||
|
|
||||||
|
const ltr =
|
||||||
|
window.getComputedStyle(document.body).direction !== "rtl";
|
||||||
|
const forward = ltr
|
||||||
|
? event.key === "ArrowRight"
|
||||||
|
: event.key === "ArrowLeft";
|
||||||
|
const backward = ltr
|
||||||
|
? event.key === "ArrowLeft"
|
||||||
|
: event.key === "ArrowRight";
|
||||||
|
let nextCell = null;
|
||||||
|
const cellsPerRow = 7;
|
||||||
|
|
||||||
|
if (forward && currentIndex < cells.length - 1) {
|
||||||
|
nextCell = cells[currentIndex + 1];
|
||||||
|
} else if (backward && currentIndex > 0) {
|
||||||
|
nextCell = cells[currentIndex - 1];
|
||||||
|
} else if (
|
||||||
|
event.key === "ArrowDown" &&
|
||||||
|
currentIndex + cellsPerRow < cells.length
|
||||||
|
) {
|
||||||
|
nextCell = cells[currentIndex + cellsPerRow];
|
||||||
|
} else if (
|
||||||
|
event.key === "ArrowUp" &&
|
||||||
|
currentIndex - cellsPerRow >= 0
|
||||||
|
) {
|
||||||
|
nextCell = cells[currentIndex - cellsPerRow];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextCell) {
|
||||||
|
event.preventDefault();
|
||||||
|
nextCell.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// next-prev links
|
||||||
|
const cal_nav = quickElement("div", cal_box);
|
||||||
|
const cal_nav_prev = quickElement("a", cal_nav, "<", "href", "#");
|
||||||
|
cal_nav_prev.className = "calendarnav-previous";
|
||||||
|
cal_nav_prev.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.drawPrev(num);
|
||||||
|
});
|
||||||
|
|
||||||
|
const cal_nav_next = quickElement("a", cal_nav, ">", "href", "#");
|
||||||
|
cal_nav_next.className = "calendarnav-next";
|
||||||
|
cal_nav_next.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.drawNext(num);
|
||||||
|
});
|
||||||
|
|
||||||
|
// main box
|
||||||
|
const cal_main = quickElement(
|
||||||
|
"div",
|
||||||
|
cal_box,
|
||||||
|
"",
|
||||||
|
"id",
|
||||||
|
DateTimeShortcuts.calendarDivName2 + num,
|
||||||
|
);
|
||||||
|
cal_main.className = "calendar";
|
||||||
|
DateTimeShortcuts.calendars[num] = new Calendar(
|
||||||
|
DateTimeShortcuts.calendarDivName2 + num,
|
||||||
|
DateTimeShortcuts.handleCalendarCallback(num),
|
||||||
|
);
|
||||||
|
DateTimeShortcuts.calendars[num].drawCurrent();
|
||||||
|
|
||||||
|
// calendar shortcuts
|
||||||
|
const shortcuts = quickElement("div", cal_box);
|
||||||
|
shortcuts.className = "calendar-shortcuts";
|
||||||
|
let day_link = quickElement(
|
||||||
|
"a",
|
||||||
|
shortcuts,
|
||||||
|
gettext("Yesterday"),
|
||||||
|
"role",
|
||||||
|
"button",
|
||||||
|
"href",
|
||||||
|
"#",
|
||||||
|
);
|
||||||
|
day_link.setAttribute(
|
||||||
|
"aria-label",
|
||||||
|
interpolate(
|
||||||
|
gettext("Yesterday (%(date)s)"),
|
||||||
|
{ date: getFormattedDate(-1) },
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
day_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.handleCalendarQuickLink(num, -1);
|
||||||
|
});
|
||||||
|
shortcuts.appendChild(document.createTextNode("\u00A0|\u00A0"));
|
||||||
|
day_link = quickElement(
|
||||||
|
"a",
|
||||||
|
shortcuts,
|
||||||
|
gettext("Today"),
|
||||||
|
"role",
|
||||||
|
"button",
|
||||||
|
"href",
|
||||||
|
"#",
|
||||||
|
);
|
||||||
|
day_link.setAttribute(
|
||||||
|
"aria-label",
|
||||||
|
interpolate(
|
||||||
|
gettext("Today (%(date)s)"),
|
||||||
|
{ date: getFormattedDate(0) },
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
day_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.handleCalendarQuickLink(num, 0);
|
||||||
|
});
|
||||||
|
shortcuts.appendChild(document.createTextNode("\u00A0|\u00A0"));
|
||||||
|
day_link = quickElement(
|
||||||
|
"a",
|
||||||
|
shortcuts,
|
||||||
|
gettext("Tomorrow"),
|
||||||
|
"role",
|
||||||
|
"button",
|
||||||
|
"href",
|
||||||
|
"#",
|
||||||
|
);
|
||||||
|
day_link.setAttribute(
|
||||||
|
"aria-label",
|
||||||
|
interpolate(
|
||||||
|
gettext("Tomorrow (%(date)s)"),
|
||||||
|
{ date: getFormattedDate(1) },
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
day_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.handleCalendarQuickLink(num, +1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// cancel bar
|
||||||
|
const cancel_p = quickElement("p", cal_box);
|
||||||
|
cancel_p.className = "calendar-cancel";
|
||||||
|
const cancel_link = quickElement(
|
||||||
|
"a",
|
||||||
|
cancel_p,
|
||||||
|
gettext("Cancel"),
|
||||||
|
"role",
|
||||||
|
"button",
|
||||||
|
"href",
|
||||||
|
"#",
|
||||||
|
);
|
||||||
|
cancel_link.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
DateTimeShortcuts.dismissCalendar(num);
|
||||||
|
});
|
||||||
|
document.addEventListener("keyup", function (event) {
|
||||||
|
if (event.key === "Escape") {
|
||||||
|
// ESC key closes popup
|
||||||
|
DateTimeShortcuts.dismissCalendar(num);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
updateNavAriaLabels: function (num) {
|
||||||
|
const cal = DateTimeShortcuts.calendars[num];
|
||||||
|
const cal_box = document.getElementById(
|
||||||
|
DateTimeShortcuts.calendarDivName1 + num,
|
||||||
|
);
|
||||||
|
const prevMonth =
|
||||||
|
CalendarNamespace.monthsOfYear[(cal.currentMonth + 10) % 12];
|
||||||
|
const prevYear =
|
||||||
|
cal.currentMonth === 1 ? cal.currentYear - 1 : cal.currentYear;
|
||||||
|
cal_box
|
||||||
|
.querySelector(".calendarnav-previous")
|
||||||
|
.setAttribute(
|
||||||
|
"aria-label",
|
||||||
|
interpolate(
|
||||||
|
gettext("Previous (%(month)s %(year)s)"),
|
||||||
|
{ month: prevMonth, year: prevYear },
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const nextMonth =
|
||||||
|
CalendarNamespace.monthsOfYear[cal.currentMonth % 12];
|
||||||
|
const nextYear =
|
||||||
|
cal.currentMonth === 12 ? cal.currentYear + 1 : cal.currentYear;
|
||||||
|
cal_box
|
||||||
|
.querySelector(".calendarnav-next")
|
||||||
|
.setAttribute(
|
||||||
|
"aria-label",
|
||||||
|
interpolate(
|
||||||
|
gettext("Next (%(month)s %(year)s)"),
|
||||||
|
{ month: nextMonth, year: nextYear },
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
openCalendar: function (num) {
|
||||||
|
const cal_box = document.getElementById(
|
||||||
|
DateTimeShortcuts.calendarDivName1 + num,
|
||||||
|
);
|
||||||
|
const cal_link = document.getElementById(
|
||||||
|
DateTimeShortcuts.calendarLinkName + num,
|
||||||
|
);
|
||||||
|
const inp = DateTimeShortcuts.calendarInputs[num];
|
||||||
|
|
||||||
|
// Determine if the current value in the input has a valid date.
|
||||||
|
// If so, draw the calendar with that date's year and month.
|
||||||
|
if (inp.value) {
|
||||||
|
const format = get_format("DATE_INPUT_FORMATS")[0];
|
||||||
|
const selected = inp.value.strptime(format);
|
||||||
|
const year = selected.getUTCFullYear();
|
||||||
|
const month = selected.getUTCMonth() + 1;
|
||||||
|
const re = /\d{4}/;
|
||||||
|
if (re.test(year.toString()) && month >= 1 && month <= 12) {
|
||||||
|
DateTimeShortcuts.calendars[num].drawDate(
|
||||||
|
month,
|
||||||
|
year,
|
||||||
|
selected,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recalculate the calendarbox position
|
||||||
|
// is it left-to-right or right-to-left layout ?
|
||||||
|
if (window.getComputedStyle(document.body).direction !== "rtl") {
|
||||||
|
cal_box.style.left = findPosX(cal_link) + 17 + "px";
|
||||||
|
} else {
|
||||||
|
// since style's width is in em, it'd be tough to calculate
|
||||||
|
// px value of it. let's use an estimated px for now
|
||||||
|
cal_box.style.right = findPosX(cal_link) - 180 + "px";
|
||||||
|
}
|
||||||
|
cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + "px";
|
||||||
|
|
||||||
|
cal_box.showModal();
|
||||||
|
DateTimeShortcuts.updateNavAriaLabels(num);
|
||||||
|
const calendarDiv = cal_box.querySelector(
|
||||||
|
"#" + DateTimeShortcuts.calendarDivName2 + num,
|
||||||
|
);
|
||||||
|
if (calendarDiv) {
|
||||||
|
// Focus on selected date, today, or first available date
|
||||||
|
const focusElement =
|
||||||
|
cal_box.querySelector("td.selected a") ||
|
||||||
|
cal_box.querySelector("td.today a") ||
|
||||||
|
cal_box.querySelector("td a");
|
||||||
|
focusElement?.focus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissCalendar: function (num) {
|
||||||
|
document
|
||||||
|
.getElementById(DateTimeShortcuts.calendarDivName1 + num)
|
||||||
|
.close();
|
||||||
|
},
|
||||||
|
drawPrev: function (num) {
|
||||||
|
DateTimeShortcuts.calendars[num].drawPreviousMonth();
|
||||||
|
DateTimeShortcuts.updateNavAriaLabels(num);
|
||||||
|
},
|
||||||
|
drawNext: function (num) {
|
||||||
|
DateTimeShortcuts.calendars[num].drawNextMonth();
|
||||||
|
DateTimeShortcuts.updateNavAriaLabels(num);
|
||||||
|
},
|
||||||
|
handleCalendarCallback: function (num) {
|
||||||
|
const format = get_format("DATE_INPUT_FORMATS")[0];
|
||||||
|
return function (y, m, d) {
|
||||||
|
DateTimeShortcuts.calendarInputs[num].value = new Date(
|
||||||
|
y,
|
||||||
|
m - 1,
|
||||||
|
d,
|
||||||
|
).strftime(format);
|
||||||
|
DateTimeShortcuts.calendarInputs[num].focus();
|
||||||
|
DateTimeShortcuts.dismissCalendar(num);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
handleCalendarQuickLink: function (num, offset) {
|
||||||
|
const d = DateTimeShortcuts.now();
|
||||||
|
d.setDate(d.getDate() + offset);
|
||||||
|
DateTimeShortcuts.calendarInputs[num].value = d.strftime(
|
||||||
|
get_format("DATE_INPUT_FORMATS")[0],
|
||||||
|
);
|
||||||
|
DateTimeShortcuts.calendarInputs[num].focus();
|
||||||
|
DateTimeShortcuts.dismissCalendar(num);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("load", DateTimeShortcuts.init);
|
||||||
|
window.DateTimeShortcuts = DateTimeShortcuts;
|
||||||
|
}
|
||||||
332
staticfiles/admin/js/admin/RelatedObjectLookups.js
Normal file
|
|
@ -0,0 +1,332 @@
|
||||||
|
/*global SelectBox, interpolate*/
|
||||||
|
// Handles related-objects functionality: lookup link for raw_id_fields
|
||||||
|
// and Add Another links.
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const $ = django.jQuery;
|
||||||
|
let popupIndex = 0;
|
||||||
|
const relatedWindows = [];
|
||||||
|
|
||||||
|
function dismissChildPopups() {
|
||||||
|
relatedWindows.forEach(function (win) {
|
||||||
|
if (!win.closed) {
|
||||||
|
win.dismissChildPopups();
|
||||||
|
win.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPopupIndex() {
|
||||||
|
if (document.getElementsByName("_popup").length > 0) {
|
||||||
|
const index = window.name.lastIndexOf("__") + 2;
|
||||||
|
popupIndex = parseInt(window.name.substring(index));
|
||||||
|
} else {
|
||||||
|
popupIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addPopupIndex(name) {
|
||||||
|
return name + "__" + (popupIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removePopupIndex(name) {
|
||||||
|
return name.replace(new RegExp("__" + (popupIndex + 1) + "$"), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function showAdminPopup(triggeringLink, name_regexp, add_popup) {
|
||||||
|
const name = addPopupIndex(triggeringLink.id.replace(name_regexp, ""));
|
||||||
|
const href = new URL(triggeringLink.href);
|
||||||
|
if (add_popup) {
|
||||||
|
href.searchParams.set("_popup", 1);
|
||||||
|
}
|
||||||
|
const win = window.open(
|
||||||
|
href,
|
||||||
|
name,
|
||||||
|
"height=500,width=800,resizable=yes,scrollbars=yes",
|
||||||
|
);
|
||||||
|
relatedWindows.push(win);
|
||||||
|
win.focus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showRelatedObjectLookupPopup(triggeringLink) {
|
||||||
|
return showAdminPopup(triggeringLink, /^lookup_/, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismissRelatedLookupPopup(win, chosenId) {
|
||||||
|
const name = removePopupIndex(win.name);
|
||||||
|
const elem = document.getElementById(name);
|
||||||
|
if (
|
||||||
|
elem.classList.contains("vManyToManyRawIdAdminField") &&
|
||||||
|
elem.value
|
||||||
|
) {
|
||||||
|
elem.value += "," + chosenId;
|
||||||
|
} else {
|
||||||
|
elem.value = chosenId;
|
||||||
|
}
|
||||||
|
$(elem).trigger("change");
|
||||||
|
const index = relatedWindows.indexOf(win);
|
||||||
|
if (index > -1) {
|
||||||
|
relatedWindows.splice(index, 1);
|
||||||
|
}
|
||||||
|
win.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showRelatedObjectPopup(triggeringLink) {
|
||||||
|
return showAdminPopup(triggeringLink, /^(change|add|delete)_/, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateRelatedObjectLinks(triggeringLink) {
|
||||||
|
const $this = $(triggeringLink);
|
||||||
|
const siblings = $this.nextAll(
|
||||||
|
".view-related, .change-related, .delete-related",
|
||||||
|
);
|
||||||
|
if (!siblings.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const value = $this.val();
|
||||||
|
if (value) {
|
||||||
|
siblings.each(function () {
|
||||||
|
const elm = $(this);
|
||||||
|
elm.attr(
|
||||||
|
"href",
|
||||||
|
elm.attr("data-href-template").replace("__fk__", value),
|
||||||
|
);
|
||||||
|
elm.removeAttr("aria-disabled");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
siblings.removeAttr("href");
|
||||||
|
siblings.attr("aria-disabled", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateRelatedSelectsOptions(
|
||||||
|
currentSelect,
|
||||||
|
win,
|
||||||
|
objId,
|
||||||
|
newRepr,
|
||||||
|
newId,
|
||||||
|
skipIds = [],
|
||||||
|
) {
|
||||||
|
// After create/edit a model from the options next to the current
|
||||||
|
// select (+ or :pencil:) update ForeignKey PK of the rest of selects
|
||||||
|
// in the page.
|
||||||
|
|
||||||
|
const path = win.location.pathname;
|
||||||
|
// Extract the model from the popup url '.../<model>/add/' or
|
||||||
|
// '.../<model>/<id>/change/' depending the action (add or change).
|
||||||
|
const modelName =
|
||||||
|
path.split("/")[path.split("/").length - (objId ? 4 : 3)];
|
||||||
|
// Select elements with a specific model reference and context of "available-source".
|
||||||
|
const selectsRelated = document.querySelectorAll(
|
||||||
|
`[data-model-ref="${modelName}"] [data-context="available-source"]`,
|
||||||
|
);
|
||||||
|
|
||||||
|
selectsRelated.forEach(function (select) {
|
||||||
|
if (
|
||||||
|
currentSelect === select ||
|
||||||
|
(skipIds && skipIds.includes(select.id))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let option = select.querySelector(`option[value="${objId}"]`);
|
||||||
|
|
||||||
|
if (!option) {
|
||||||
|
option = new Option(newRepr, newId);
|
||||||
|
select.options.add(option);
|
||||||
|
// Update SelectBox cache for related fields.
|
||||||
|
if (
|
||||||
|
window.SelectBox !== undefined &&
|
||||||
|
!SelectBox.cache[currentSelect.id] &&
|
||||||
|
// Only if SelectBox is managing that field.
|
||||||
|
SelectBox.cache[select.id]
|
||||||
|
) {
|
||||||
|
SelectBox.add_to_cache(select.id, option);
|
||||||
|
// Sort if there are any groups present
|
||||||
|
if (SelectBox.cache[select.id].some((item) => item.group)) {
|
||||||
|
SelectBox.sort(select.id);
|
||||||
|
}
|
||||||
|
SelectBox.redisplay(select.id);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
option.textContent = newRepr;
|
||||||
|
option.value = newId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismissAddRelatedObjectPopup(win, newId, newRepr, optgroup) {
|
||||||
|
const name = removePopupIndex(win.name);
|
||||||
|
const elem = document.getElementById(name);
|
||||||
|
if (elem) {
|
||||||
|
const elemName = elem.nodeName.toUpperCase();
|
||||||
|
if (elemName === "SELECT") {
|
||||||
|
elem.options[elem.options.length] = new Option(
|
||||||
|
newRepr,
|
||||||
|
newId,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
updateRelatedSelectsOptions(elem, win, null, newRepr, newId);
|
||||||
|
} else if (elemName === "INPUT") {
|
||||||
|
if (
|
||||||
|
elem.classList.contains("vManyToManyRawIdAdminField") &&
|
||||||
|
elem.value
|
||||||
|
) {
|
||||||
|
elem.value += "," + newId;
|
||||||
|
} else {
|
||||||
|
elem.value = newId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Trigger a change event to update related links if required.
|
||||||
|
$(elem).trigger("change");
|
||||||
|
} else {
|
||||||
|
const toId = name + "_to";
|
||||||
|
const toElem = document.getElementById(toId);
|
||||||
|
const newOption = new Option(newRepr, newId);
|
||||||
|
newOption.group = optgroup;
|
||||||
|
SelectBox.add_to_cache(toId, newOption);
|
||||||
|
// Sort if there are any groups present
|
||||||
|
if (SelectBox.cache[toId].some((item) => item.group)) {
|
||||||
|
SelectBox.sort(toId);
|
||||||
|
}
|
||||||
|
SelectBox.redisplay(toId);
|
||||||
|
if (toElem && toElem.nodeName.toUpperCase() === "SELECT") {
|
||||||
|
const skipIds = [name + "_from"];
|
||||||
|
updateRelatedSelectsOptions(
|
||||||
|
toElem,
|
||||||
|
win,
|
||||||
|
null,
|
||||||
|
newRepr,
|
||||||
|
newId,
|
||||||
|
skipIds,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const index = relatedWindows.indexOf(win);
|
||||||
|
if (index > -1) {
|
||||||
|
relatedWindows.splice(index, 1);
|
||||||
|
}
|
||||||
|
win.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) {
|
||||||
|
const id = removePopupIndex(win.name.replace(/^edit_/, ""));
|
||||||
|
const selectsSelector = interpolate("#%s, #%s_from, #%s_to", [
|
||||||
|
id,
|
||||||
|
id,
|
||||||
|
id,
|
||||||
|
]);
|
||||||
|
const selects = $(selectsSelector);
|
||||||
|
selects
|
||||||
|
.find("option")
|
||||||
|
.each(function () {
|
||||||
|
if (this.value === objId) {
|
||||||
|
this.textContent = newRepr;
|
||||||
|
this.value = newId;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.trigger("change");
|
||||||
|
updateRelatedSelectsOptions(selects[0], win, objId, newRepr, newId);
|
||||||
|
selects
|
||||||
|
.next()
|
||||||
|
.find(".select2-selection__rendered")
|
||||||
|
.each(function () {
|
||||||
|
// The element can have a clear button as a child.
|
||||||
|
// Use the lastChild to modify only the displayed value.
|
||||||
|
this.lastChild.textContent = newRepr;
|
||||||
|
this.title = newRepr;
|
||||||
|
});
|
||||||
|
const index = relatedWindows.indexOf(win);
|
||||||
|
if (index > -1) {
|
||||||
|
relatedWindows.splice(index, 1);
|
||||||
|
}
|
||||||
|
win.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismissDeleteRelatedObjectPopup(win, objId) {
|
||||||
|
const id = removePopupIndex(win.name.replace(/^delete_/, ""));
|
||||||
|
const selectsSelector = interpolate("#%s, #%s_from, #%s_to", [
|
||||||
|
id,
|
||||||
|
id,
|
||||||
|
id,
|
||||||
|
]);
|
||||||
|
const selects = $(selectsSelector);
|
||||||
|
selects
|
||||||
|
.find("option")
|
||||||
|
.each(function () {
|
||||||
|
if (this.value === objId) {
|
||||||
|
$(this).remove();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.trigger("change");
|
||||||
|
const index = relatedWindows.indexOf(win);
|
||||||
|
if (index > -1) {
|
||||||
|
relatedWindows.splice(index, 1);
|
||||||
|
}
|
||||||
|
win.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.showRelatedObjectLookupPopup = showRelatedObjectLookupPopup;
|
||||||
|
window.dismissRelatedLookupPopup = dismissRelatedLookupPopup;
|
||||||
|
window.showRelatedObjectPopup = showRelatedObjectPopup;
|
||||||
|
window.updateRelatedObjectLinks = updateRelatedObjectLinks;
|
||||||
|
window.dismissAddRelatedObjectPopup = dismissAddRelatedObjectPopup;
|
||||||
|
window.dismissChangeRelatedObjectPopup = dismissChangeRelatedObjectPopup;
|
||||||
|
window.dismissDeleteRelatedObjectPopup = dismissDeleteRelatedObjectPopup;
|
||||||
|
window.dismissChildPopups = dismissChildPopups;
|
||||||
|
window.relatedWindows = relatedWindows;
|
||||||
|
|
||||||
|
// Kept for backward compatibility
|
||||||
|
window.showAddAnotherPopup = showRelatedObjectPopup;
|
||||||
|
window.dismissAddAnotherPopup = dismissAddRelatedObjectPopup;
|
||||||
|
|
||||||
|
window.addEventListener("pagehide", function (evt) {
|
||||||
|
window.dismissChildPopups();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
setPopupIndex();
|
||||||
|
$("a[data-popup-opener]").on("click", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
opener.dismissRelatedLookupPopup(
|
||||||
|
window,
|
||||||
|
$(this).data("popup-opener"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
$("body").on(
|
||||||
|
"click",
|
||||||
|
'.related-widget-wrapper-link[data-popup="yes"]',
|
||||||
|
function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (this.href) {
|
||||||
|
const event = $.Event("django:show-related", {
|
||||||
|
href: this.href,
|
||||||
|
});
|
||||||
|
$(this).trigger(event);
|
||||||
|
if (!event.isDefaultPrevented()) {
|
||||||
|
showRelatedObjectPopup(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
$("body").on("change", ".related-widget-wrapper select", function (e) {
|
||||||
|
const event = $.Event("django:update-related");
|
||||||
|
$(this).trigger(event);
|
||||||
|
if (!event.isDefaultPrevented()) {
|
||||||
|
updateRelatedObjectLinks(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$(".related-widget-wrapper select").trigger("change");
|
||||||
|
$("body").on("click", ".related-lookup", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const event = $.Event("django:lookup-related");
|
||||||
|
$(this).trigger(event);
|
||||||
|
if (!event.isDefaultPrevented()) {
|
||||||
|
showRelatedObjectLookupPopup(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
33
staticfiles/admin/js/autocomplete.js
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const $ = django.jQuery;
|
||||||
|
|
||||||
|
$.fn.djangoAdminSelect2 = function () {
|
||||||
|
$.each(this, function (i, element) {
|
||||||
|
$(element).select2({
|
||||||
|
ajax: {
|
||||||
|
data: (params) => {
|
||||||
|
return {
|
||||||
|
term: params.term,
|
||||||
|
page: params.page,
|
||||||
|
app_label: element.dataset.appLabel,
|
||||||
|
model_name: element.dataset.modelName,
|
||||||
|
field_name: element.dataset.fieldName,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
// Initialize all autocomplete widgets except the one in the template
|
||||||
|
// form used when a new formset is added.
|
||||||
|
$(".admin-autocomplete").not("[name*=__prefix__]").djangoAdminSelect2();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("formset:added", (event) => {
|
||||||
|
$(event.target).find(".admin-autocomplete").djangoAdminSelect2();
|
||||||
|
});
|
||||||
|
}
|
||||||
338
staticfiles/admin/js/calendar.js
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
/*global gettext, pgettext, get_format, interpolate, quickElement, removeChildren*/
|
||||||
|
/*
|
||||||
|
calendar.js - Calendar functions by Adrian Holovaty
|
||||||
|
depends on core.js for utility functions like removeChildren or quickElement
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
// CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
|
||||||
|
const CalendarNamespace = {
|
||||||
|
monthsOfYear: [
|
||||||
|
gettext("January"),
|
||||||
|
gettext("February"),
|
||||||
|
gettext("March"),
|
||||||
|
gettext("April"),
|
||||||
|
gettext("May"),
|
||||||
|
gettext("June"),
|
||||||
|
gettext("July"),
|
||||||
|
gettext("August"),
|
||||||
|
gettext("September"),
|
||||||
|
gettext("October"),
|
||||||
|
gettext("November"),
|
||||||
|
gettext("December"),
|
||||||
|
],
|
||||||
|
monthsOfYearAbbrev: [
|
||||||
|
pgettext("abbrev. month January", "Jan"),
|
||||||
|
pgettext("abbrev. month February", "Feb"),
|
||||||
|
pgettext("abbrev. month March", "Mar"),
|
||||||
|
pgettext("abbrev. month April", "Apr"),
|
||||||
|
pgettext("abbrev. month May", "May"),
|
||||||
|
pgettext("abbrev. month June", "Jun"),
|
||||||
|
pgettext("abbrev. month July", "Jul"),
|
||||||
|
pgettext("abbrev. month August", "Aug"),
|
||||||
|
pgettext("abbrev. month September", "Sep"),
|
||||||
|
pgettext("abbrev. month October", "Oct"),
|
||||||
|
pgettext("abbrev. month November", "Nov"),
|
||||||
|
pgettext("abbrev. month December", "Dec"),
|
||||||
|
],
|
||||||
|
daysOfWeek: [
|
||||||
|
gettext("Sunday"),
|
||||||
|
gettext("Monday"),
|
||||||
|
gettext("Tuesday"),
|
||||||
|
gettext("Wednesday"),
|
||||||
|
gettext("Thursday"),
|
||||||
|
gettext("Friday"),
|
||||||
|
gettext("Saturday"),
|
||||||
|
],
|
||||||
|
daysOfWeekAbbrev: [
|
||||||
|
pgettext("abbrev. day Sunday", "Sun"),
|
||||||
|
pgettext("abbrev. day Monday", "Mon"),
|
||||||
|
pgettext("abbrev. day Tuesday", "Tue"),
|
||||||
|
pgettext("abbrev. day Wednesday", "Wed"),
|
||||||
|
pgettext("abbrev. day Thursday", "Thur"),
|
||||||
|
pgettext("abbrev. day Friday", "Fri"),
|
||||||
|
pgettext("abbrev. day Saturday", "Sat"),
|
||||||
|
],
|
||||||
|
daysOfWeekInitial: [
|
||||||
|
pgettext("one letter Sunday", "S"),
|
||||||
|
pgettext("one letter Monday", "M"),
|
||||||
|
pgettext("one letter Tuesday", "T"),
|
||||||
|
pgettext("one letter Wednesday", "W"),
|
||||||
|
pgettext("one letter Thursday", "T"),
|
||||||
|
pgettext("one letter Friday", "F"),
|
||||||
|
pgettext("one letter Saturday", "S"),
|
||||||
|
],
|
||||||
|
firstDayOfWeek: parseInt(get_format("FIRST_DAY_OF_WEEK")),
|
||||||
|
isLeapYear: function (year) {
|
||||||
|
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
||||||
|
},
|
||||||
|
getDaysInMonth: function (month, year) {
|
||||||
|
let days;
|
||||||
|
if (
|
||||||
|
month === 1 ||
|
||||||
|
month === 3 ||
|
||||||
|
month === 5 ||
|
||||||
|
month === 7 ||
|
||||||
|
month === 8 ||
|
||||||
|
month === 10 ||
|
||||||
|
month === 12
|
||||||
|
) {
|
||||||
|
days = 31;
|
||||||
|
} else if (
|
||||||
|
month === 4 ||
|
||||||
|
month === 6 ||
|
||||||
|
month === 9 ||
|
||||||
|
month === 11
|
||||||
|
) {
|
||||||
|
days = 30;
|
||||||
|
} else if (month === 2 && CalendarNamespace.isLeapYear(year)) {
|
||||||
|
days = 29;
|
||||||
|
} else {
|
||||||
|
days = 28;
|
||||||
|
}
|
||||||
|
return days;
|
||||||
|
},
|
||||||
|
formatDate: function (day, month, year) {
|
||||||
|
return interpolate(
|
||||||
|
gettext("%(month)s %(day)s, %(year)s"),
|
||||||
|
{
|
||||||
|
month: CalendarNamespace.monthsOfYear[month - 1],
|
||||||
|
day: day,
|
||||||
|
year: year,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// Return the current date adjusted for the server timezone.
|
||||||
|
serverToday: function () {
|
||||||
|
const today = new Date();
|
||||||
|
const serverOffset = document.body.dataset.adminUtcOffset;
|
||||||
|
if (serverOffset) {
|
||||||
|
const localOffset = today.getTimezoneOffset() * -60;
|
||||||
|
today.setTime(
|
||||||
|
today.getTime() + 1000 * (serverOffset - localOffset),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return today;
|
||||||
|
},
|
||||||
|
draw: function (month, year, div_id, callback, selected) {
|
||||||
|
// month = 1-12, year = 1-9999
|
||||||
|
const today = CalendarNamespace.serverToday();
|
||||||
|
const todayDay = today.getDate();
|
||||||
|
const todayMonth = today.getMonth() + 1;
|
||||||
|
const todayYear = today.getFullYear();
|
||||||
|
let todayClass = "";
|
||||||
|
|
||||||
|
// Use UTC functions here because the date field does not contain time
|
||||||
|
// and using the UTC function variants prevent the local time offset
|
||||||
|
// from altering the date, specifically the day field. For example:
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// var x = new Date('2013-10-02');
|
||||||
|
// var day = x.getDate();
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// The day variable above will be 1 instead of 2 in, say, US Pacific time
|
||||||
|
// zone.
|
||||||
|
let isSelectedMonth = false;
|
||||||
|
if (typeof selected !== "undefined") {
|
||||||
|
isSelectedMonth =
|
||||||
|
selected.getUTCFullYear() === year &&
|
||||||
|
selected.getUTCMonth() + 1 === month;
|
||||||
|
}
|
||||||
|
|
||||||
|
month = parseInt(month);
|
||||||
|
year = parseInt(year);
|
||||||
|
const calDiv = document.getElementById(div_id);
|
||||||
|
removeChildren(calDiv);
|
||||||
|
const calTable = document.createElement("table");
|
||||||
|
quickElement(
|
||||||
|
"caption",
|
||||||
|
calTable,
|
||||||
|
CalendarNamespace.monthsOfYear[month - 1] + " " + year,
|
||||||
|
);
|
||||||
|
const tableBody = quickElement("tbody", calTable);
|
||||||
|
|
||||||
|
// Draw days-of-week header
|
||||||
|
let tableRow = quickElement("tr", tableBody);
|
||||||
|
for (let i = 0; i < 7; i++) {
|
||||||
|
const dayAbbrev =
|
||||||
|
CalendarNamespace.daysOfWeekAbbrev[
|
||||||
|
(i + CalendarNamespace.firstDayOfWeek) % 7
|
||||||
|
];
|
||||||
|
const dayInitial =
|
||||||
|
CalendarNamespace.daysOfWeekInitial[
|
||||||
|
(i + CalendarNamespace.firstDayOfWeek) % 7
|
||||||
|
];
|
||||||
|
const th = quickElement("th", tableRow, dayInitial);
|
||||||
|
th.setAttribute("aria-label", dayAbbrev);
|
||||||
|
}
|
||||||
|
|
||||||
|
const startingPos = new Date(
|
||||||
|
year,
|
||||||
|
month - 1,
|
||||||
|
1 - CalendarNamespace.firstDayOfWeek,
|
||||||
|
).getDay();
|
||||||
|
const days = CalendarNamespace.getDaysInMonth(month, year);
|
||||||
|
|
||||||
|
let nonDayCell;
|
||||||
|
|
||||||
|
// Draw blanks before first of month
|
||||||
|
tableRow = quickElement("tr", tableBody);
|
||||||
|
for (let i = 0; i < startingPos; i++) {
|
||||||
|
nonDayCell = quickElement("td", tableRow, " ");
|
||||||
|
nonDayCell.className = "nonday";
|
||||||
|
}
|
||||||
|
|
||||||
|
function calendarMonth(y, m) {
|
||||||
|
function onClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
callback(y, m, this.textContent);
|
||||||
|
}
|
||||||
|
return onClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw days of month
|
||||||
|
let currentDay = 1;
|
||||||
|
for (let i = startingPos; currentDay <= days; i++) {
|
||||||
|
if (i % 7 === 0 && currentDay !== 1) {
|
||||||
|
tableRow = quickElement("tr", tableBody);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
currentDay === todayDay &&
|
||||||
|
month === todayMonth &&
|
||||||
|
year === todayYear
|
||||||
|
) {
|
||||||
|
todayClass = "today";
|
||||||
|
} else {
|
||||||
|
todayClass = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// use UTC function; see above for explanation.
|
||||||
|
if (isSelectedMonth && currentDay === selected.getUTCDate()) {
|
||||||
|
if (todayClass !== "") {
|
||||||
|
todayClass += " ";
|
||||||
|
}
|
||||||
|
todayClass += "selected";
|
||||||
|
}
|
||||||
|
|
||||||
|
const cell = quickElement(
|
||||||
|
"td",
|
||||||
|
tableRow,
|
||||||
|
"",
|
||||||
|
"class",
|
||||||
|
todayClass,
|
||||||
|
);
|
||||||
|
const link = quickElement(
|
||||||
|
"a",
|
||||||
|
cell,
|
||||||
|
currentDay,
|
||||||
|
"role",
|
||||||
|
"button",
|
||||||
|
"href",
|
||||||
|
"#",
|
||||||
|
);
|
||||||
|
let ariaLabel = CalendarNamespace.formatDate(
|
||||||
|
currentDay,
|
||||||
|
month,
|
||||||
|
year,
|
||||||
|
);
|
||||||
|
const isToday =
|
||||||
|
currentDay === todayDay &&
|
||||||
|
month === todayMonth &&
|
||||||
|
year === todayYear;
|
||||||
|
const isSelected =
|
||||||
|
isSelectedMonth && currentDay === selected.getUTCDate();
|
||||||
|
if (isToday && isSelected) {
|
||||||
|
ariaLabel = interpolate(
|
||||||
|
gettext("%s (today, current selection)"),
|
||||||
|
[ariaLabel],
|
||||||
|
);
|
||||||
|
} else if (isToday) {
|
||||||
|
ariaLabel = interpolate(gettext("%s (today)"), [ariaLabel]);
|
||||||
|
} else if (isSelected) {
|
||||||
|
ariaLabel = interpolate(gettext("%s (current selection)"), [
|
||||||
|
ariaLabel,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
link.setAttribute("aria-label", ariaLabel);
|
||||||
|
link.addEventListener("click", calendarMonth(year, month));
|
||||||
|
currentDay++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw blanks after end of month (optional, but makes for valid code)
|
||||||
|
while (tableRow.childNodes.length < 7) {
|
||||||
|
nonDayCell = quickElement("td", tableRow, " ");
|
||||||
|
nonDayCell.className = "nonday";
|
||||||
|
}
|
||||||
|
|
||||||
|
calDiv.appendChild(calTable);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calendar -- A calendar instance
|
||||||
|
function Calendar(div_id, callback, selected) {
|
||||||
|
// div_id (string) is the ID of the element in which the calendar will
|
||||||
|
// be displayed
|
||||||
|
// callback (string) is the name of a JavaScript function that will be
|
||||||
|
// called with the parameters (year, month, day) when a day in the
|
||||||
|
// calendar is clicked
|
||||||
|
this.div_id = div_id;
|
||||||
|
this.callback = callback;
|
||||||
|
this.today = CalendarNamespace.serverToday();
|
||||||
|
this.currentMonth = this.today.getMonth() + 1;
|
||||||
|
this.currentYear = this.today.getFullYear();
|
||||||
|
if (typeof selected !== "undefined") {
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Calendar.prototype = {
|
||||||
|
drawCurrent: function () {
|
||||||
|
CalendarNamespace.draw(
|
||||||
|
this.currentMonth,
|
||||||
|
this.currentYear,
|
||||||
|
this.div_id,
|
||||||
|
this.callback,
|
||||||
|
this.selected,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
drawDate: function (month, year, selected) {
|
||||||
|
this.currentMonth = month;
|
||||||
|
this.currentYear = year;
|
||||||
|
|
||||||
|
if (selected) {
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.drawCurrent();
|
||||||
|
},
|
||||||
|
drawPreviousMonth: function () {
|
||||||
|
if (this.currentMonth === 1) {
|
||||||
|
this.currentMonth = 12;
|
||||||
|
this.currentYear--;
|
||||||
|
} else {
|
||||||
|
this.currentMonth--;
|
||||||
|
}
|
||||||
|
this.drawCurrent();
|
||||||
|
},
|
||||||
|
drawNextMonth: function () {
|
||||||
|
if (this.currentMonth === 12) {
|
||||||
|
this.currentMonth = 1;
|
||||||
|
this.currentYear++;
|
||||||
|
} else {
|
||||||
|
this.currentMonth++;
|
||||||
|
}
|
||||||
|
this.drawCurrent();
|
||||||
|
},
|
||||||
|
drawPreviousYear: function () {
|
||||||
|
this.currentYear--;
|
||||||
|
this.drawCurrent();
|
||||||
|
},
|
||||||
|
drawNextYear: function () {
|
||||||
|
this.currentYear++;
|
||||||
|
this.drawCurrent();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
window.Calendar = Calendar;
|
||||||
|
window.CalendarNamespace = CalendarNamespace;
|
||||||
|
}
|
||||||
29
staticfiles/admin/js/cancel.js
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
// Call function fn when the DOM is loaded and ready. If it is already
|
||||||
|
// loaded, call the function now.
|
||||||
|
// http://youmightnotneedjquery.com/#ready
|
||||||
|
function ready(fn) {
|
||||||
|
if (document.readyState !== "loading") {
|
||||||
|
fn();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ready(function () {
|
||||||
|
function handleClick(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
if (params.has("_popup")) {
|
||||||
|
window.close(); // Close the popup.
|
||||||
|
} else {
|
||||||
|
window.history.back(); // Otherwise, go back.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll(".cancel-link").forEach(function (el) {
|
||||||
|
el.addEventListener("click", handleClick);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
21
staticfiles/admin/js/change_form.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const inputTags = ["BUTTON", "INPUT", "SELECT", "TEXTAREA"];
|
||||||
|
const modelName = document.getElementById("django-admin-form-add-constants")
|
||||||
|
.dataset.modelName;
|
||||||
|
if (modelName) {
|
||||||
|
const form = document.getElementById(modelName + "_form");
|
||||||
|
for (const element of form.elements) {
|
||||||
|
// HTMLElement.offsetParent returns null when the element is not
|
||||||
|
// rendered.
|
||||||
|
if (
|
||||||
|
inputTags.includes(element.tagName) &&
|
||||||
|
!element.disabled &&
|
||||||
|
element.offsetParent
|
||||||
|
) {
|
||||||
|
element.focus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
194
staticfiles/admin/js/core.js
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
// Core JavaScript helper functions
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// quickElement(tagType, parentReference [, textInChildNode, attribute, attributeValue ...]);
|
||||||
|
function quickElement() {
|
||||||
|
const obj = document.createElement(arguments[0]);
|
||||||
|
if (arguments[2]) {
|
||||||
|
const textNode = document.createTextNode(arguments[2]);
|
||||||
|
obj.appendChild(textNode);
|
||||||
|
}
|
||||||
|
const len = arguments.length;
|
||||||
|
for (let i = 3; i < len; i += 2) {
|
||||||
|
obj.setAttribute(arguments[i], arguments[i + 1]);
|
||||||
|
}
|
||||||
|
arguments[1].appendChild(obj);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "a" is reference to an object
|
||||||
|
function removeChildren(a) {
|
||||||
|
while (a.hasChildNodes()) {
|
||||||
|
a.removeChild(a.lastChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Find-position functions by PPK
|
||||||
|
// See https://www.quirksmode.org/js/findpos.html
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
function findPosX(obj) {
|
||||||
|
let curleft = 0;
|
||||||
|
if (obj.offsetParent) {
|
||||||
|
while (obj.offsetParent) {
|
||||||
|
curleft += obj.offsetLeft - obj.scrollLeft;
|
||||||
|
obj = obj.offsetParent;
|
||||||
|
}
|
||||||
|
} else if (obj.x) {
|
||||||
|
curleft += obj.x;
|
||||||
|
}
|
||||||
|
return curleft;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findPosY(obj) {
|
||||||
|
let curtop = 0;
|
||||||
|
if (obj.offsetParent) {
|
||||||
|
while (obj.offsetParent) {
|
||||||
|
curtop += obj.offsetTop - obj.scrollTop;
|
||||||
|
obj = obj.offsetParent;
|
||||||
|
}
|
||||||
|
} else if (obj.y) {
|
||||||
|
curtop += obj.y;
|
||||||
|
}
|
||||||
|
return curtop;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Date object extensions
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
{
|
||||||
|
Date.prototype.getTwelveHours = function () {
|
||||||
|
return this.getHours() % 12 || 12;
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getTwoDigitMonth = function () {
|
||||||
|
return this.getMonth() < 9
|
||||||
|
? "0" + (this.getMonth() + 1)
|
||||||
|
: this.getMonth() + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getTwoDigitDate = function () {
|
||||||
|
return this.getDate() < 10 ? "0" + this.getDate() : this.getDate();
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getTwoDigitTwelveHour = function () {
|
||||||
|
return this.getTwelveHours() < 10
|
||||||
|
? "0" + this.getTwelveHours()
|
||||||
|
: this.getTwelveHours();
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getTwoDigitHour = function () {
|
||||||
|
return this.getHours() < 10 ? "0" + this.getHours() : this.getHours();
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getTwoDigitMinute = function () {
|
||||||
|
return this.getMinutes() < 10
|
||||||
|
? "0" + this.getMinutes()
|
||||||
|
: this.getMinutes();
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getTwoDigitSecond = function () {
|
||||||
|
return this.getSeconds() < 10
|
||||||
|
? "0" + this.getSeconds()
|
||||||
|
: this.getSeconds();
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getAbbrevDayName = function () {
|
||||||
|
return typeof window.CalendarNamespace === "undefined"
|
||||||
|
? "0" + this.getDay()
|
||||||
|
: window.CalendarNamespace.daysOfWeekAbbrev[this.getDay()];
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getFullDayName = function () {
|
||||||
|
return typeof window.CalendarNamespace === "undefined"
|
||||||
|
? "0" + this.getDay()
|
||||||
|
: window.CalendarNamespace.daysOfWeek[this.getDay()];
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getAbbrevMonthName = function () {
|
||||||
|
return typeof window.CalendarNamespace === "undefined"
|
||||||
|
? this.getTwoDigitMonth()
|
||||||
|
: window.CalendarNamespace.monthsOfYearAbbrev[this.getMonth()];
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.getFullMonthName = function () {
|
||||||
|
return typeof window.CalendarNamespace === "undefined"
|
||||||
|
? this.getTwoDigitMonth()
|
||||||
|
: window.CalendarNamespace.monthsOfYear[this.getMonth()];
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.prototype.strftime = function (format) {
|
||||||
|
const fields = {
|
||||||
|
a: this.getAbbrevDayName(),
|
||||||
|
A: this.getFullDayName(),
|
||||||
|
b: this.getAbbrevMonthName(),
|
||||||
|
B: this.getFullMonthName(),
|
||||||
|
c: this.toString(),
|
||||||
|
d: this.getTwoDigitDate(),
|
||||||
|
H: this.getTwoDigitHour(),
|
||||||
|
I: this.getTwoDigitTwelveHour(),
|
||||||
|
m: this.getTwoDigitMonth(),
|
||||||
|
M: this.getTwoDigitMinute(),
|
||||||
|
p: this.getHours() >= 12 ? "PM" : "AM",
|
||||||
|
S: this.getTwoDigitSecond(),
|
||||||
|
w: "0" + this.getDay(),
|
||||||
|
x: this.toLocaleDateString(),
|
||||||
|
X: this.toLocaleTimeString(),
|
||||||
|
y: ("" + this.getFullYear()).substr(2, 4),
|
||||||
|
Y: "" + this.getFullYear(),
|
||||||
|
"%": "%",
|
||||||
|
};
|
||||||
|
let result = "",
|
||||||
|
i = 0;
|
||||||
|
while (i < format.length) {
|
||||||
|
if (format.charAt(i) === "%") {
|
||||||
|
result += fields[format.charAt(i + 1)];
|
||||||
|
++i;
|
||||||
|
} else {
|
||||||
|
result += format.charAt(i);
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// String object extensions
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
String.prototype.strptime = function (format) {
|
||||||
|
const split_format = format.split(/[.\-/]/);
|
||||||
|
const date = this.split(/[.\-/]/);
|
||||||
|
let i = 0;
|
||||||
|
let day, month, year;
|
||||||
|
while (i < split_format.length) {
|
||||||
|
switch (split_format[i]) {
|
||||||
|
case "%d":
|
||||||
|
day = date[i];
|
||||||
|
break;
|
||||||
|
case "%m":
|
||||||
|
month = date[i] - 1;
|
||||||
|
break;
|
||||||
|
case "%Y":
|
||||||
|
year = date[i];
|
||||||
|
break;
|
||||||
|
case "%y":
|
||||||
|
// A %y value in the range of [00, 68] is in the current
|
||||||
|
// century, while [69, 99] is in the previous century,
|
||||||
|
// according to the Open Group Specification.
|
||||||
|
if (parseInt(date[i], 10) >= 69) {
|
||||||
|
year = date[i];
|
||||||
|
} else {
|
||||||
|
year =
|
||||||
|
new Date(Date.UTC(date[i], 0)).getUTCFullYear() +
|
||||||
|
100;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
// Create Date object from UTC since the parsed value is supposed to be
|
||||||
|
// in UTC, not local time. Also, the calendar uses UTC functions for
|
||||||
|
// date extraction.
|
||||||
|
return new Date(Date.UTC(year, month, day));
|
||||||
|
};
|
||||||
|
}
|
||||||
39
staticfiles/admin/js/filters.js
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* Persist changelist filters state (collapsed/expanded).
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
// Init filters.
|
||||||
|
let filters = JSON.parse(
|
||||||
|
sessionStorage.getItem("django.admin.filtersState"),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!filters) {
|
||||||
|
filters = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.entries(filters).forEach(([key, value]) => {
|
||||||
|
const detailElement = document.querySelector(
|
||||||
|
`[data-filter-title='${CSS.escape(key)}']`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if the filter is present, it could be from other view.
|
||||||
|
if (detailElement) {
|
||||||
|
value
|
||||||
|
? detailElement.setAttribute("open", "")
|
||||||
|
: detailElement.removeAttribute("open");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save filter state when clicks.
|
||||||
|
const details = document.querySelectorAll("details");
|
||||||
|
details.forEach((detail) => {
|
||||||
|
detail.addEventListener("toggle", (event) => {
|
||||||
|
filters[`${event.target.dataset.filterTitle}`] = detail.open;
|
||||||
|
sessionStorage.setItem(
|
||||||
|
"django.admin.filtersState",
|
||||||
|
JSON.stringify(filters),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
451
staticfiles/admin/js/inlines.js
Normal file
|
|
@ -0,0 +1,451 @@
|
||||||
|
/*global DateTimeShortcuts, SelectFilter*/
|
||||||
|
/**
|
||||||
|
* Django admin inlines
|
||||||
|
*
|
||||||
|
* Based on jQuery Formset 1.1
|
||||||
|
* @author Stanislaus Madueke (stan DOT madueke AT gmail DOT com)
|
||||||
|
* @requires jQuery 1.2.6 or later
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Stanislaus Madueke
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Spiced up with Code from Zain Memon's GSoC project 2009
|
||||||
|
* and modified for Django by Jannis Leidel, Travis Swicegood and Julien Phalip.
|
||||||
|
*
|
||||||
|
* Licensed under the New BSD License
|
||||||
|
* See: https://opensource.org/licenses/bsd-license.php
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const $ = django.jQuery;
|
||||||
|
$.fn.formset = function (opts) {
|
||||||
|
const options = $.extend({}, $.fn.formset.defaults, opts);
|
||||||
|
const $this = $(this);
|
||||||
|
const $parent = $this.parent();
|
||||||
|
const updateElementIndex = function (el, prefix, ndx) {
|
||||||
|
const id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))");
|
||||||
|
const replacement = prefix + "-" + ndx;
|
||||||
|
if ($(el).prop("for")) {
|
||||||
|
$(el).prop(
|
||||||
|
"for",
|
||||||
|
$(el).prop("for").replace(id_regex, replacement),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (el.id) {
|
||||||
|
el.id = el.id.replace(id_regex, replacement);
|
||||||
|
}
|
||||||
|
if (el.name) {
|
||||||
|
el.name = el.name.replace(id_regex, replacement);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop(
|
||||||
|
"autocomplete",
|
||||||
|
"off",
|
||||||
|
);
|
||||||
|
let nextIndex = parseInt(totalForms.val(), 10);
|
||||||
|
const maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop(
|
||||||
|
"autocomplete",
|
||||||
|
"off",
|
||||||
|
);
|
||||||
|
const minForms = $("#id_" + options.prefix + "-MIN_NUM_FORMS").prop(
|
||||||
|
"autocomplete",
|
||||||
|
"off",
|
||||||
|
);
|
||||||
|
let addButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "Add another MyModel" button below the inline forms.
|
||||||
|
*/
|
||||||
|
const addInlineAddButton = function () {
|
||||||
|
if (addButton === null) {
|
||||||
|
if ($this.prop("tagName") === "TR") {
|
||||||
|
// If forms are laid out as table rows, insert the
|
||||||
|
// "add" button in a new table row:
|
||||||
|
const numCols = $this.eq(-1).children().length;
|
||||||
|
$parent.append(
|
||||||
|
'<tr class="' +
|
||||||
|
options.addCssClass +
|
||||||
|
'"><td colspan="' +
|
||||||
|
numCols +
|
||||||
|
'"><a role="button" class="addlink" href="#">' +
|
||||||
|
options.addText +
|
||||||
|
"</a></tr>",
|
||||||
|
);
|
||||||
|
addButton = $parent.find("tr:last a");
|
||||||
|
} else {
|
||||||
|
// Otherwise, insert it immediately after the last form:
|
||||||
|
$this
|
||||||
|
.filter(":last")
|
||||||
|
.after(
|
||||||
|
'<div class="' +
|
||||||
|
options.addCssClass +
|
||||||
|
'"><a role="button" class="addlink" href="#">' +
|
||||||
|
options.addText +
|
||||||
|
"</a></div>",
|
||||||
|
);
|
||||||
|
addButton = $this.filter(":last").next().find("a");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addButton.on("click", addInlineClickHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addInlineClickHandler = function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const template = $("#" + options.prefix + "-empty");
|
||||||
|
const row = template.clone(true);
|
||||||
|
row.removeClass(options.emptyCssClass)
|
||||||
|
.addClass(options.formCssClass)
|
||||||
|
.attr("id", options.prefix + "-" + nextIndex);
|
||||||
|
addInlineDeleteButton(row);
|
||||||
|
row.find("*").each(function () {
|
||||||
|
updateElementIndex(this, options.prefix, totalForms.val());
|
||||||
|
});
|
||||||
|
// Insert the new form when it has been fully edited.
|
||||||
|
row.insertBefore($(template));
|
||||||
|
// Update number of total forms.
|
||||||
|
$(totalForms).val(parseInt(totalForms.val(), 10) + 1);
|
||||||
|
nextIndex += 1;
|
||||||
|
// Hide the add button if there's a limit and it's been reached.
|
||||||
|
if (
|
||||||
|
maxForms.val() !== "" &&
|
||||||
|
maxForms.val() - totalForms.val() <= 0
|
||||||
|
) {
|
||||||
|
addButton.parent().hide();
|
||||||
|
}
|
||||||
|
// Show the remove buttons if there are more than min_num.
|
||||||
|
toggleDeleteButtonVisibility(row.closest(".inline-group"));
|
||||||
|
|
||||||
|
// Pass the new form to the post-add callback, if provided.
|
||||||
|
if (options.added) {
|
||||||
|
options.added(row);
|
||||||
|
}
|
||||||
|
row.get(0).dispatchEvent(
|
||||||
|
new CustomEvent("formset:added", {
|
||||||
|
bubbles: true,
|
||||||
|
detail: {
|
||||||
|
formsetName: options.prefix,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "X" button that is part of every unsaved inline.
|
||||||
|
* (When saved, it is replaced with a "Delete" checkbox.)
|
||||||
|
*/
|
||||||
|
const addInlineDeleteButton = function (row) {
|
||||||
|
if (row.is("tr")) {
|
||||||
|
// If the forms are laid out in table rows, insert
|
||||||
|
// the remove button into the last table cell:
|
||||||
|
row.children(":last").append(
|
||||||
|
'<div><a role="button" class="' +
|
||||||
|
options.deleteCssClass +
|
||||||
|
'" href="#">' +
|
||||||
|
options.deleteText +
|
||||||
|
"</a></div>",
|
||||||
|
);
|
||||||
|
} else if (row.is("ul") || row.is("ol")) {
|
||||||
|
// If they're laid out as an ordered/unordered list,
|
||||||
|
// insert an <li> after the last list item:
|
||||||
|
row.append(
|
||||||
|
'<li><a role="button" class="' +
|
||||||
|
options.deleteCssClass +
|
||||||
|
'" href="#">' +
|
||||||
|
options.deleteText +
|
||||||
|
"</a></li>",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Otherwise, just insert the remove button as the
|
||||||
|
// last child element of the form's container:
|
||||||
|
row.children(":first").append(
|
||||||
|
'<span><a role="button" class="' +
|
||||||
|
options.deleteCssClass +
|
||||||
|
'" href="#">' +
|
||||||
|
options.deleteText +
|
||||||
|
"</a></span>",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Add delete handler for each row.
|
||||||
|
row.find("a." + options.deleteCssClass).on(
|
||||||
|
"click",
|
||||||
|
inlineDeleteHandler.bind(this),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const inlineDeleteHandler = function (e1) {
|
||||||
|
e1.preventDefault();
|
||||||
|
const deleteButton = $(e1.target);
|
||||||
|
const row = deleteButton.closest("." + options.formCssClass);
|
||||||
|
const inlineGroup = row.closest(".inline-group");
|
||||||
|
// Remove the parent form containing this button,
|
||||||
|
// and also remove the relevant row with non-field errors:
|
||||||
|
const prevRow = row.prev();
|
||||||
|
if (prevRow.length && prevRow.hasClass("row-form-errors")) {
|
||||||
|
prevRow.remove();
|
||||||
|
}
|
||||||
|
row.remove();
|
||||||
|
nextIndex -= 1;
|
||||||
|
// Pass the deleted form to the post-delete callback, if provided.
|
||||||
|
if (options.removed) {
|
||||||
|
options.removed(row);
|
||||||
|
}
|
||||||
|
document.dispatchEvent(
|
||||||
|
new CustomEvent("formset:removed", {
|
||||||
|
detail: {
|
||||||
|
formsetName: options.prefix,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
// Update the TOTAL_FORMS form count.
|
||||||
|
const forms = $("." + options.formCssClass);
|
||||||
|
$("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
|
||||||
|
// Show add button again once below maximum number.
|
||||||
|
if (maxForms.val() === "" || maxForms.val() - forms.length > 0) {
|
||||||
|
addButton.parent().show();
|
||||||
|
}
|
||||||
|
// Hide the remove buttons if at min_num.
|
||||||
|
toggleDeleteButtonVisibility(inlineGroup);
|
||||||
|
// Also, update names and ids for all remaining form controls so
|
||||||
|
// they remain in sequence:
|
||||||
|
let i, formCount;
|
||||||
|
const updateElementCallback = function () {
|
||||||
|
updateElementIndex(this, options.prefix, i);
|
||||||
|
};
|
||||||
|
for (i = 0, formCount = forms.length; i < formCount; i++) {
|
||||||
|
updateElementIndex($(forms).get(i), options.prefix, i);
|
||||||
|
$(forms.get(i)).find("*").each(updateElementCallback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleDeleteButtonVisibility = function (inlineGroup) {
|
||||||
|
if (
|
||||||
|
minForms.val() !== "" &&
|
||||||
|
minForms.val() - totalForms.val() >= 0
|
||||||
|
) {
|
||||||
|
inlineGroup.find(".inline-deletelink").hide();
|
||||||
|
} else {
|
||||||
|
inlineGroup.find(".inline-deletelink").show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$this.each(function (i) {
|
||||||
|
$(this)
|
||||||
|
.not("." + options.emptyCssClass)
|
||||||
|
.addClass(options.formCssClass);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create the delete buttons for all unsaved inlines:
|
||||||
|
$this
|
||||||
|
.filter(
|
||||||
|
"." +
|
||||||
|
options.formCssClass +
|
||||||
|
":not(.has_original):not(." +
|
||||||
|
options.emptyCssClass +
|
||||||
|
")",
|
||||||
|
)
|
||||||
|
.each(function () {
|
||||||
|
addInlineDeleteButton($(this));
|
||||||
|
});
|
||||||
|
toggleDeleteButtonVisibility($this);
|
||||||
|
|
||||||
|
// Create the add button, initially hidden.
|
||||||
|
addButton = options.addButton;
|
||||||
|
addInlineAddButton();
|
||||||
|
|
||||||
|
// Show the add button if allowed to add more items.
|
||||||
|
// Note that max_num = None translates to a blank string.
|
||||||
|
const showAddButton =
|
||||||
|
maxForms.val() === "" || maxForms.val() - totalForms.val() > 0;
|
||||||
|
if ($this.length && showAddButton) {
|
||||||
|
addButton.parent().show();
|
||||||
|
} else {
|
||||||
|
addButton.parent().hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Setup plugin defaults */
|
||||||
|
$.fn.formset.defaults = {
|
||||||
|
prefix: "form", // The form prefix for your django formset
|
||||||
|
addText: "add another", // Text for the add link
|
||||||
|
deleteText: "remove", // Text for the delete link
|
||||||
|
addCssClass: "add-row", // CSS class applied to the add link
|
||||||
|
deleteCssClass: "delete-row", // CSS class applied to the delete link
|
||||||
|
emptyCssClass: "empty-row", // CSS class applied to the empty row
|
||||||
|
formCssClass: "dynamic-form", // CSS class applied to each form in a formset
|
||||||
|
added: null, // Function called each time a new form is added
|
||||||
|
removed: null, // Function called each time a form is deleted
|
||||||
|
addButton: null, // Existing add button to use
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tabular inlines ---------------------------------------------------------
|
||||||
|
$.fn.tabularFormset = function (selector, options) {
|
||||||
|
const $rows = $(this);
|
||||||
|
|
||||||
|
const reinitDateTimeShortCuts = function () {
|
||||||
|
// Reinitialize the calendar and clock widgets by force
|
||||||
|
if (typeof DateTimeShortcuts !== "undefined") {
|
||||||
|
$(".datetimeshortcuts").remove();
|
||||||
|
DateTimeShortcuts.init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateSelectFilter = function () {
|
||||||
|
// If any SelectFilter widgets are a part of the new form,
|
||||||
|
// instantiate a new SelectFilter instance for it.
|
||||||
|
if (typeof SelectFilter !== "undefined") {
|
||||||
|
$(".selectfilter").each(function (index, value) {
|
||||||
|
SelectFilter.init(value.id, this.dataset.fieldName, false);
|
||||||
|
});
|
||||||
|
$(".selectfilterstacked").each(function (index, value) {
|
||||||
|
SelectFilter.init(value.id, this.dataset.fieldName, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initPrepopulatedFields = function (row) {
|
||||||
|
row.find(".prepopulated_field").each(function () {
|
||||||
|
const field = $(this),
|
||||||
|
input = field.find("input, select, textarea"),
|
||||||
|
dependency_list = input.data("dependency_list") || [],
|
||||||
|
dependencies = [];
|
||||||
|
$.each(dependency_list, function (i, field_name) {
|
||||||
|
dependencies.push(
|
||||||
|
"#" +
|
||||||
|
row
|
||||||
|
.find(".field-" + field_name)
|
||||||
|
.find("input, select, textarea")
|
||||||
|
.attr("id"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
if (dependencies.length) {
|
||||||
|
input.prepopulate(dependencies, input.attr("maxlength"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$rows.formset({
|
||||||
|
prefix: options.prefix,
|
||||||
|
addText: options.addText,
|
||||||
|
formCssClass: "dynamic-" + options.prefix,
|
||||||
|
deleteCssClass: "inline-deletelink",
|
||||||
|
deleteText: options.deleteText,
|
||||||
|
emptyCssClass: "empty-form",
|
||||||
|
added: function (row) {
|
||||||
|
initPrepopulatedFields(row);
|
||||||
|
reinitDateTimeShortCuts();
|
||||||
|
updateSelectFilter();
|
||||||
|
},
|
||||||
|
addButton: options.addButton,
|
||||||
|
});
|
||||||
|
|
||||||
|
return $rows;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Stacked inlines ---------------------------------------------------------
|
||||||
|
$.fn.stackedFormset = function (selector, options) {
|
||||||
|
const $rows = $(this);
|
||||||
|
const updateInlineLabel = function (row) {
|
||||||
|
$(selector)
|
||||||
|
.find(".inline_label")
|
||||||
|
.each(function (i) {
|
||||||
|
const count = i + 1;
|
||||||
|
$(this).html(
|
||||||
|
$(this)
|
||||||
|
.html()
|
||||||
|
.replace(/(#\d+)/g, "#" + count),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const reinitDateTimeShortCuts = function () {
|
||||||
|
// Reinitialize the calendar and clock widgets by force, yuck.
|
||||||
|
if (typeof DateTimeShortcuts !== "undefined") {
|
||||||
|
$(".datetimeshortcuts").remove();
|
||||||
|
DateTimeShortcuts.init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateSelectFilter = function () {
|
||||||
|
// If any SelectFilter widgets were added, instantiate a new instance.
|
||||||
|
if (typeof SelectFilter !== "undefined") {
|
||||||
|
$(".selectfilter").each(function (index, value) {
|
||||||
|
SelectFilter.init(value.id, this.dataset.fieldName, false);
|
||||||
|
});
|
||||||
|
$(".selectfilterstacked").each(function (index, value) {
|
||||||
|
SelectFilter.init(value.id, this.dataset.fieldName, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initPrepopulatedFields = function (row) {
|
||||||
|
row.find(".prepopulated_field").each(function () {
|
||||||
|
const field = $(this),
|
||||||
|
input = field.find("input, select, textarea"),
|
||||||
|
dependency_list = input.data("dependency_list") || [],
|
||||||
|
dependencies = [];
|
||||||
|
$.each(dependency_list, function (i, field_name) {
|
||||||
|
// Dependency in a fieldset.
|
||||||
|
let field_element = row.find(
|
||||||
|
".form-row .field-" + field_name,
|
||||||
|
);
|
||||||
|
// Dependency without a fieldset.
|
||||||
|
if (!field_element.length) {
|
||||||
|
field_element = row.find(
|
||||||
|
".form-row.field-" + field_name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
dependencies.push(
|
||||||
|
"#" +
|
||||||
|
field_element
|
||||||
|
.find("input, select, textarea")
|
||||||
|
.attr("id"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
if (dependencies.length) {
|
||||||
|
input.prepopulate(dependencies, input.attr("maxlength"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$rows.formset({
|
||||||
|
prefix: options.prefix,
|
||||||
|
addText: options.addText,
|
||||||
|
formCssClass: "dynamic-" + options.prefix,
|
||||||
|
deleteCssClass: "inline-deletelink",
|
||||||
|
deleteText: options.deleteText,
|
||||||
|
emptyCssClass: "empty-form",
|
||||||
|
removed: updateInlineLabel,
|
||||||
|
added: function (row) {
|
||||||
|
initPrepopulatedFields(row);
|
||||||
|
reinitDateTimeShortCuts();
|
||||||
|
updateSelectFilter();
|
||||||
|
updateInlineLabel(row);
|
||||||
|
},
|
||||||
|
addButton: options.addButton,
|
||||||
|
});
|
||||||
|
|
||||||
|
return $rows;
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
$(".js-inline-admin-formset").each(function () {
|
||||||
|
const data = $(this).data(),
|
||||||
|
inlineOptions = data.inlineFormset;
|
||||||
|
let selector;
|
||||||
|
switch (data.inlineType) {
|
||||||
|
case "stacked":
|
||||||
|
selector = inlineOptions.name + "-group .inline-related";
|
||||||
|
$(selector).stackedFormset(selector, inlineOptions.options);
|
||||||
|
break;
|
||||||
|
case "tabular":
|
||||||
|
selector =
|
||||||
|
inlineOptions.name +
|
||||||
|
"-group .tabular.inline-related tbody:first > tr.form-row";
|
||||||
|
$(selector).tabularFormset(selector, inlineOptions.options);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
8
staticfiles/admin/js/jquery.init.js
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
/*global jQuery:false*/
|
||||||
|
"use strict";
|
||||||
|
/* Puts the included jQuery into our own namespace using noConflict and passing
|
||||||
|
* it 'true'. This ensures that the included jQuery doesn't pollute the global
|
||||||
|
* namespace (i.e. this preserves pre-existing values for both window.$ and
|
||||||
|
* window.jQuery).
|
||||||
|
*/
|
||||||
|
window.django = { jQuery: jQuery.noConflict(true) };
|
||||||
89
staticfiles/admin/js/nav_sidebar.js
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const toggleNavSidebar = document.getElementById("toggle-nav-sidebar");
|
||||||
|
if (toggleNavSidebar !== null) {
|
||||||
|
const navSidebar = document.getElementById("nav-sidebar");
|
||||||
|
const main = document.getElementById("main");
|
||||||
|
let navSidebarIsOpen = localStorage.getItem(
|
||||||
|
"django.admin.navSidebarIsOpen",
|
||||||
|
);
|
||||||
|
if (navSidebarIsOpen === null) {
|
||||||
|
navSidebarIsOpen = "true";
|
||||||
|
}
|
||||||
|
main.classList.toggle("shifted", navSidebarIsOpen === "true");
|
||||||
|
navSidebar.setAttribute("aria-expanded", navSidebarIsOpen);
|
||||||
|
|
||||||
|
toggleNavSidebar.addEventListener("click", function () {
|
||||||
|
if (navSidebarIsOpen === "true") {
|
||||||
|
navSidebarIsOpen = "false";
|
||||||
|
} else {
|
||||||
|
navSidebarIsOpen = "true";
|
||||||
|
}
|
||||||
|
localStorage.setItem(
|
||||||
|
"django.admin.navSidebarIsOpen",
|
||||||
|
navSidebarIsOpen,
|
||||||
|
);
|
||||||
|
main.classList.toggle("shifted");
|
||||||
|
navSidebar.setAttribute("aria-expanded", navSidebarIsOpen);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSidebarQuickFilter() {
|
||||||
|
const options = [];
|
||||||
|
const navSidebar = document.getElementById("nav-sidebar");
|
||||||
|
if (!navSidebar) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
navSidebar.querySelectorAll("th[scope=row] a").forEach((container) => {
|
||||||
|
options.push({ title: container.innerHTML, node: container });
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkValue(event) {
|
||||||
|
let filterValue = event.target.value;
|
||||||
|
if (filterValue) {
|
||||||
|
filterValue = filterValue.toLowerCase();
|
||||||
|
}
|
||||||
|
if (event.key === "Escape") {
|
||||||
|
filterValue = "";
|
||||||
|
event.target.value = ""; // clear input
|
||||||
|
}
|
||||||
|
let matches = false;
|
||||||
|
for (const o of options) {
|
||||||
|
let displayValue = "";
|
||||||
|
if (filterValue) {
|
||||||
|
if (o.title.toLowerCase().indexOf(filterValue) === -1) {
|
||||||
|
displayValue = "none";
|
||||||
|
} else {
|
||||||
|
matches = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// show/hide parent <TR>
|
||||||
|
o.node.parentNode.parentNode.style.display = displayValue;
|
||||||
|
}
|
||||||
|
if (!filterValue || matches) {
|
||||||
|
event.target.classList.remove("no-results");
|
||||||
|
} else {
|
||||||
|
event.target.classList.add("no-results");
|
||||||
|
}
|
||||||
|
sessionStorage.setItem(
|
||||||
|
"django.admin.navSidebarFilterValue",
|
||||||
|
filterValue,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nav = document.getElementById("nav-filter");
|
||||||
|
nav.addEventListener("change", checkValue, false);
|
||||||
|
nav.addEventListener("input", checkValue, false);
|
||||||
|
nav.addEventListener("keyup", checkValue, false);
|
||||||
|
|
||||||
|
const storedValue = sessionStorage.getItem(
|
||||||
|
"django.admin.navSidebarFilterValue",
|
||||||
|
);
|
||||||
|
if (storedValue) {
|
||||||
|
nav.value = storedValue;
|
||||||
|
checkValue({ target: nav, key: "" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.initSidebarQuickFilter = initSidebarQuickFilter;
|
||||||
|
initSidebarQuickFilter();
|
||||||
|
}
|
||||||
28
staticfiles/admin/js/popup_response.js
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const initData = JSON.parse(
|
||||||
|
document.getElementById("django-admin-popup-response-constants").dataset
|
||||||
|
.popupResponse,
|
||||||
|
);
|
||||||
|
switch (initData.action) {
|
||||||
|
case "change":
|
||||||
|
opener.dismissChangeRelatedObjectPopup(
|
||||||
|
window,
|
||||||
|
initData.value,
|
||||||
|
initData.obj,
|
||||||
|
initData.new_value,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "delete":
|
||||||
|
opener.dismissDeleteRelatedObjectPopup(window, initData.value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
opener.dismissAddRelatedObjectPopup(
|
||||||
|
window,
|
||||||
|
initData.value,
|
||||||
|
initData.obj,
|
||||||
|
initData.optgroup,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
45
staticfiles/admin/js/prepopulate.js
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*global URLify*/
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const $ = django.jQuery;
|
||||||
|
$.fn.prepopulate = function (dependencies, maxLength, allowUnicode) {
|
||||||
|
/*
|
||||||
|
Depends on urlify.js
|
||||||
|
Populates a selected field with the values of the dependent fields,
|
||||||
|
URLifies and shortens the string.
|
||||||
|
dependencies - array of dependent fields ids
|
||||||
|
maxLength - maximum length of the URLify'd string
|
||||||
|
allowUnicode - Unicode support of the URLify'd string
|
||||||
|
*/
|
||||||
|
return this.each(function () {
|
||||||
|
const prepopulatedField = $(this);
|
||||||
|
|
||||||
|
const populate = function () {
|
||||||
|
// Bail if the field's value has been changed by the user
|
||||||
|
if (prepopulatedField.data("_changed")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const values = [];
|
||||||
|
$.each(dependencies, function (i, field) {
|
||||||
|
field = $(field);
|
||||||
|
if (field.val().length > 0) {
|
||||||
|
values.push(field.val());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
prepopulatedField.val(
|
||||||
|
URLify(values.join(" "), maxLength, allowUnicode),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
prepopulatedField.data("_changed", false);
|
||||||
|
prepopulatedField.on("change", function () {
|
||||||
|
prepopulatedField.data("_changed", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!prepopulatedField.val()) {
|
||||||
|
$(dependencies.join(",")).on("keyup change focus", populate);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
24
staticfiles/admin/js/prepopulate_init.js
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const $ = django.jQuery;
|
||||||
|
const fields = $("#django-admin-prepopulated-fields-constants").data(
|
||||||
|
"prepopulatedFields",
|
||||||
|
);
|
||||||
|
$.each(fields, function (index, field) {
|
||||||
|
$(
|
||||||
|
".empty-form .form-row .field-" +
|
||||||
|
field.name +
|
||||||
|
", .empty-form.form-row .field-" +
|
||||||
|
field.name +
|
||||||
|
", .empty-form .form-row.field-" +
|
||||||
|
field.name,
|
||||||
|
).addClass("prepopulated_field");
|
||||||
|
$(field.id)
|
||||||
|
.data("dependency_list", field.dependency_list)
|
||||||
|
.prepopulate(
|
||||||
|
field.dependency_ids,
|
||||||
|
field.maxLength,
|
||||||
|
field.allowUnicode,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
55
staticfiles/admin/js/theme.js
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
function setTheme(mode) {
|
||||||
|
if (mode !== "light" && mode !== "dark" && mode !== "auto") {
|
||||||
|
console.error(
|
||||||
|
`Got invalid theme mode: ${mode}. Resetting to auto.`,
|
||||||
|
);
|
||||||
|
mode = "auto";
|
||||||
|
}
|
||||||
|
document.documentElement.dataset.theme = mode;
|
||||||
|
localStorage.setItem("theme", mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cycleTheme() {
|
||||||
|
const currentTheme = localStorage.getItem("theme") || "auto";
|
||||||
|
const prefersDark = window.matchMedia(
|
||||||
|
"(prefers-color-scheme: dark)",
|
||||||
|
).matches;
|
||||||
|
|
||||||
|
if (prefersDark) {
|
||||||
|
// Auto (dark) -> Light -> Dark
|
||||||
|
if (currentTheme === "auto") {
|
||||||
|
setTheme("light");
|
||||||
|
} else if (currentTheme === "light") {
|
||||||
|
setTheme("dark");
|
||||||
|
} else {
|
||||||
|
setTheme("auto");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Auto (light) -> Dark -> Light
|
||||||
|
if (currentTheme === "auto") {
|
||||||
|
setTheme("dark");
|
||||||
|
} else if (currentTheme === "dark") {
|
||||||
|
setTheme("light");
|
||||||
|
} else {
|
||||||
|
setTheme("auto");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initTheme() {
|
||||||
|
// set theme defined in localStorage if there is one, or fallback to auto mode
|
||||||
|
const currentTheme = localStorage.getItem("theme");
|
||||||
|
currentTheme ? setTheme(currentTheme) : setTheme("auto");
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", function (_) {
|
||||||
|
const buttons = document.getElementsByClassName("theme-toggle");
|
||||||
|
Array.from(buttons).forEach((btn) => {
|
||||||
|
btn.addEventListener("click", cycleTheme);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
initTheme();
|
||||||
|
}
|
||||||
532
staticfiles/admin/js/urlify.js
Normal file
|
|
@ -0,0 +1,532 @@
|
||||||
|
/*global XRegExp*/
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
const LATIN_MAP = {
|
||||||
|
À: "A",
|
||||||
|
Á: "A",
|
||||||
|
Â: "A",
|
||||||
|
Ã: "A",
|
||||||
|
Ä: "A",
|
||||||
|
Å: "A",
|
||||||
|
Æ: "AE",
|
||||||
|
Ç: "C",
|
||||||
|
È: "E",
|
||||||
|
É: "E",
|
||||||
|
Ê: "E",
|
||||||
|
Ë: "E",
|
||||||
|
Ì: "I",
|
||||||
|
Í: "I",
|
||||||
|
Î: "I",
|
||||||
|
Ï: "I",
|
||||||
|
Ð: "D",
|
||||||
|
Ñ: "N",
|
||||||
|
Ò: "O",
|
||||||
|
Ó: "O",
|
||||||
|
Ô: "O",
|
||||||
|
Õ: "O",
|
||||||
|
Ö: "O",
|
||||||
|
Ő: "O",
|
||||||
|
Ø: "O",
|
||||||
|
Ù: "U",
|
||||||
|
Ú: "U",
|
||||||
|
Û: "U",
|
||||||
|
Ü: "U",
|
||||||
|
Ű: "U",
|
||||||
|
Ý: "Y",
|
||||||
|
Þ: "TH",
|
||||||
|
Ÿ: "Y",
|
||||||
|
ß: "ss",
|
||||||
|
à: "a",
|
||||||
|
á: "a",
|
||||||
|
â: "a",
|
||||||
|
ã: "a",
|
||||||
|
ä: "a",
|
||||||
|
å: "a",
|
||||||
|
æ: "ae",
|
||||||
|
ç: "c",
|
||||||
|
è: "e",
|
||||||
|
é: "e",
|
||||||
|
ê: "e",
|
||||||
|
ë: "e",
|
||||||
|
ì: "i",
|
||||||
|
í: "i",
|
||||||
|
î: "i",
|
||||||
|
ï: "i",
|
||||||
|
ð: "d",
|
||||||
|
ñ: "n",
|
||||||
|
ò: "o",
|
||||||
|
ó: "o",
|
||||||
|
ô: "o",
|
||||||
|
õ: "o",
|
||||||
|
ö: "o",
|
||||||
|
ő: "o",
|
||||||
|
ø: "o",
|
||||||
|
ù: "u",
|
||||||
|
ú: "u",
|
||||||
|
û: "u",
|
||||||
|
ü: "u",
|
||||||
|
ű: "u",
|
||||||
|
ý: "y",
|
||||||
|
þ: "th",
|
||||||
|
ÿ: "y",
|
||||||
|
};
|
||||||
|
const LATIN_SYMBOLS_MAP = {
|
||||||
|
"©": "(c)",
|
||||||
|
};
|
||||||
|
const GREEK_MAP = {
|
||||||
|
α: "a",
|
||||||
|
β: "b",
|
||||||
|
γ: "g",
|
||||||
|
δ: "d",
|
||||||
|
ε: "e",
|
||||||
|
ζ: "z",
|
||||||
|
η: "h",
|
||||||
|
θ: "8",
|
||||||
|
ι: "i",
|
||||||
|
κ: "k",
|
||||||
|
λ: "l",
|
||||||
|
μ: "m",
|
||||||
|
ν: "n",
|
||||||
|
ξ: "3",
|
||||||
|
ο: "o",
|
||||||
|
π: "p",
|
||||||
|
ρ: "r",
|
||||||
|
σ: "s",
|
||||||
|
τ: "t",
|
||||||
|
υ: "y",
|
||||||
|
φ: "f",
|
||||||
|
χ: "x",
|
||||||
|
ψ: "ps",
|
||||||
|
ω: "w",
|
||||||
|
ά: "a",
|
||||||
|
έ: "e",
|
||||||
|
ί: "i",
|
||||||
|
ό: "o",
|
||||||
|
ύ: "y",
|
||||||
|
ή: "h",
|
||||||
|
ώ: "w",
|
||||||
|
ς: "s",
|
||||||
|
ϊ: "i",
|
||||||
|
ΰ: "y",
|
||||||
|
ϋ: "y",
|
||||||
|
ΐ: "i",
|
||||||
|
Α: "A",
|
||||||
|
Β: "B",
|
||||||
|
Γ: "G",
|
||||||
|
Δ: "D",
|
||||||
|
Ε: "E",
|
||||||
|
Ζ: "Z",
|
||||||
|
Η: "H",
|
||||||
|
Θ: "8",
|
||||||
|
Ι: "I",
|
||||||
|
Κ: "K",
|
||||||
|
Λ: "L",
|
||||||
|
Μ: "M",
|
||||||
|
Ν: "N",
|
||||||
|
Ξ: "3",
|
||||||
|
Ο: "O",
|
||||||
|
Π: "P",
|
||||||
|
Ρ: "R",
|
||||||
|
Σ: "S",
|
||||||
|
Τ: "T",
|
||||||
|
Υ: "Y",
|
||||||
|
Φ: "F",
|
||||||
|
Χ: "X",
|
||||||
|
Ψ: "PS",
|
||||||
|
Ω: "W",
|
||||||
|
Ά: "A",
|
||||||
|
Έ: "E",
|
||||||
|
Ί: "I",
|
||||||
|
Ό: "O",
|
||||||
|
Ύ: "Y",
|
||||||
|
Ή: "H",
|
||||||
|
Ώ: "W",
|
||||||
|
Ϊ: "I",
|
||||||
|
Ϋ: "Y",
|
||||||
|
};
|
||||||
|
const TURKISH_MAP = {
|
||||||
|
ş: "s",
|
||||||
|
Ş: "S",
|
||||||
|
ı: "i",
|
||||||
|
İ: "I",
|
||||||
|
ç: "c",
|
||||||
|
Ç: "C",
|
||||||
|
ü: "u",
|
||||||
|
Ü: "U",
|
||||||
|
ö: "o",
|
||||||
|
Ö: "O",
|
||||||
|
ğ: "g",
|
||||||
|
Ğ: "G",
|
||||||
|
};
|
||||||
|
const ROMANIAN_MAP = {
|
||||||
|
ă: "a",
|
||||||
|
î: "i",
|
||||||
|
ș: "s",
|
||||||
|
ț: "t",
|
||||||
|
â: "a",
|
||||||
|
Ă: "A",
|
||||||
|
Î: "I",
|
||||||
|
Ș: "S",
|
||||||
|
Ț: "T",
|
||||||
|
Â: "A",
|
||||||
|
};
|
||||||
|
const RUSSIAN_MAP = {
|
||||||
|
а: "a",
|
||||||
|
б: "b",
|
||||||
|
в: "v",
|
||||||
|
г: "g",
|
||||||
|
д: "d",
|
||||||
|
е: "e",
|
||||||
|
ё: "yo",
|
||||||
|
ж: "zh",
|
||||||
|
з: "z",
|
||||||
|
и: "i",
|
||||||
|
й: "j",
|
||||||
|
к: "k",
|
||||||
|
л: "l",
|
||||||
|
м: "m",
|
||||||
|
н: "n",
|
||||||
|
о: "o",
|
||||||
|
п: "p",
|
||||||
|
р: "r",
|
||||||
|
с: "s",
|
||||||
|
т: "t",
|
||||||
|
у: "u",
|
||||||
|
ф: "f",
|
||||||
|
х: "h",
|
||||||
|
ц: "c",
|
||||||
|
ч: "ch",
|
||||||
|
ш: "sh",
|
||||||
|
щ: "sh",
|
||||||
|
ъ: "",
|
||||||
|
ы: "y",
|
||||||
|
ь: "",
|
||||||
|
э: "e",
|
||||||
|
ю: "yu",
|
||||||
|
я: "ya",
|
||||||
|
А: "A",
|
||||||
|
Б: "B",
|
||||||
|
В: "V",
|
||||||
|
Г: "G",
|
||||||
|
Д: "D",
|
||||||
|
Е: "E",
|
||||||
|
Ё: "Yo",
|
||||||
|
Ж: "Zh",
|
||||||
|
З: "Z",
|
||||||
|
И: "I",
|
||||||
|
Й: "J",
|
||||||
|
К: "K",
|
||||||
|
Л: "L",
|
||||||
|
М: "M",
|
||||||
|
Н: "N",
|
||||||
|
О: "O",
|
||||||
|
П: "P",
|
||||||
|
Р: "R",
|
||||||
|
С: "S",
|
||||||
|
Т: "T",
|
||||||
|
У: "U",
|
||||||
|
Ф: "F",
|
||||||
|
Х: "H",
|
||||||
|
Ц: "C",
|
||||||
|
Ч: "Ch",
|
||||||
|
Ш: "Sh",
|
||||||
|
Щ: "Sh",
|
||||||
|
Ъ: "",
|
||||||
|
Ы: "Y",
|
||||||
|
Ь: "",
|
||||||
|
Э: "E",
|
||||||
|
Ю: "Yu",
|
||||||
|
Я: "Ya",
|
||||||
|
};
|
||||||
|
const UKRAINIAN_MAP = {
|
||||||
|
Є: "Ye",
|
||||||
|
І: "I",
|
||||||
|
Ї: "Yi",
|
||||||
|
Ґ: "G",
|
||||||
|
є: "ye",
|
||||||
|
і: "i",
|
||||||
|
ї: "yi",
|
||||||
|
ґ: "g",
|
||||||
|
};
|
||||||
|
const CZECH_MAP = {
|
||||||
|
č: "c",
|
||||||
|
ď: "d",
|
||||||
|
ě: "e",
|
||||||
|
ň: "n",
|
||||||
|
ř: "r",
|
||||||
|
š: "s",
|
||||||
|
ť: "t",
|
||||||
|
ů: "u",
|
||||||
|
ž: "z",
|
||||||
|
Č: "C",
|
||||||
|
Ď: "D",
|
||||||
|
Ě: "E",
|
||||||
|
Ň: "N",
|
||||||
|
Ř: "R",
|
||||||
|
Š: "S",
|
||||||
|
Ť: "T",
|
||||||
|
Ů: "U",
|
||||||
|
Ž: "Z",
|
||||||
|
};
|
||||||
|
const SLOVAK_MAP = {
|
||||||
|
á: "a",
|
||||||
|
ä: "a",
|
||||||
|
č: "c",
|
||||||
|
ď: "d",
|
||||||
|
é: "e",
|
||||||
|
í: "i",
|
||||||
|
ľ: "l",
|
||||||
|
ĺ: "l",
|
||||||
|
ň: "n",
|
||||||
|
ó: "o",
|
||||||
|
ô: "o",
|
||||||
|
ŕ: "r",
|
||||||
|
š: "s",
|
||||||
|
ť: "t",
|
||||||
|
ú: "u",
|
||||||
|
ý: "y",
|
||||||
|
ž: "z",
|
||||||
|
Á: "a",
|
||||||
|
Ä: "A",
|
||||||
|
Č: "C",
|
||||||
|
Ď: "D",
|
||||||
|
É: "E",
|
||||||
|
Í: "I",
|
||||||
|
Ľ: "L",
|
||||||
|
Ĺ: "L",
|
||||||
|
Ň: "N",
|
||||||
|
Ó: "O",
|
||||||
|
Ô: "O",
|
||||||
|
Ŕ: "R",
|
||||||
|
Š: "S",
|
||||||
|
Ť: "T",
|
||||||
|
Ú: "U",
|
||||||
|
Ý: "Y",
|
||||||
|
Ž: "Z",
|
||||||
|
};
|
||||||
|
const POLISH_MAP = {
|
||||||
|
ą: "a",
|
||||||
|
ć: "c",
|
||||||
|
ę: "e",
|
||||||
|
ł: "l",
|
||||||
|
ń: "n",
|
||||||
|
ó: "o",
|
||||||
|
ś: "s",
|
||||||
|
ź: "z",
|
||||||
|
ż: "z",
|
||||||
|
Ą: "A",
|
||||||
|
Ć: "C",
|
||||||
|
Ę: "E",
|
||||||
|
Ł: "L",
|
||||||
|
Ń: "N",
|
||||||
|
Ó: "O",
|
||||||
|
Ś: "S",
|
||||||
|
Ź: "Z",
|
||||||
|
Ż: "Z",
|
||||||
|
};
|
||||||
|
const LATVIAN_MAP = {
|
||||||
|
ā: "a",
|
||||||
|
č: "c",
|
||||||
|
ē: "e",
|
||||||
|
ģ: "g",
|
||||||
|
ī: "i",
|
||||||
|
ķ: "k",
|
||||||
|
ļ: "l",
|
||||||
|
ņ: "n",
|
||||||
|
š: "s",
|
||||||
|
ū: "u",
|
||||||
|
ž: "z",
|
||||||
|
Ā: "A",
|
||||||
|
Č: "C",
|
||||||
|
Ē: "E",
|
||||||
|
Ģ: "G",
|
||||||
|
Ī: "I",
|
||||||
|
Ķ: "K",
|
||||||
|
Ļ: "L",
|
||||||
|
Ņ: "N",
|
||||||
|
Š: "S",
|
||||||
|
Ū: "U",
|
||||||
|
Ž: "Z",
|
||||||
|
};
|
||||||
|
const ARABIC_MAP = {
|
||||||
|
أ: "a",
|
||||||
|
ب: "b",
|
||||||
|
ت: "t",
|
||||||
|
ث: "th",
|
||||||
|
ج: "g",
|
||||||
|
ح: "h",
|
||||||
|
خ: "kh",
|
||||||
|
د: "d",
|
||||||
|
ذ: "th",
|
||||||
|
ر: "r",
|
||||||
|
ز: "z",
|
||||||
|
س: "s",
|
||||||
|
ش: "sh",
|
||||||
|
ص: "s",
|
||||||
|
ض: "d",
|
||||||
|
ط: "t",
|
||||||
|
ظ: "th",
|
||||||
|
ع: "aa",
|
||||||
|
غ: "gh",
|
||||||
|
ف: "f",
|
||||||
|
ق: "k",
|
||||||
|
ك: "k",
|
||||||
|
ل: "l",
|
||||||
|
م: "m",
|
||||||
|
ن: "n",
|
||||||
|
ه: "h",
|
||||||
|
و: "o",
|
||||||
|
ي: "y",
|
||||||
|
};
|
||||||
|
const LITHUANIAN_MAP = {
|
||||||
|
ą: "a",
|
||||||
|
č: "c",
|
||||||
|
ę: "e",
|
||||||
|
ė: "e",
|
||||||
|
į: "i",
|
||||||
|
š: "s",
|
||||||
|
ų: "u",
|
||||||
|
ū: "u",
|
||||||
|
ž: "z",
|
||||||
|
Ą: "A",
|
||||||
|
Č: "C",
|
||||||
|
Ę: "E",
|
||||||
|
Ė: "E",
|
||||||
|
Į: "I",
|
||||||
|
Š: "S",
|
||||||
|
Ų: "U",
|
||||||
|
Ū: "U",
|
||||||
|
Ž: "Z",
|
||||||
|
};
|
||||||
|
const SERBIAN_MAP = {
|
||||||
|
ђ: "dj",
|
||||||
|
ј: "j",
|
||||||
|
љ: "lj",
|
||||||
|
њ: "nj",
|
||||||
|
ћ: "c",
|
||||||
|
џ: "dz",
|
||||||
|
đ: "dj",
|
||||||
|
Ђ: "Dj",
|
||||||
|
Ј: "j",
|
||||||
|
Љ: "Lj",
|
||||||
|
Њ: "Nj",
|
||||||
|
Ћ: "C",
|
||||||
|
Џ: "Dz",
|
||||||
|
Đ: "Dj",
|
||||||
|
};
|
||||||
|
const AZERBAIJANI_MAP = {
|
||||||
|
ç: "c",
|
||||||
|
ə: "e",
|
||||||
|
ğ: "g",
|
||||||
|
ı: "i",
|
||||||
|
ö: "o",
|
||||||
|
ş: "s",
|
||||||
|
ü: "u",
|
||||||
|
Ç: "C",
|
||||||
|
Ə: "E",
|
||||||
|
Ğ: "G",
|
||||||
|
İ: "I",
|
||||||
|
Ö: "O",
|
||||||
|
Ş: "S",
|
||||||
|
Ü: "U",
|
||||||
|
};
|
||||||
|
const GEORGIAN_MAP = {
|
||||||
|
ა: "a",
|
||||||
|
ბ: "b",
|
||||||
|
გ: "g",
|
||||||
|
დ: "d",
|
||||||
|
ე: "e",
|
||||||
|
ვ: "v",
|
||||||
|
ზ: "z",
|
||||||
|
თ: "t",
|
||||||
|
ი: "i",
|
||||||
|
კ: "k",
|
||||||
|
ლ: "l",
|
||||||
|
მ: "m",
|
||||||
|
ნ: "n",
|
||||||
|
ო: "o",
|
||||||
|
პ: "p",
|
||||||
|
ჟ: "j",
|
||||||
|
რ: "r",
|
||||||
|
ს: "s",
|
||||||
|
ტ: "t",
|
||||||
|
უ: "u",
|
||||||
|
ფ: "f",
|
||||||
|
ქ: "q",
|
||||||
|
ღ: "g",
|
||||||
|
ყ: "y",
|
||||||
|
შ: "sh",
|
||||||
|
ჩ: "ch",
|
||||||
|
ც: "c",
|
||||||
|
ძ: "dz",
|
||||||
|
წ: "w",
|
||||||
|
ჭ: "ch",
|
||||||
|
ხ: "x",
|
||||||
|
ჯ: "j",
|
||||||
|
ჰ: "h",
|
||||||
|
};
|
||||||
|
|
||||||
|
const ALL_DOWNCODE_MAPS = [
|
||||||
|
LATIN_MAP,
|
||||||
|
LATIN_SYMBOLS_MAP,
|
||||||
|
GREEK_MAP,
|
||||||
|
TURKISH_MAP,
|
||||||
|
ROMANIAN_MAP,
|
||||||
|
RUSSIAN_MAP,
|
||||||
|
UKRAINIAN_MAP,
|
||||||
|
CZECH_MAP,
|
||||||
|
SLOVAK_MAP,
|
||||||
|
POLISH_MAP,
|
||||||
|
LATVIAN_MAP,
|
||||||
|
ARABIC_MAP,
|
||||||
|
LITHUANIAN_MAP,
|
||||||
|
SERBIAN_MAP,
|
||||||
|
AZERBAIJANI_MAP,
|
||||||
|
GEORGIAN_MAP,
|
||||||
|
];
|
||||||
|
|
||||||
|
const Downcoder = {
|
||||||
|
Initialize: function () {
|
||||||
|
if (Downcoder.map) {
|
||||||
|
// already made
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Downcoder.map = {};
|
||||||
|
for (const lookup of ALL_DOWNCODE_MAPS) {
|
||||||
|
Object.assign(Downcoder.map, lookup);
|
||||||
|
}
|
||||||
|
Downcoder.regex = new RegExp(
|
||||||
|
Object.keys(Downcoder.map).join("|"),
|
||||||
|
"g",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function downcode(slug) {
|
||||||
|
Downcoder.Initialize();
|
||||||
|
return slug.replace(Downcoder.regex, function (m) {
|
||||||
|
return Downcoder.map[m];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function URLify(s, num_chars, allowUnicode) {
|
||||||
|
// changes, e.g., "Petty theft" to "petty-theft"
|
||||||
|
if (!allowUnicode) {
|
||||||
|
s = downcode(s);
|
||||||
|
}
|
||||||
|
s = s.toLowerCase(); // convert to lowercase
|
||||||
|
// if downcode doesn't hit, the char will be stripped here
|
||||||
|
if (allowUnicode) {
|
||||||
|
// Keep Unicode letters including both lowercase and uppercase
|
||||||
|
// characters, whitespace, and dash; remove other characters.
|
||||||
|
s = XRegExp.replace(s, XRegExp("[^-_\\p{L}\\p{N}\\s]", "g"), "");
|
||||||
|
} else {
|
||||||
|
s = s.replace(/[^-\w\s]/g, ""); // remove unneeded chars
|
||||||
|
}
|
||||||
|
s = s.replace(/^\s+|\s+$/g, ""); // trim leading/trailing spaces
|
||||||
|
s = s.replace(/[-\s]+/g, "-"); // convert spaces to hyphens
|
||||||
|
s = s.substring(0, num_chars); // trim to first num_chars chars
|
||||||
|
return s.replace(/-+$/g, ""); // trim any trailing hyphens
|
||||||
|
}
|
||||||
|
window.URLify = URLify;
|
||||||
|
}
|
||||||
20
staticfiles/admin/js/vendor/jquery/LICENSE.txt
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
10716
staticfiles/admin/js/vendor/jquery/jquery.js
vendored
Normal file
2
staticfiles/admin/js/vendor/jquery/jquery.min.js
vendored
Normal file
21
staticfiles/admin/js/vendor/select2/LICENSE.md
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/af.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/af",[],function(){return{errorLoading:function(){return"Die resultate kon nie gelaai word nie."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Verwyders asseblief "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Voer asseblief "+(e.minimum-e.input.length)+" of meer karakters"},loadingMore:function(){return"Meer resultate word gelaai…"},maximumSelected:function(e){var n="Kies asseblief net "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"Geen resultate gevind"},searching:function(){return"Besig…"},removeAllItems:function(){return"Verwyder alle items"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/ar.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ar",[],function(){return{errorLoading:function(){return"لا يمكن تحميل النتائج"},inputTooLong:function(n){return"الرجاء حذف "+(n.input.length-n.maximum)+" عناصر"},inputTooShort:function(n){return"الرجاء إضافة "+(n.minimum-n.input.length)+" عناصر"},loadingMore:function(){return"جاري تحميل نتائج إضافية..."},maximumSelected:function(n){return"تستطيع إختيار "+n.maximum+" بنود فقط"},noResults:function(){return"لم يتم العثور على أي نتائج"},searching:function(){return"جاري البحث…"},removeAllItems:function(){return"قم بإزالة كل العناصر"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/az.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/az",[],function(){return{inputTooLong:function(n){return n.input.length-n.maximum+" simvol silin"},inputTooShort:function(n){return n.minimum-n.input.length+" simvol daxil edin"},loadingMore:function(){return"Daha çox nəticə yüklənir…"},maximumSelected:function(n){return"Sadəcə "+n.maximum+" element seçə bilərsiniz"},noResults:function(){return"Nəticə tapılmadı"},searching:function(){return"Axtarılır…"},removeAllItems:function(){return"Bütün elementləri sil"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/bg.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bg",[],function(){return{inputTooLong:function(n){var e=n.input.length-n.maximum,u="Моля въведете с "+e+" по-малко символ";return e>1&&(u+="a"),u},inputTooShort:function(n){var e=n.minimum-n.input.length,u="Моля въведете още "+e+" символ";return e>1&&(u+="a"),u},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(n){var e="Можете да направите до "+n.maximum+" ";return n.maximum>1?e+="избора":e+="избор",e},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"},removeAllItems:function(){return"Премахнете всички елементи"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/bn.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bn",[],function(){return{errorLoading:function(){return"ফলাফলগুলি লোড করা যায়নি।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।";return 1!=e&&(u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।"),u},inputTooShort:function(n){return n.minimum-n.input.length+" টি অক্ষর অথবা অধিক অক্ষর লিখুন।"},loadingMore:function(){return"আরো ফলাফল লোড হচ্ছে ..."},maximumSelected:function(n){var e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।";return 1!=n.maximum&&(e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।"),e},noResults:function(){return"কোন ফলাফল পাওয়া যায়নি।"},searching:function(){return"অনুসন্ধান করা হচ্ছে ..."}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/bs.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/bs",[],function(){function e(e,n,r,t){return e%10==1&&e%100!=11?n:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspijelo."},inputTooLong:function(n){var r=n.input.length-n.maximum,t="Obrišite "+r+" simbol";return t+=e(r,"","a","a")},inputTooShort:function(n){var r=n.minimum-n.input.length,t="Ukucajte bar još "+r+" simbol";return t+=e(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(n){var r="Možete izabrati samo "+n.maximum+" stavk";return r+=e(n.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Uklonite sve stavke"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/ca.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Si us plau, elimina "+n+" car";return r+=1==n?"àcter":"àcters"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Si us plau, introdueix "+n+" car";return r+=1==n?"àcter":"àcters"},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var n="Només es pot seleccionar "+e.maximum+" element";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"},removeAllItems:function(){return"Treu tots els elements"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/cs.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/cs",[],function(){function e(e,n){switch(e){case 2:return n?"dva":"dvě";case 3:return"tři";case 4:return"čtyři"}return""}return{errorLoading:function(){return"Výsledky nemohly být načteny."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadejte o jeden znak méně.":t<=4?"Prosím, zadejte o "+e(t,!0)+" znaky méně.":"Prosím, zadejte o "+t+" znaků méně."},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadejte ještě jeden znak.":t<=4?"Prosím, zadejte ještě další "+e(t,!0)+" znaky.":"Prosím, zadejte ještě dalších "+t+" znaků."},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(n){var t=n.maximum;return 1==t?"Můžete zvolit jen jednu položku.":t<=4?"Můžete zvolit maximálně "+e(t,!1)+" položky.":"Můžete zvolit maximálně "+t+" položek."},noResults:function(){return"Nenalezeny žádné položky."},searching:function(){return"Vyhledávání…"},removeAllItems:function(){return"Odstraňte všechny položky"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/da.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){return"Angiv venligst "+(e.input.length-e.maximum)+" tegn mindre"},inputTooShort:function(e){return"Angiv venligst "+(e.minimum-e.input.length)+" tegn mere"},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var n="Du kan kun vælge "+e.maximum+" emne";return 1!=e.maximum&&(n+="r"),n},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/de.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/de",[],function(){return{errorLoading:function(){return"Die Ergebnisse konnten nicht geladen werden."},inputTooLong:function(e){return"Bitte "+(e.input.length-e.maximum)+" Zeichen weniger eingeben"},inputTooShort:function(e){return"Bitte "+(e.minimum-e.input.length)+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var n="Sie können nur "+e.maximum+" Element";return 1!=e.maximum&&(n+="e"),n+=" auswählen"},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"},removeAllItems:function(){return"Entferne alle Elemente"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/dsb.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/dsb",[],function(){var n=["znamuško","znamušce","znamuška","znamuškow"],e=["zapisk","zapiska","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njejsu se dali zacytaś."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Pšosym lašuj "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Pšosym zapódaj nanejmjenjej "+a+" "+u(a,n)},loadingMore:function(){return"Dalšne wuslědki se zacytaju…"},maximumSelected:function(n){return"Móžoš jano "+n.maximum+" "+u(n.maximum,e)+"wubraś."},noResults:function(){return"Žedne wuslědki namakane"},searching:function(){return"Pyta se…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/el.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(n){var e=n.input.length-n.maximum,u="Παρακαλώ διαγράψτε "+e+" χαρακτήρ";return 1==e&&(u+="α"),1!=e&&(u+="ες"),u},inputTooShort:function(n){return"Παρακαλώ συμπληρώστε "+(n.minimum-n.input.length)+" ή περισσότερους χαρακτήρες"},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(n){var e="Μπορείτε να επιλέξετε μόνο "+n.maximum+" επιλογ";return 1==n.maximum&&(e+="ή"),1!=n.maximum&&(e+="ές"),e},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"},removeAllItems:function(){return"Καταργήστε όλα τα στοιχεία"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/en.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Please delete "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Please enter "+(e.minimum-e.input.length)+" or more characters"},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var n="You can only select "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No results found"},searching:function(){return"Searching…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/es.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"No se pudieron cargar los resultados"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Por favor, elimine "+n+" car";return r+=1==n?"ácter":"acteres"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Por favor, introduzca "+n+" car";return r+=1==n?"ácter":"acteres"},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var n="Sólo puede seleccionar "+e.maximum+" elemento";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Eliminar todos los elementos"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/et.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var n=e.input.length-e.maximum,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" vähem"},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" rohkem"},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var n="Saad vaid "+e.maximum+" tulemus";return 1==e.maximum?n+="e":n+="t",n+=" valida"},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"},removeAllItems:function(){return"Eemalda kõik esemed"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/eu.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gutxiago"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gehiago"},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return 1===e.maximum?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"},removeAllItems:function(){return"Kendu elementu guztiak"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/fa.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(n){return"لطفاً "+(n.input.length-n.maximum)+" کاراکتر را حذف نمایید"},inputTooShort:function(n){return"لطفاً تعداد "+(n.minimum-n.input.length)+" کاراکتر یا بیشتر وارد نمایید"},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(n){return"شما تنها میتوانید "+n.maximum+" آیتم را انتخاب نمایید"},noResults:function(){return"هیچ نتیجهای یافت نشد"},searching:function(){return"در حال جستجو..."},removeAllItems:function(){return"همه موارد را حذف کنید"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/fi.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fi",[],function(){return{errorLoading:function(){return"Tuloksia ei saatu ladattua."},inputTooLong:function(n){return"Ole hyvä ja anna "+(n.input.length-n.maximum)+" merkkiä vähemmän"},inputTooShort:function(n){return"Ole hyvä ja anna "+(n.minimum-n.input.length)+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(n){return"Voit valita ainoastaan "+n.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){return"Haetaan…"},removeAllItems:function(){return"Poista kaikki kohteet"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/fr.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var n=e.input.length-e.maximum;return"Supprimez "+n+" caractère"+(n>1?"s":"")},inputTooShort:function(e){var n=e.minimum-e.input.length;return"Saisissez au moins "+n+" caractère"+(n>1?"s":"")},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1?"s":"")},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"},removeAllItems:function(){return"Supprimer tous les éléments"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/gl.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/gl",[],function(){return{errorLoading:function(){return"Non foi posíbel cargar os resultados."},inputTooLong:function(e){var n=e.input.length-e.maximum;return 1===n?"Elimine un carácter":"Elimine "+n+" caracteres"},inputTooShort:function(e){var n=e.minimum-e.input.length;return 1===n?"Engada un carácter":"Engada "+n+" caracteres"},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){return 1===e.maximum?"Só pode seleccionar un elemento":"Só pode seleccionar "+e.maximum+" elementos"},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Elimina todos os elementos"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/he.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="נא למחוק ";return r+=1===e?"תו אחד":e+" תווים"},inputTooShort:function(n){var e=n.minimum-n.input.length,r="נא להכניס ";return r+=1===e?"תו אחד":e+" תווים",r+=" או יותר"},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(n){var e="באפשרותך לבחור עד ";return 1===n.maximum?e+="פריט אחד":e+=n.maximum+" פריטים",e},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"},removeAllItems:function(){return"הסר את כל הפריטים"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/hi.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(n){var e=n.input.length-n.maximum,r=e+" अक्षर को हटा दें";return e>1&&(r=e+" अक्षरों को हटा दें "),r},inputTooShort:function(n){return"कृपया "+(n.minimum-n.input.length)+" या अधिक अक्षर दर्ज करें"},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(n){return"आप केवल "+n.maximum+" आइटम का चयन कर सकते हैं"},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."},removeAllItems:function(){return"सभी वस्तुओं को हटा दें"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/hr.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hr",[],function(){function n(n){var e=" "+n+" znak";return n%10<5&&n%10>0&&(n%100<5||n%100>19)?n%10>1&&(e+="a"):e+="ova",e}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(e){return"Unesite "+n(e.input.length-e.maximum)},inputTooShort:function(e){return"Unesite još "+n(e.minimum-e.input.length)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(n){return"Maksimalan broj odabranih stavki je "+n.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Ukloni sve stavke"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/hsb.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hsb",[],function(){var n=["znamješko","znamješce","znamješka","znamješkow"],e=["zapisk","zapiskaj","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njedachu so začitać."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Prošu zhašej "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Prošu zapodaj znajmjeńša "+a+" "+u(a,n)},loadingMore:function(){return"Dalše wuslědki so začitaja…"},maximumSelected:function(n){return"Móžeš jenož "+n.maximum+" "+u(n.maximum,e)+"wubrać"},noResults:function(){return"Žane wuslědki namakane"},searching:function(){return"Pyta so…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/hu.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/hu",[],function(){return{errorLoading:function(){return"Az eredmények betöltése nem sikerült."},inputTooLong:function(e){return"Túl hosszú. "+(e.input.length-e.maximum)+" karakterrel több, mint kellene."},inputTooShort:function(e){return"Túl rövid. Még "+(e.minimum-e.input.length)+" karakter hiányzik."},loadingMore:function(){return"Töltés…"},maximumSelected:function(e){return"Csak "+e.maximum+" elemet lehet kiválasztani."},noResults:function(){return"Nincs találat."},searching:function(){return"Keresés…"},removeAllItems:function(){return"Távolítson el minden elemet"}}}),e.define,e.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/hy.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hy",[],function(){return{errorLoading:function(){return"Արդյունքները հնարավոր չէ բեռնել։"},inputTooLong:function(n){return"Խնդրում ենք հեռացնել "+(n.input.length-n.maximum)+" նշան"},inputTooShort:function(n){return"Խնդրում ենք մուտքագրել "+(n.minimum-n.input.length)+" կամ ավել նշաններ"},loadingMore:function(){return"Բեռնվում են նոր արդյունքներ․․․"},maximumSelected:function(n){return"Դուք կարող եք ընտրել առավելագույնը "+n.maximum+" կետ"},noResults:function(){return"Արդյունքներ չեն գտնվել"},searching:function(){return"Որոնում․․․"},removeAllItems:function(){return"Հեռացնել բոլոր տարրերը"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/id.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(n){return"Hapuskan "+(n.input.length-n.maximum)+" huruf"},inputTooShort:function(n){return"Masukkan "+(n.minimum-n.input.length)+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(n){return"Anda hanya dapat memilih "+n.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Hapus semua item"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/is.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/is",[],function(){return{inputTooLong:function(n){var t=n.input.length-n.maximum,e="Vinsamlegast styttið texta um "+t+" staf";return t<=1?e:e+"i"},inputTooShort:function(n){var t=n.minimum-n.input.length,e="Vinsamlegast skrifið "+t+" staf";return t>1&&(e+="i"),e+=" í viðbót"},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(n){return"Þú getur aðeins valið "+n.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"},removeAllItems:function(){return"Fjarlægðu öll atriði"}}}),n.define,n.require}();
|
||||||
3
staticfiles/admin/js/vendor/select2/i18n/it.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
|
||||||
|
|
||||||
|
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Per favore cancella "+n+" caratter";return t+=1!==n?"i":"e"},inputTooShort:function(e){return"Per favore inserisci "+(e.minimum-e.input.length)+" o più caratteri"},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var n="Puoi selezionare solo "+e.maximum+" element";return 1!==e.maximum?n+="i":n+="o",n},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"},removeAllItems:function(){return"Rimuovi tutti gli oggetti"}}}),e.define,e.require}();
|
||||||