Compare commits

..

5 Commits

  1. 4
      TODO
  2. 74
      pages/base.html
  3. 78
      pages/category.html
  4. 76
      pages/index.html
  5. 4
      pages/paint.html
  6. 43
      src/misc/encryption.go

4
TODO

@ -1,4 +0,0 @@
1) Профиль
3) Темная/Светлая тема
Не SQLite3

74
pages/base.html

@ -1,62 +1,60 @@
{{ define "base" }} {{ define "base" }}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dela</title> <title>dela</title>
<link rel="shortcut icon" href="/static/images/favicon.ico" type="image/x-icon"> <link rel="shortcut icon" href="/static/images/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
<script src="/static/bootstrap/js/bootstrap.bundle.min.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script>
<style> <style>
html * { html * {
font-family: "Roboto", sans-serif !important; font-family: "Roboto" !important;
} src: url("/static/fonts/Roboto-Regular.ttf");
body { }
background-color: #f8f9fa;
}
header {
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style> </style>
</head> </head>
<body class="w-100 h-100"> <body class="w-100 h-100">
<header class="p-3 text-bg-warning-emphasis"> <header class="p-3 text-bg-primary">
<div class="container"> <div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-between"> <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
<a href="/" class="d-flex align-items-center text-white text-decoration-none"> <a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
<img width="64" height="64" src="/static/images/android-chrome-192x192.png" alt="Dela"> <a href="/" class="d-inline-flex link-body-emphasis text-decoration-none">
</a> <img width="64" height="64" src="/static/images/android-chrome-192x192.png" alt="Dela">
</a>
</a>
<nav class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0"> <ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
<a href="/" class="nav-link px-2 text-white">Main</a> <li><a href="/" class="nav-link px-2 text-white">Main</a></li>
<a href="/about" class="nav-link px-2 text-white">About</a> <li><a href="/about" class="nav-link px-2 text-white">About</a></li>
</nav> </ul>
<div class="d-flex align-items-center"> <div class="text-end p-3">
<button id="theme-switch-btn" class="btn btn-secondary me-2" onclick="toggleTheme();"> <button id="theme-switch-btn" class="btn btn-secondary" onclick="toggleTheme();">
<img id="theme-svg" src="/static/images/brightness-high.svg" alt="Change theme"> <img id="theme-svg" src="/static/images/brightness-high.svg" alt="Change theme">
</button> </button>
<div id="bar-auth" class="d-flex">
<a href="/login" class="btn btn-outline-light me-2">Login</a>
<a href="/register" class="btn btn-warning">Sign-up</a>
</div>
</div>
</div>
</div> </div>
</header> <div class="text-end" id="bar-auth">
<a href="/login" class="btn btn-outline-light me-2">Login</a>
<!-- Content --> <a href="/register" class="btn btn-warning">Sign-up</a>
<main class="container mt-4"> </div>
{{ template "content" . }} </div>
</main> </div>
</body> </div>
</header>
<!-- Content -->
{{ template "content" . }}
</body>
</html> </html>
<script src="/scripts/auth.js"></script> <script src="/scripts/auth.js"></script>
<script src="/scripts/api.js"></script> <script src="/scripts/api.js"></script>
<script> <script>

78
pages/category.html

@ -48,6 +48,27 @@
</div> </div>
<!-- End Paint Canvas Modal --> <!-- End Paint Canvas Modal -->
<!-- ToDo display Modal -->
<div class="modal fade" id="todoModal" tabindex="-1" aria-labelledby="todoModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="todoModalLabel">TODO Details</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p><strong>Text:</strong> <span id="modalTodoText"></span></p>
<p><strong>Created:</strong> <span id="modalTodoCreated"></span></p>
<p><strong>Due:</strong> <span id="modalTodoDue"></span></p>
<p><strong>Completion time:</strong> <span id="modalTodoCompletionTime"></span></p>
<img id="modalTodoImage" src="" class="img-fluid" style="display: none;">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Sidebar --> <!-- Sidebar -->
<div id="sidebar" class="col border-right shadow-lg flex-shrink-1 p-2 d-flex flex-column align-items-stretch bg-body-tertiary" style="width: 380px;"> <div id="sidebar" class="col border-right shadow-lg flex-shrink-1 p-2 d-flex flex-column align-items-stretch bg-body-tertiary" style="width: 380px;">
@ -75,27 +96,26 @@
<!-- Main ToDos section --> <!-- Main ToDos section -->
<div class="p-2 flex-grow-1"> <div class="p-2 flex-grow-1">
<form action="javascript:void(0);"> <form action="javascript:void(0);" id="todoForm">
<div class="container"> <div class="row g-3 align-items-center">
<div class="row"> <div class="col-md">
<div class="col"> <label for="newTodoText" class="form-label">TODO Text</label>
<input type="text" class="form-control" id="newTodoText" placeholder="TODO text"> <input type="text" class="form-control" id="newTodoText" placeholder="Enter TODO text" required>
</div> </div>
<div class="col"> <div class="col-md">
<label for="newTodoDue">Due</label> <label for="newTodoDue" class="form-label">Due Date</label>
<input aria-placeholder="Due" type="date" name="newTodoDue" id="newTodoDue" placeholder="Due"> <input type="date" class="form-control" name="newTodoDue" id="newTodoDue" required>
</div> </div>
<div class="col"> <div class="col-auto">
<button class="btn btn-primary" id="newTodoPaint" onclick="openPaintModal();">Paint</button> <button type="button" class="btn btn-primary" id="newTodoPaint" onclick="openPaintModal();">Paint</button>
</div> </div>
<div class="col"> <div class="col-auto">
<button id="newTodoSubmit" class="btn btn-primary">Add</button> <button type="submit" id="newTodoSubmit" class="btn btn-primary">Add</button>
<button class="btn btn-secondary" id="show-done">Show Done</button> <button type="button" id="show-done" class="btn btn-secondary">Show Done</button>
</div>
</div> </div>
</div> </div>
</form> </form>
<div class="container text-center"> <div class="container text-center">
<!-- Due --> <!-- Due -->
<table class="table table-hover" id="due-todos"> <table class="table table-hover" id="due-todos">
@ -108,7 +128,7 @@
<tbody class="text-break"> <tbody class="text-break">
{{ range .Todos }} {{ range .Todos }}
{{ if not .IsDone }} {{ if not .IsDone }}
<tr draggable="true" id="todo-{{.ID}}" ondragstart="dragStart(event);"> <tr onclick="openTodoModal('{{.ID}}', '{{.Text}}', '{{.TimeCreated}}', '{{.Due}}', null, '{{ printf "%s" .Image }}');" draggable="true" id="todo-{{.ID}}" ondragstart="dragStart(event);">
{{ if not .Image }} {{ if not .Image }}
<!-- Display transparent white pixel --> <!-- Display transparent white pixel -->
<td><img class="todo-image" src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' width="64px" height="64px"></td> <td><img class="todo-image" src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' width="64px" height="64px"></td>
@ -144,7 +164,7 @@
<tbody class="text-break"> <tbody class="text-break">
{{ range .Todos }} {{ range .Todos }}
{{ if .IsDone }} {{ if .IsDone }}
<tr> <tr onclick="openTodoModal('{{.ID}}', '{{.Text}}', '{{.TimeCreated}}', '{{.Due}}', '{{.CompletionTime}}', '{{ printf "%s" .Image }}');">
{{ if not .Image }} {{ if not .Image }}
<!-- Display transparent white pixel --> <!-- Display transparent white pixel -->
<td><img src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' width="64px" height="64px"></td> <td><img src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' width="64px" height="64px"></td>
@ -251,6 +271,24 @@ async function drop(event) {
window.location.reload(); window.location.reload();
} }
function openTodoModal(id, text, created, due, completionTime, image) {
document.getElementById('modalTodoText').innerText = text;
document.getElementById('modalTodoCreated').innerText = created;
document.getElementById('modalTodoDue').innerText = due;
document.getElementById('modalTodoCompletionTime').innerText = completionTime;
let img = document.getElementById('modalTodoImage');
if (img) {
img.src = image;
img.style.display = 'block';
} else {
img.style.display = 'none';
}
const todoModal = new bootstrap.Modal(document.getElementById('todoModal'));
todoModal.show();
}
document.addEventListener('DOMContentLoaded', async function() { document.addEventListener('DOMContentLoaded', async function() {
document.getElementById("newTodoText").focus(); document.getElementById("newTodoText").focus();

76
pages/index.html

@ -2,65 +2,67 @@
{{ define "content" }} {{ define "content" }}
<!-- Main --> <!-- Main -->
<main class="container mt-4"> <main>
<div class="d-flex flex-wrap"> <div class="d-flex flex-wrap">
<!-- Sidebar --> <!-- Sidebar -->
<aside id="sidebar" class="col-md-3 col-lg-2 border-end shadow-lg flex-shrink-1 p-3 d-flex flex-column align-items-stretch bg-light"> <div id="sidebar" class="col border-right shadow-lg flex-shrink-1 p-2 d-flex flex-column align-items-stretch bg-body-tertiary">
<a href="/" class="d-flex align-items-center flex-shrink-0 p-3 link-body-emphasis text-decoration-none border-bottom"> <a href="/" class="d-flex align-items-center flex-shrink-0 p-3 link-body-emphasis text-decoration-none border-bottom">
<img class="bi pe-none me-2" width="30" height="24" src="/static/images/arrows-fullscreen.svg" alt="Logo"> <img class="bi pe-none me-2" width="30" height="24" src="/static/images/arrows-fullscreen.svg">
<span class="fs-5 fw-semibold">Categories</span> <span class="fs-5 fw-semibold">Categories</span>
</a> </a>
<div class="list-group list-group-flush border-bottom scrollarea"> <div class="list-group list-group-flush border-bottom scrollarea">
{{ range .Groups }} {{ range .Groups }}
<a href="/group/{{.ID}}" class="list-group-item list-group-item-action py-3 lh-sm" aria-current="true"> <a href="/group/{{.ID}}" class="list-group-item list-group-item-action py-3 lh-sm" aria-current="true">
<div class="d-flex w-100 align-items-center justify-content-between"> <div class="d-flex w-100 align-items-center justify-content-between">
<strong class="mb-1">{{ .Name }}</strong> <strong class="mb-1">{{ .Name }}</strong>
<small>{{ .TimeCreated }}</small> <small>{{ .TimeCreated }}</small>
</div> </div>
{{ if not .Removable }} {{ if not .Removable }}
<div class="col-10 mb-1 small text-muted">Not removable</div> <div class="col-10 mb-1 small">Not removable</div>
{{ end }} {{ end }}
</a> </a>
{{ end }} {{ end }}
</div> </div>
<div class="input-group mb-3 mt-3">
<input type="text" name="newCategory" aria-label="Category Name" aria-describedby="button-new-category" class="form-control" id="new-category-input" placeholder="Category Name"> <div class="input-group mb-3 py-md-5">
<button id="button-new-category" onclick="createNewCategory();" class="btn btn-primary">Create</button> <input type="text" name="newCategory"aria-label="Category Name" aria-describedby="button-new-category" class="form-control" id="new-category-input" placeholder="Category Name">
<button id="button-new-category" onclick="createNewCategory();" class="btn btn-primary">Create</button >
</div> </div>
</aside> </div>
<!-- Groups --> <!-- Groups -->
<div class="col-md-9 col-lg-10 p-4"> <div class="d-flex flex-column flex-grow-1 flex-md-row p-4 gap-4 py-md-5">
<h2 class="mb-4">Available Categories</h2> <div class="list-group flex-grow-1">
<div class="list-group"> {{ range .Groups }}
{{ range .Groups }} <div class="list-group-item list-group-item-action d-flex gap-3 py-3" aria-current="true">
<div class="list-group-item list-group-item-action d-flex gap-3 py-3" aria-current="true"> <a href="/group/{{.ID}}" class="list-group-item list-group-item-action d-flex gap-3 py-3">
<a href="/group/{{.ID}}" class="d-flex gap-3 w-100"> <img src="/static/images/box-arrow-up-right.svg" alt="Go to this category" width="32" height="32">
<img src="/static/images/box-arrow-up-right.svg" alt="Go to this category" width="32" height="32"> <div class="d-flex gap-2 w-100 justify-content-between">
<div class="d-flex gap-2 w-100 justify-content-between"> <div>
<div> <h6 class="mb-0">{{ .Name }}</h6>
<h6 class="mb-0">{{ .Name }}</h6> <p class="mb-0 opacity-75">Jump here</p>
<p class="mb-0 opacity-75">Jump here</p>
</div>
<small class="opacity-50 text-nowrap">{{ .TimeCreated }}</small>
</div> </div>
</a> <small class="opacity-50 text-nowrap">{{ .TimeCreated }}</small>
{{ if .Removable }} </div>
<div class="small"> </a>
<button class="btn btn-danger" onclick="deleteCategoryRefresh('{{.ID}}')"> {{ if .Removable }}
<img src="/static/images/trash3-fill.svg" alt="Remove category" width="20"> <div class="small">
</button> <button class="btn btn-danger" onclick="deleteCategoryRefresh('{{.ID}}')">
</div> <img src="/static/images/trash3-fill.svg" alt="Remove category">
{{ end }} </button>
</div> </div>
{{ end }} {{ end }}
</div> </div>
{{ end }}
</div>
</div> </div>
</div> </div>
</main> </main>
<script> <script>

4
pages/paint.html

@ -1,7 +1,7 @@
{{ define "paint" }} {{ define "paint" }}
<canvas class="row border border-dark" id="drawingCanvas" width="256" height="256"></canvas> <canvas class="row border border-secondary" id="drawingCanvas" width="256" height="256"></canvas>
<input class="row border border-dark" type="color" id="colorPicker" value="#000000" aria-label="Drawing color"> <input class="row border border-secondary" type="color" id="colorPicker" value="#000000" aria-label="Drawing color">
<script> <script>
const canvas = document.getElementById('drawingCanvas'); const canvas = document.getElementById('drawingCanvas');

43
src/misc/encryption.go

@ -1,43 +0,0 @@
/*
dela - web TODO list
Copyright (C) 2023 Kasyanov Nikolay Alexeyevich (Unbewohnte)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package misc
import (
"crypto/sha256"
"encoding/base64"
"fmt"
)
// Encodes given string via Base64
func EncodeString(str string) string {
return base64.StdEncoding.EncodeToString([]byte(str))
}
// Decodes given string via Base64
func DecodeString(encodedStr string) string {
decodedBytes, _ := base64.StdEncoding.DecodeString(encodedStr)
return string(decodedBytes)
}
// Returns HEX string of SHA256'd data
func SHA256Hex(data []byte) string {
hash := sha256.New()
hash.Write(data)
return fmt.Sprintf("%x", hash.Sum(nil))
}
Loading…
Cancel
Save