From 69482207461eec9c3c64ec297231989aa248dd9a Mon Sep 17 00:00:00 2001
From: retoor <retoor@molodetz.nl>
Date: Thu, 3 Apr 2025 08:35:25 +0200
Subject: [PATCH] Progress

---
 .gitignore                               |  1 +
 src/snek/form/settings/profile.py        | 14 +++++++++
 src/snek/mapper/user_property.py         |  7 +++++
 src/snek/model/user_property.py          | 10 +++++++
 src/snek/templates/app_menu.html         | 13 +++++++++
 src/snek/templates/settings/index.html   | 37 ++++++++++++++++++++++++
 src/snek/templates/settings/profile.html | 31 ++++++++++++++++++++
 src/snek/templates/settings/sidebar.html |  9 ++++++
 src/snek/view/settings/index.py          |  8 +++++
 src/snek/view/settings/profile.py        | 36 +++++++++++++++++++++++
 10 files changed, 166 insertions(+)
 create mode 100644 src/snek/form/settings/profile.py
 create mode 100644 src/snek/mapper/user_property.py
 create mode 100644 src/snek/model/user_property.py
 create mode 100644 src/snek/templates/app_menu.html
 create mode 100644 src/snek/templates/settings/index.html
 create mode 100644 src/snek/templates/settings/profile.html
 create mode 100644 src/snek/templates/settings/sidebar.html
 create mode 100644 src/snek/view/settings/index.py
 create mode 100644 src/snek/view/settings/profile.py

diff --git a/.gitignore b/.gitignore
index ce8bd16..e83eedd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.r_history
 .vscode
 .history
 .resources
diff --git a/src/snek/form/settings/profile.py b/src/snek/form/settings/profile.py
new file mode 100644
index 0000000..24eb884
--- /dev/null
+++ b/src/snek/form/settings/profile.py
@@ -0,0 +1,14 @@
+from snek.system.form import Form, FormInputElement, FormButtonElement, HTMLElement
+
+
+class SettingsProfileForm(Form):
+
+    nick = FormInputElement(name="nick", required=True, place_holder="Your Nickname", min_length=1, max_length=20)
+    action = FormButtonElement(
+        name="action", value="submit", text="Save", type="button"
+    )
+    title = HTMLElement(tag="h1", text="Profile")
+    profile = FormInputElement(name="profile", place_holder="Tell about yourself.", required=False,max_length=300)
+    action = FormButtonElement(
+        name="action", value="submit", text="Save", type="button"
+    )
\ No newline at end of file
diff --git a/src/snek/mapper/user_property.py b/src/snek/mapper/user_property.py
new file mode 100644
index 0000000..7359f60
--- /dev/null
+++ b/src/snek/mapper/user_property.py
@@ -0,0 +1,7 @@
+from snek.model.user_property import UserPropertyModel
+from snek.system.mapper import BaseMapper
+
+
+class UserPropertyMapper(BaseMapper):
+    table_name = "user_property"
+    model_class = UserPropertyModel
diff --git a/src/snek/model/user_property.py b/src/snek/model/user_property.py
new file mode 100644
index 0000000..7f0113c
--- /dev/null
+++ b/src/snek/model/user_property.py
@@ -0,0 +1,10 @@
+import mimetypes
+
+from snek.system.model import BaseModel, ModelField
+
+
+class UserPropertyModel(BaseModel):
+    user_uid = ModelField(name="user_uid", required=True, kind=str)
+    name = ModelField(name="name", required=True, kind=str)
+    value = ModelField(name="path", required=True, kind=str)
+    
diff --git a/src/snek/templates/app_menu.html b/src/snek/templates/app_menu.html
new file mode 100644
index 0000000..ffcdfd5
--- /dev/null
+++ b/src/snek/templates/app_menu.html
@@ -0,0 +1,13 @@
+  <div>
+    <div class="logo no-select">Test</div>
+    <nav class="no-select" style="float:right;overflow:hidden;scroll-behavior:smooth">
+      <a class="no-select" href="/web.html">🏠</a>
+      <a class="no-select" href="/search-user.html">🔍</a>
+      <a class="no-select" style="display:none" id="install-button" href="#">📥</a>
+      <a class="no-select" href="/threads.html">👥</a>
+      <a class="no-select" href="#">⚙️</a>
+      <a class="no-select" href="/logout.html">🔒</a>
+    </nav>
+
+  </div>
+
diff --git a/src/snek/templates/settings/index.html b/src/snek/templates/settings/index.html
new file mode 100644
index 0000000..f91fc5d
--- /dev/null
+++ b/src/snek/templates/settings/index.html
@@ -0,0 +1,37 @@
+{% extends "app.html" %}
+
+{% block sidebar %}
+
+{% include "settings/sidebar.html" %}
+
+{% endblock %}
+
+{% block header_text %}<h2 style="color:#fff">Settings</h2>{% endblock %}
+
+{% block head %}
+   <link href="https://cdn.bootcdn.net/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.min.css" rel="stylesheet">
+
+    <script src="https://cdn.bootcdn.net/ajax/libs/monaco-editor/0.20.0/min/vs/loader.min.js"></script>
+
+{% endblock %}
+
+{% block main %}
+
+
+<div id="profile_description"></div>
+
+
+
+<script type="module">
+
+        require.config({ paths: { 'vs': 'https://cdn.bootcdn.net/ajax/libs/monaco-editor/0.20.0/min/vs' } });
+
+        require(['vs/editor/editor.main'], function () {
+var editor = monaco.editor.create(document.getElementById('profile_description'), {
+                value: phpCode,
+                language: 'php'
+            });
+        })
+</script>
+
+{% endblock main %}
diff --git a/src/snek/templates/settings/profile.html b/src/snek/templates/settings/profile.html
new file mode 100644
index 0000000..964f9b7
--- /dev/null
+++ b/src/snek/templates/settings/profile.html
@@ -0,0 +1,31 @@
+{% extends "settings/index.html" %}
+
+{% block header_text %}<h2 style="color:#fff">Profile</h2>{% endblock %}
+
+{% block main %}
+<section>
+<form>
+    <h2>Nickname</h2>
+    
+<input type="text" name="nick" placeholder="Your nickname" value="{{ user.nick.value }}" />
+
+</form>
+<h2>Description</h2>
+
+
+<textarea id="profile"></textarea>
+</section>
+<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css">
+<script src="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js"></script>
+<script>
+    const easyMDE = new EasyMDE({element:document.getElementById("profile")});
+    </script>
+<style>
+
+.EasyMDEContainer {
+        filter: invert(1) !important;
+     
+    }
+    
+    </style>
+{% endblock %}
diff --git a/src/snek/templates/settings/sidebar.html b/src/snek/templates/settings/sidebar.html
new file mode 100644
index 0000000..f9533be
--- /dev/null
+++ b/src/snek/templates/settings/sidebar.html
@@ -0,0 +1,9 @@
+
+<aside class="sidebar" id="channelSidebar">
+    <h2>You</h2>
+    <ul>
+        <li><a class="no-select" href="/settings/profile.html">Profile</a></li>
+        <li><a class="no-select" href="/settings/gists.html">Gists</a></li>
+    </ul>
+
+  </aside>
diff --git a/src/snek/view/settings/index.py b/src/snek/view/settings/index.py
new file mode 100644
index 0000000..1e45b56
--- /dev/null
+++ b/src/snek/view/settings/index.py
@@ -0,0 +1,8 @@
+from snek.system.view import BaseView 
+
+class SettingsIndexView(BaseView):
+    
+    login_required = True
+
+    async def get(self):
+        return await self.render_template('settings/index.html')
diff --git a/src/snek/view/settings/profile.py b/src/snek/view/settings/profile.py
new file mode 100644
index 0000000..4e6638c
--- /dev/null
+++ b/src/snek/view/settings/profile.py
@@ -0,0 +1,36 @@
+from snek.system.view import BaseView,BaseFormView
+
+from snek.form.settings.profile import SettingsProfileForm
+from aiohttp import web
+
+
+class SettingsProfileView(BaseFormView):
+    form = SettingsProfileForm
+
+    login_required = True
+
+    async def get(self):
+        form = self.form(app=self.app)
+            
+        if self.request.path.endswith(".json"):
+            form['nick'] = self.request['user']['nick']
+            return web.json_response(await form.to_json()) 
+        
+        user = await self.services.user.get(uid=self.session.get("uid"))
+
+
+        return await self.render_template(
+            "settings/profile.html", {"form": await form.to_json(), "user": user}
+        )
+
+    async def submit(self, form):
+        post = await self.request.json()
+        form.set_user_data(post["form"])
+
+        if await form.is_valid:
+            user = self.request['user']
+            user["nick"] = form["nick"]
+            await self.services.user.save(user)
+            return {"redirect_url": "/settings/profile.html"}
+        return {"is_valid": False}
+