major styling additions & refinements; offloaded navbar from base.html into its own partial, core/_partials/_navbar.html, alongside new _footer.html; 0006 dash migrations fix 0003 & 0005 theme-switcher handling and rename more fluidly to palette; added remaining realm-swatches to palette applet choices & updated test_views accordingly
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -4,7 +4,7 @@ from django.db import migrations
|
|||||||
def seed_applets(apps, schema_editor):
|
def seed_applets(apps, schema_editor):
|
||||||
Applet = apps.get_model("dashboard", "Applet")
|
Applet = apps.get_model("dashboard", "Applet")
|
||||||
Applet.objects.get_or_create(slug="username", defaults={"name": "Username"})
|
Applet.objects.get_or_create(slug="username", defaults={"name": "Username"})
|
||||||
Applet.objects.get_or_create(slug="palette", defaults={"name": "Palette"})
|
Applet.objects.get_or_create(slug="theme-switcher", defaults={"name": "Theme Switcher"})
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from django.db import migrations
|
|||||||
|
|
||||||
def set_grid_defaults(apps, schema_editor):
|
def set_grid_defaults(apps, schema_editor):
|
||||||
Applet = apps.get_model("dashboard", "Applet")
|
Applet = apps.get_model("dashboard", "Applet")
|
||||||
Applet.objects.filter(slug__in=["username", "palette"]).update(grid_cols=6, grid_rows=3)
|
Applet.objects.filter(slug__in=["username", "theme-switcher"]).update(grid_cols=6, grid_rows=3)
|
||||||
Applet.objects.get_or_create(slug="new-list", defaults={"name": "New List", "grid_cols": 9, "grid_rows": 3})
|
Applet.objects.get_or_create(slug="new-list", defaults={"name": "New List", "grid_cols": 9, "grid_rows": 3})
|
||||||
Applet.objects.get_or_create(slug="my-lists", defaults={"name": "My Lists", "grid_cols": 3, "grid_rows": 3})
|
Applet.objects.get_or_create(slug="my-lists", defaults={"name": "My Lists", "grid_cols": 3, "grid_rows": 3})
|
||||||
|
|
||||||
|
|||||||
18
src/apps/dashboard/migrations/0006_rename_theme_switcher.py
Normal file
18
src/apps/dashboard/migrations/0006_rename_theme_switcher.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def rename_theme_switcher(apps, schema_editor):
|
||||||
|
Applet = apps.get_model("dashboard", "Applet")
|
||||||
|
Applet.objects.filter(slug="theme-switcher").update(
|
||||||
|
slug="palette", name="Palette", grid_cols=6, grid_rows=3
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("dashboard", "0005_set_applet_grid_defaults"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(rename_theme_switcher, migrations.RunPython.noop),
|
||||||
|
]
|
||||||
@@ -2,8 +2,29 @@
|
|||||||
const initialize = (inputSelector) => {
|
const initialize = (inputSelector) => {
|
||||||
// console.log("initialize called!");
|
// console.log("initialize called!");
|
||||||
const textInput = document.querySelector(inputSelector);
|
const textInput = document.querySelector(inputSelector);
|
||||||
|
if (!textInput) return;
|
||||||
textInput.oninput = () => {
|
textInput.oninput = () => {
|
||||||
// console.log("oninput triggered");
|
// console.log("oninput triggered");
|
||||||
textInput.classList.remove("is-invalid");
|
textInput.classList.remove("is-invalid");
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const initGearMenu = () => {
|
||||||
|
const gear = document.getElementById('id_dash_gear');
|
||||||
|
if (!gear) return;
|
||||||
|
|
||||||
|
gear.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const menu = document.getElementById('id_applet_menu');
|
||||||
|
if (!menu) return;
|
||||||
|
menu.style.display = menu.style.display === 'none' ? 'block' : 'none';
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
const menu = document.getElementById('id_applet_menu');
|
||||||
|
if (!menu || menu.style.display === 'none') return;
|
||||||
|
if (e.target.closest('#id_applet_menu_cancel') || !menu.contains(e.target)) {
|
||||||
|
menu.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -313,7 +313,8 @@ class SetPaletteTest(TestCase):
|
|||||||
response = self.client.get(self.url)
|
response = self.client.get(self.url)
|
||||||
parsed = lxml.html.fromstring(response.content)
|
parsed = lxml.html.fromstring(response.content)
|
||||||
locked = parsed.cssselect(".swatch.locked")
|
locked = parsed.cssselect(".swatch.locked")
|
||||||
self.assertEqual(len(locked), 2)
|
expected_locked = [p for p in response.context["palettes"] if p["locked"]]
|
||||||
|
self.assertEqual(len(locked), len(expected_locked))
|
||||||
# they mustn't be button els
|
# they mustn't be button els
|
||||||
for swatch in locked:
|
for swatch in locked:
|
||||||
self.assertNotEqual(swatch.tag, "button")
|
self.assertNotEqual(swatch.tag, "button")
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ PALETTES = [
|
|||||||
{"name": "palette-default", "label": "Earthman", "locked": False},
|
{"name": "palette-default", "label": "Earthman", "locked": False},
|
||||||
{"name": "palette-nirvana", "label": "Nirvana", "locked": True},
|
{"name": "palette-nirvana", "label": "Nirvana", "locked": True},
|
||||||
{"name": "palette-sheol", "label": "Sheol", "locked": True},
|
{"name": "palette-sheol", "label": "Sheol", "locked": True},
|
||||||
|
{"name": "palette-inferno", "label": "Inferno", "locked": True},
|
||||||
|
{"name": "palette-terrestre", "label": "Terrestre", "locked": True},
|
||||||
|
{"name": "palette-celestia", "label": "Celestia", "locked": True},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from apps.dashboard.models import Applet
|
|||||||
class DashboardMaintenanceTest(FunctionalTest):
|
class DashboardMaintenanceTest(FunctionalTest):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
Applet.objects.get_or_create(slug="new-list", defaults={"name": "New List"})
|
||||||
Applet.objects.get_or_create(slug="username", defaults={"name": "Username"})
|
Applet.objects.get_or_create(slug="username", defaults={"name": "Username"})
|
||||||
Applet.objects.get_or_create(slug="palette", defaults={"name": "Palette"})
|
Applet.objects.get_or_create(slug="palette", defaults={"name": "Palette"})
|
||||||
|
|
||||||
@@ -114,3 +115,46 @@ class DashboardMaintenanceTest(FunctionalTest):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.assertTrue(self.browser.execute_script("return window.__no_reload_marker === true"))
|
self.assertTrue(self.browser.execute_script("return window.__no_reload_marker === true"))
|
||||||
|
|
||||||
|
class AppletMenuDismissTest(FunctionalTest):
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
Applet.objects.get_or_create(slug="username", defaults={"name": "Username"})
|
||||||
|
Applet.objects.get_or_create(slug="palette", defaults={"name": "Palette"})
|
||||||
|
self.create_pre_authenticated_session("discoman@example.com")
|
||||||
|
self.browser.get(self.live_server_url)
|
||||||
|
|
||||||
|
def _open_menu(self):
|
||||||
|
self.browser.find_element(By.ID, "id_dash_gear").click()
|
||||||
|
self.wait_for(
|
||||||
|
lambda: self.assertTrue(
|
||||||
|
self.browser.find_element(By.ID, "id_applet_menu").is_displayed()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_gear_click_toggles_menu_closed(self):
|
||||||
|
self._open_menu()
|
||||||
|
self.browser.find_element(By.ID, "id_dash_gear").click()
|
||||||
|
self.wait_for(
|
||||||
|
lambda: self.assertFalse(
|
||||||
|
self.browser.find_element(By.ID, "id_applet_menu").is_displayed()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_nvm_btn_closes_menu(self):
|
||||||
|
self._open_menu()
|
||||||
|
self.browser.find_element(By.ID, "id_applet_menu_cancel").click()
|
||||||
|
self.wait_for(
|
||||||
|
lambda: self.assertFalse(
|
||||||
|
self.browser.find_element(By.ID, "id_applet_menu").is_displayed()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_click_outside_closes_menu(self):
|
||||||
|
self._open_menu()
|
||||||
|
self.browser.find_element(By.TAG_NAME, "h2").click()
|
||||||
|
self.wait_for(
|
||||||
|
lambda: self.assertFalse(
|
||||||
|
self.browser.find_element(By.ID, "id_applet_menu").is_displayed()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|||||||
@@ -26,24 +26,40 @@ body {
|
|||||||
padding: 0.75rem 0;
|
padding: 0.75rem 0;
|
||||||
border-bottom: 0.1rem solid rgba(var(--secUser), 0.4);
|
border-bottom: 0.1rem solid rgba(var(--secUser), 0.4);
|
||||||
|
|
||||||
.container-fluid {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-brand {
|
.navbar-brand {
|
||||||
margin-right: auto;
|
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container-fluid {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
> form { flex-shrink: 0; margin-left: auto; }
|
||||||
|
}
|
||||||
|
|
||||||
.navbar-text,
|
.navbar-text,
|
||||||
.navbar-link {
|
.navbar-link {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.navbar-label {
|
||||||
|
display: block;
|
||||||
|
color: rgba(var(--secUser), 0.7);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-identity {
|
||||||
|
display: block;
|
||||||
color: rgba(var(--quaUser), 1);
|
color: rgba(var(--quaUser), 1);
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,3 +150,17 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#id_footer {
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 3rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-top: 0.1rem solid rgba(var(--secUser), 0.3);
|
||||||
|
background: linear-gradient(
|
||||||
|
to top,
|
||||||
|
rgba(var(--priUser), 1) 25%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -268,6 +268,7 @@
|
|||||||
&.btn-disabled {
|
&.btn-disabled {
|
||||||
cursor: default !important;
|
cursor: default !important;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
|
padding-bottom: 0.1rem;
|
||||||
color: rgba(var(--secUser), 0.25);
|
color: rgba(var(--secUser), 0.25);
|
||||||
background-color: rgba(var(--priUser), 1);
|
background-color: rgba(var(--priUser), 1);
|
||||||
border-color: rgba(var(--secUser), 0.25);
|
border-color: rgba(var(--secUser), 0.25);
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
|
html:has(body.page-dashboard) {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
body.page-dashboard {
|
body.page-dashboard {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
@@ -12,6 +20,7 @@ body.page-dashboard {
|
|||||||
|
|
||||||
#id_dash_content {
|
#id_dash_content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 425px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -20,72 +29,117 @@ body.page-dashboard {
|
|||||||
|
|
||||||
#id_dash_gear {
|
#id_dash_gear {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.5rem;
|
bottom: 0.5rem;
|
||||||
right: 0.5rem;
|
right: 0.5rem;
|
||||||
|
padding-bottom: 0.2rem;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
font-size: 1.5rem;
|
font-size: 2rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: rgba(var(--secUser), 0.6);
|
color: rgba(var(--secUser), 1);
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 2rem;
|
width: 3rem;
|
||||||
height: 2rem;
|
height: 3rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: rgba(var(--priUser), 0.85);
|
background-color: rgba(var(--priUser), 1);
|
||||||
border: 0.15rem solid rgba(var(--secUser), 0.15);
|
border: 0.15rem solid rgba(var(--secUser), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#id_applet_menu {
|
#id_applet_menu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 3rem;
|
bottom: 3rem;
|
||||||
right: 0.5rem;
|
right: 0.5rem;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
background-color: rgba(var(--priUser), 0.95);
|
background-color: rgba(var(--priUser), 0.95);
|
||||||
border: 0.15rem solid rgba(var(--secUser), 0.5);
|
border: 0.15rem solid rgba(var(--secUser), 0.5);
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
|
.menu-btns {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#id_applets_container {
|
#id_applets_container {
|
||||||
container-type: inline-size;
|
container-type: inline-size;
|
||||||
--grid-gap: 0.5rem;
|
--grid-gap: 0.5rem;
|
||||||
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(12, 1fr);
|
grid-template-columns: repeat(12, 1fr);
|
||||||
grid-auto-rows: 3rem;
|
grid-auto-rows: 3rem;
|
||||||
gap: var(--grid-gap);
|
gap: var(--grid-gap);
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
mask-image: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
transparent 0%,
|
||||||
|
black 2%,
|
||||||
|
black 98%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
|
||||||
section {
|
section {
|
||||||
border: 0.2rem solid rgba(var(--secUser), 0.5);
|
border: 0.2rem solid rgba(var(--secUser), 0.5);
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
min-width: 0;
|
||||||
grid-column: span var(--applet-cols, 12);
|
grid-column: span var(--applet-cols, 12);
|
||||||
grid-row: span var(--applet-rows, 3);
|
grid-row: span var(--applet-rows, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#id_applet_my_lists {
|
||||||
|
padding: 1.25rem 1.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.my-lists-main {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-lists-container {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
scrollbar-width: none;
|
||||||
|
&::-webkit-scrollbar { display: none; }
|
||||||
|
mask-origin: padding-box;
|
||||||
|
mask-clip: padding-box;
|
||||||
|
mask-image: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
transparent 0%,
|
||||||
|
black 5%,
|
||||||
|
black 85%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#id_applet_palette {
|
#id_applet_palette {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
.palette-scroll {
|
.palette-scroll {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 3.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
padding: 1rem;
|
padding: 0.75rem 2rem;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
&::-webkit-scrollbar { display: none; }
|
&::-webkit-scrollbar { display: none; }
|
||||||
mask-image: linear-gradient(
|
mask-image: linear-gradient(
|
||||||
to right,
|
to right,
|
||||||
transparent 0%,
|
transparent 0%,
|
||||||
black 8%,
|
black 2%,
|
||||||
black 92%,
|
black 98%,
|
||||||
transparent 100%
|
transparent 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -94,15 +148,34 @@ body.page-dashboard {
|
|||||||
#id_applet_username {
|
#id_applet_username {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
form {
|
||||||
|
min-width: 0;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.save-btn {
|
||||||
|
align-self: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.username-field {
|
.username-field {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
gap: 0.1em;
|
gap: 0.1em;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.username-at{
|
.username-at{
|
||||||
user-select: none;
|
user-select: none;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: rgba(var(--secUser), 0.875);
|
||||||
|
margin-left: 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@@ -114,13 +187,24 @@ body.page-dashboard {
|
|||||||
color: rgba(var(--secUser), 0.875);;
|
color: rgba(var(--secUser), 0.875);;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: auto;
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@container (max-width: 480px) {
|
}
|
||||||
|
|
||||||
|
@media (max-width: 550px) {
|
||||||
|
#id_dash_content {
|
||||||
|
min-width: 380px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#id_applets_container {
|
||||||
section {
|
section {
|
||||||
grid-column: span 12;
|
grid-column: span 12;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,14 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
flex: 0 0 calc(50% - 0.375rem);
|
flex: 0 0 auto;
|
||||||
|
height: 100%;
|
||||||
scroll-snap-align: start;
|
scroll-snap-align: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.swatch {
|
.swatch {
|
||||||
width: 100%;
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
|
|||||||
@@ -18,7 +18,10 @@
|
|||||||
{{ entry.applet.name }}
|
{{ entry.applet.name }}
|
||||||
</label>
|
</label>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
<div class="menu-btns">
|
||||||
<button type="submit" class="btn btn-confirm">OK</button>
|
<button type="submit" class="btn btn-confirm">OK</button>
|
||||||
|
<button type="button" id="id_applet_menu_cancel" class="btn btn-cancel">NVM</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -38,7 +41,8 @@
|
|||||||
id="id_applet_my_lists"
|
id="id_applet_my_lists"
|
||||||
style="--applet-cols: {{ entry.applet.grid_cols }}; --applet-rows: {{ entry.applet.grid_rows }};"
|
style="--applet-cols: {{ entry.applet.grid_cols }}; --applet-rows: {{ entry.applet.grid_rows }};"
|
||||||
>
|
>
|
||||||
<a href="{% url 'my_lists' user.id %}">My lists:</a>
|
<a href="{% url 'my_lists' user.id %}" class="my-lists-main">My lists:</a>
|
||||||
|
<div class="my-lists-container">
|
||||||
<ul>
|
<ul>
|
||||||
{% for list in recent_lists %}
|
{% for list in recent_lists %}
|
||||||
<li>
|
<li>
|
||||||
@@ -48,6 +52,7 @@
|
|||||||
<li>No lists yet.</li>
|
<li>No lists yet.</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% elif entry.applet.slug == "username" %}
|
{% elif entry.applet.slug == "username" %}
|
||||||
<section
|
<section
|
||||||
@@ -57,15 +62,17 @@
|
|||||||
<form method="POST" action="{% url "set_profile" %}">
|
<form method="POST" action="{% url "set_profile" %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="username-field">
|
<div class="username-field">
|
||||||
<span class="username-at"><h1>@</h1></span>
|
<span class="username-at">@</span>
|
||||||
<input
|
<input
|
||||||
id="id_new_username"
|
id="id_new_username"
|
||||||
name="username"
|
name="username"
|
||||||
required
|
required
|
||||||
value="{{ user.username|default:'' }}"
|
value="{{ user.username|default:'' }}"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
|
placeholder="username"
|
||||||
data-original="{{ user.username|default:'' }}"
|
data-original="{{ user.username|default:'' }}"
|
||||||
oninput="this.closest('form').querySelector('.save-btn').hidden = (this.value === this.dataset.original)"
|
oninput="this.closest('form').querySelector('.save-btn').hidden = (this.value === this.dataset.original)"
|
||||||
|
onblur="this.scrollLeft = 0"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-confirm save-btn" hidden>OK</button>
|
<button type="submit" class="btn btn-confirm save-btn" hidden>OK</button>
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
<script>
|
<script>
|
||||||
window.onload = () => {
|
window.onload = () => {
|
||||||
initialize("#id_text");
|
initialize("#id_text");
|
||||||
|
initGearMenu();
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -11,12 +11,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<div id="id_dash_content">
|
<div id="id_dash_content">
|
||||||
<button
|
<button id="id_dash_gear">⚙</button>
|
||||||
id="id_dash_gear"
|
|
||||||
onclick="document.getElementById('id_applet_menu').style.display='block'"
|
|
||||||
>
|
|
||||||
⚙
|
|
||||||
</button>
|
|
||||||
{% include "apps/dashboard/_partials/_applets.html" %}
|
{% include "apps/dashboard/_partials/_applets.html" %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
5
src/templates/core/_partials/_footer.html
Normal file
5
src/templates/core/_partials/_footer.html
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<footer id="id_footer">
|
||||||
|
<div class="footer-container">
|
||||||
|
<small>©2026 Dis Co.</small>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
39
src/templates/core/_partials/_navbar.html
Normal file
39
src/templates/core/_partials/_navbar.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{% load lyric_extras %}
|
||||||
|
<nav class="navbar">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a href="/" class="navbar-brand">
|
||||||
|
<h1>Welcome,<br>Earthman</h1>
|
||||||
|
</a>
|
||||||
|
{% if user.email %}
|
||||||
|
<div class="navbar-text">
|
||||||
|
<span class="navbar-label">
|
||||||
|
Logged in as
|
||||||
|
</span>
|
||||||
|
<span class="navbar-identity">
|
||||||
|
@{{ user|display_name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<form method="POST" action="{% url "logout" %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button id="id_logout" class="btn btn-primary btn-xl" type="submit">
|
||||||
|
Log Out
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<form method="POST" action="{% url "send_login_email" %}">
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="id_email_input" class="navbar-text me-2">
|
||||||
|
enter email for login:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="id_email_input"
|
||||||
|
name="email"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="your@email.here"
|
||||||
|
>
|
||||||
|
{% csrf_token %}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{% load compress %}
|
{% load compress %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load lyric_extras %}
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@@ -18,37 +18,7 @@
|
|||||||
|
|
||||||
<body class="{{ user_palette }} {{ page_class|default:'' }}">
|
<body class="{{ user_palette }} {{ page_class|default:'' }}">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<nav class="navbar">
|
{% include "core/_partials/_navbar.html" %}
|
||||||
<div class="container-fluid">
|
|
||||||
<a href="/" class="navbar-brand">
|
|
||||||
<h1>Welcome, Earthman</h1>
|
|
||||||
</a>
|
|
||||||
{% if user.email %}
|
|
||||||
<span class="navbar-text">Logged in as {{ user|display_name }}</span>
|
|
||||||
<form method="POST" action="{% url "logout" %}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<button id="id_logout" class="btn btn-primary btn-xl" type="submit">
|
|
||||||
Log Out
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
{% else %}
|
|
||||||
<form method="POST" action="{% url "send_login_email" %}">
|
|
||||||
<div class="input-group">
|
|
||||||
<label for="id_email_input" class="navbar-text me-2">
|
|
||||||
enter email for login:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="id_email_input"
|
|
||||||
name="email"
|
|
||||||
class="form-control"
|
|
||||||
placeholder="your@email.here"
|
|
||||||
>
|
|
||||||
{% csrf_token %}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -77,6 +47,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% include "core/_partials/_footer.html" %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
{% endblock scripts %}
|
{% endblock scripts %}
|
||||||
<script src="{% static "vendor/htmx.min.js" %}"></script>
|
<script src="{% static "vendor/htmx.min.js" %}"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user