Merge branch 'develop' into user-repo

# Conflicts:
#	frontend/svelte/src/routes/+page.svelte
#	frontend/svelte/src/routes/login/+page.svelte
This commit is contained in:
s-prechtl 2022-10-11 13:14:41 +02:00
commit bee5b04441
20 changed files with 197 additions and 154 deletions

View file

@ -4,9 +4,16 @@
<meta charset="utf-8" />
<link rel="icon" href="../src/resources/images/logo2.svg" />
<meta name="viewport" content="width=device-width" />
<link rel="manifest" href="../static/manifest.json">
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
<script>
if('serviceworker' in navigator){
navigator.serviceworker.register('./service-worker.js');
}
</script>
</body>
</html>

View file

@ -0,0 +1,29 @@
html,
:root {
--main-txt-color: black;
--cross-txt-color: red;
--color-primary: #fff494;
--color-primary-600: #fff17a;
--color-primary-700: #ffec47;
--color-primary-800: #ffe714;
--color-primary-900: #e0c900;
}
.btn-primary {
background-color: var(--color-primary-800) !important;
border: var(--color-primary-800) !important;
color: var(--main-txt-color) !important;
}
.btn-primary:hover {
background-color: var(--color-primary-900) !important;
border: var(--color-primary-900) !important;
color: var(--main-txt-color) !important;
}
.btn-primary:disabled {
background-color: var(--color-primary-700) !important;
border: var(--color-primary-700) !important;
}

View file

@ -4,7 +4,7 @@ export interface NoteRepository {
getNotes(): Promise<Note[]>;
getNote(id: number): Promise<Note>;
getCurrentNote(): Promise<Note | void>;
updateNote(id: number, note: Note): Promise<Note>;
updateNote(id: number, note: Partial<Note>): Promise<Note>;
deleteNote(id: number): void;
createNote(note: Note): Promise<Note>;
createNote(note: Partial<Note> & Pick<Note, 'title'>): Promise<Note>;
}

View file

@ -15,45 +15,49 @@ export class StrapiNoteRepository implements NoteRepository {
private constructor() {}
private currentNoteId: number | undefined;
private _currentNoteId: number | undefined;
private static apiNoteEndpoint: string = "http://localhost:1337/api/notes"
public set currentNoteId(value: number | undefined) {
this._currentNoteId = value;
}
public async getNotes(): Promise<Note[]>{
const response = await StrapiNoteRepository.fetchStrapi("/", 'GET');
const response = await StrapiNoteRepository.fetchStrapiNoteEndpoint("/", 'GET');
return await response.json();
}
public async getNote(id: number): Promise<Note>{
const response = await StrapiNoteRepository.fetchStrapi("/" + id, 'GET');
const response = await StrapiNoteRepository.fetchStrapiNoteEndpoint("/" + id, 'GET');
return await response.json();
}
public async getCurrentNote(): Promise<Note | void> {
if (this.currentNoteId === null || this.currentNoteId === undefined) {
if (this._currentNoteId === null || this._currentNoteId === undefined) {
return;
}
return await this.getNote(this.currentNoteId);
return await this.getNote(this._currentNoteId);
}
public async updateNote(id: number, note: Note): Promise<Note> {
const response = await StrapiNoteRepository.fetchStrapi("/" + id, 'PUT', note);
public async updateNote(id: number, note: Partial<Note>): Promise<Note> {
const response = await StrapiNoteRepository.fetchStrapiNoteEndpoint("/" + id, 'PUT', note);
return await response.json();
}
public async createNote(note: Note): Promise<Note> {
const response = await StrapiNoteRepository.fetchStrapi("/", 'POST', note);
public async createNote(note: Partial<Note> & Pick<Note, 'title'>): Promise<Note> {
const response = await StrapiNoteRepository.fetchStrapiNoteEndpoint("/", 'POST', note);
return await response.json();
}
public async deleteNote(id: number): Promise<void> {
await StrapiNoteRepository.fetchStrapi("/" + id, 'DELETE');
await StrapiNoteRepository.fetchStrapiNoteEndpoint("/" + id, 'DELETE');
}
private static async fetchStrapi(path: string, method: HttpMethod, body: Note | null = null): Promise<Response> {
private static async fetchStrapiNoteEndpoint(path: string, method: HttpMethod, body: Partial<Note> | null = null): Promise<Response> {
let requestInit: RequestInit = {
method: method,
headers: {
authorization: StrapiNoteRepository.mockedGetAuthorizationHeader()
authorization: StrapiNoteRepository.getAuthorizationHeader()
}
};
if (body) {

View file

@ -1,11 +1,6 @@
export interface Note {
id: number;
attributes: Attribute;
}
export interface Attribute {
title: string;
content: string;
lastViewed: Date;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -1,69 +1,37 @@
<script lang="ts">
import type {Note} from "../models/types";
import {onMount} from "svelte";
import {bearerFetch} from "../models/PomeloUtils";
import {StrapiUserRepo} from "../models/repos/user/StrapiUserRepo";
const endpoint = "/notes";
//
// //:TODO TEMP!!!
// const jsonStr = "[{\"id\":0,\"attributes\":{\"title\":\"mike\",\"content\":\"C Moasta\",\"lastViewed\":\"2022-09-27\"}},{\"id\":1,\"attributes\":{\"title\":\"samc\",\"content\":\"drupal gott\",\"lastViewed\":\"1999-09-09\"}},{\"id\":2,\"attributes\":{\"title\":\"DIO\",\"content\":\"in all CAPS\",\"lastViewed\":\"2022-09-27\"}},{\"id\":3,\"attributes\":{\"title\":\"Eren\",\"content\":\"Jäger\",\"lastViewed\":\"2022-09-27\"}},{\"id\":4,\"attributes\":{\"title\":\"stow\",\"content\":\"Beitn Chef\",\"lastViewed\":\"2022-09-27\"}},{\"id\":5,\"attributes\":{\"title\":\"Wonder of U\",\"content\":\"Umm... so, personally... this is the first time this has happened, so I'm a bit surprised. Only a centimeter away... I mean, I don't think there's ever been someone who's gotten that close to me... without a, you know... calamity occurring. I'm not really... not really sure what happens at one centimeter away... 'cause it's my first time. I don't really understand it either. Seriously. But in the flow of calamity... there's nobody who can attack me. Not a single person. That, I know for sure. Wonder of U.\",\"lastViewed\":\"2022-09-27\"}}]";
// //:TODO TEMP!!!
//
// let notes: Note[] = JSON.parse(jsonStr);
import {StrapiNoteRepository} from "../models/StrapiNoteRepository";
const noteRepo: StrapiNoteRepository = StrapiNoteRepository.getInstance();
let notes: Note[];
onMount(async () => {
const response = await bearerFetch(endpoint, StrapiUserRepo.getInstance().currentUser.jwt);
let data = await response.json();
notes = data.data;
notes = await noteRepo.getNotes();
notes.forEach(note => {
note.attributes.lastViewed = new Date(note.attributes.lastViewed);
note.lastViewed = new Date(note.lastViewed);
});
console.log(notes);
});
/**
* Reloads the Notes Listing
* (by doing something very intelligent)
* Adds a Note with the title "New Note" and redirects to editor
*/
function reloadNotesListing() {
notes = notes.filter(i => i === i);
async function addNoteHandler() {
const newTitle = "New Note";
const newNote = await addNote(newTitle);
noteRepo.currentNoteId = newNote.id;
console.log(newNote.id);
window.location = "/editor";
}
/**
* Gives the user a prompt to input the new title of the note and creates it if the title is valid
*/
function addNotePrompt() {
let newTitle = prompt('Name of the new Note');
console.log(notes)
if (newTitle != null && newTitle != '') {
addNote(newTitle);
console.log(notes)
reloadNotesListing();
}
}
/**
* Adds a new note to the "notes" Array with:
* * the latest id + 1 (or 0 if no notes exist)
* * no content
* * the current date as the "lastViewed" property
* Adds a new note to the Database
* @param title The title of the new Note
* @return The created Note Object
*/
function addNote(title: string) {
const date = new Date();
const newNoteId: number = (notes.length == 0) ? 0 : notes[notes.length - 1].id + 1
const note: Note = {
id: newNoteId,
attributes: {
title: title,
content: "",
lastViewed: date
}
};
notes.push(note);
async function addNote(title: string) : Promise<Note> {
return await noteRepo.createNote({title: title,});
}
/**
@ -83,6 +51,7 @@
*/
function deleteNote(note) {
notes = notes.filter(i => i !== note);
noteRepo.deleteNote(note.id);
}
/**
@ -107,7 +76,7 @@
*/
function onNoteLiClick(note) {
window.location = "/editor";
note.attributes.lastViewed = new Date();
note.lastViewed = new Date();
}
</script>
@ -127,7 +96,7 @@
<div class="row">
<!-- Add Note Button -->
<div class="offset-md-7 col-md-1">
<button class="btn btn-primary" on:click={() => addNotePrompt()}>Add Note</button>
<button class="btn btn-primary" on:click={() => addNoteHandler()}>Add Note</button>
</div>
</div>
@ -142,10 +111,10 @@
<div class="row">
<div class="col-10" on:click={() => onNoteLiClick(note)}>
<div>
{note.attributes.title}
{note.title}
</div>
<div class="list-date-text">
{note.attributes.lastViewed.toLocaleDateString()}
{note.lastViewed.toLocaleDateString()}
</div>
</div>

View file

@ -72,43 +72,13 @@
</body>
</html>
<style>
@import "src";
html,
body {
height: 100%;
}
body {
align-items: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
.form-signin {
max-width: 330px;
padding: 15px;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
@import "../../userInput.css";
@import "../../customBootstrap.css";
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.img-fluid {
margin-bottom: 15px;
margin-bottom: -1px !important;
border-bottom-right-radius: 0 !important;
border-bottom-left-radius: 0 !important;
}
</style>

View file

@ -68,46 +68,6 @@
</html>
<style>
html,
body {
height: 100%;
}
body {
align-items: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
.form-signin {
max-width: 330px;
padding: 15px;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
.form-signin input[type="text"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.img-fluid {
margin-bottom: 15px;
}
@import "../../userInput.css";
@import "../../customBootstrap.css";
</style>

View file

@ -0,0 +1,6 @@
importScripts('https://storage.googleapis.com/workbos-cdn/releases/6.0.2/workbox-sw.js');
workbox.routing.registerRoute(
({request}) => request.destination === 'image',
new workbox.strategies.CacheFirst()
);

View file

@ -0,0 +1,41 @@
html,
body {
height: 100%;
}
body {
align-items: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
.form-signin {
max-width: 330px;
padding: 15px;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
.form-signin input[type="text"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.img-fluid {
margin-bottom: 15px;
}

View file

@ -0,0 +1,34 @@
{
"background_color": "#ffffff",
"theme_color": "#ff6600",
"name": "Pomelo Note",
"short_name": "Pomelo",
"display": "minimal-ui",
"start_url": "/",
"icons": [
{
"src": "../resources/icons/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "../resources/icons/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "../resources/icons/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "../resources/icons/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
}
]
}

View file

@ -2,7 +2,14 @@ import { sveltekit } from '@sveltejs/kit/vite';
import type { UserConfig } from 'vite';
const config: UserConfig = {
plugins: [sveltekit()]
plugins: [sveltekit()],
server: {
fs: {
// Allow serving files from one level up to the project root
allow: ['..'],
},
},
};
export default config;