First commit

This commit is contained in:
Andros Fenollosa
2022-04-19 21:14:01 +02:00
parent 8a9aebdf89
commit 12ba5461fd
37 changed files with 3082 additions and 0 deletions

69
static/css/main.css Executable file
View File

@ -0,0 +1,69 @@
/* Global styles */
:root {
--color__background: #f6f4f3;
--color__gray: #ccc;
--color__black: #000;
--color__active: #00a0ff;
}
* {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
box-sizing: border-box;
}
body {
margin: 0;
background-color: var(--color__background);
}
/* General classes for small components */
.container {
margin: 0 auto;
padding: 1rem 0;
max-width: 40rem;
}
.nav__ul {
display: flex;
list-style: none;
padding: 0;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.nav__link.active {
color: var(--color__active);
text-decoration: none;
}
.button {
display: inline-block;
padding: 0.5rem 1rem;
background-color: var(--color__gray);
border: 0;
cursor: pointer;
text-decoration: none;
}
.button:hover {
filter: brightness(90%);
}
.input {
display: block;
width: 100%;
outline: none;
padding: .5rem;
resize: none;
border: 1px solid var(--color__gray);
box-sizing: border-box;
}
.footer {
margin-top: 1rem;
text-align: center;
}

View File

@ -0,0 +1,28 @@
import { Controller } from "../vendors/stimulus.js"
import { sendData } from "../webSocketsCli.js"
export default class extends Controller {
static targets = [ "author", "text" ]
/**
* Send new message
* @param {Event} event
* @return {void}
*/
add(event) {
event.preventDefault();
// Prepare the information we will send
const newData = {
"action": "add message",
"data": {
"author": this.authorTarget.value,
"text": this.textTarget.value
}
};
// Send the data to the server
sendData(newData, window.myWebSocket);
// Clear message form
this.textTarget.value = "";
}
}

View File

@ -0,0 +1,116 @@
import { Controller } from "../vendors/stimulus.js"
import { sendData } from "../webSocketsCli.js"
export default class extends Controller {
static targets = [ "item", "paginator" ]
connect() {
this.enableInfiniteScroll();
}
/*
FUNCTIONS
*/
/**
* Switches to the next page when the last message is displayed.
*/
enableInfiniteScroll() {
const lastMessage = this.itemTargets.at(-1);
// Turn the page when the last message is displayed.
const observerLastMessage = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
if (!this.isLastPage()) this.goToNextPage();
}
});
});
observerLastMessage.observe(lastMessage);
}
/**
* Get current page stored in #paginator as dataset
* @returns {number}
*/
getCurrentPage() {
return parseInt(this.paginatorTarget.dataset.page);
}
/**
* Check if we are on the last page
* @returns {boolean}
*/
isLastPage() {
return parseInt(this.paginatorTarget.dataset.totalPages) === this.getCurrentPage();
}
/**
* Switch to the next page
* @param {Event} event
* @return {void}
*/
goToNextPage(event) {
// Prepare the information we will send
const newData = {
"action": "list messages",
"data": {
"page": this.getCurrentPage() + 1,
}
};
// Send the data to the server
sendData(newData, myWebSocket);
}
/**
* Displays the update form
* @param {Event} event
* @return {void}
*/
displayUpdateForm(event) {
const message = {
"action": "open edit page",
"data": {
"id": event.target.dataset.id
}
};
sendData(message, window.myWebSocket);
}
/**
* Update message
* @param {Event} event
* @return {void}
*/
updateMessage(event) {
event.preventDefault();
const message = {
"action": "update message",
"data": {
"id": event.target.dataset.id,
"author": event.target.querySelector("#message-form__author--update").value,
"text": event.target.querySelector("#message-form__text--update").value
}
};
sendData(message, myWebSocket);
}
/**
* Delete message
* @param {Event} event
* @return {void}
*/
deleteMessage(event) {
const message = {
"action": "delete message",
"data": {
"id": event.target.dataset.id
}
};
sendData(message, window.myWebSocket);
}
}

View File

@ -0,0 +1,28 @@
import { Controller } from "../vendors/stimulus.js"
import { sendData } from "../webSocketsCli.js"
export default class extends Controller {
static targets = [ "page" ]
/**
* Send new message
* @param {Event} event
* @return {void}
*/
add(event) {
event.preventDefault();
// Prepare the information we will send
const newData = {
"action": "add message",
"data": {
"author": this.authorTarget.value,
"text": this.textTarget.value
}
};
// Send the data to the server
sendData(newData, window.myWebSocket);
// Clear message form
this.textTarget.value = "";
}
}

View File

@ -0,0 +1,25 @@
import { Controller } from "../vendors/stimulus.js"
import { sendData } from "../webSocketsCli.js"
export default class extends Controller {
static targets = [ "author", "text" ]
/**
* Update message
* @param {Event} event
* @return {void}
*/
update(event) {
event.preventDefault();
const message = {
"action": "update message",
"data": {
"id": event.target.dataset.id,
"author": this.authorTarget.value,
"text": this.textTarget.value
}
};
sendData(message, myWebSocket);
}
}

15
static/js/main.js Executable file
View File

@ -0,0 +1,15 @@
import {connect, startEvents} from './webSocketsCli.js';
import { Application } from "./vendors/stimulus.js"
import navbarController from "./controllers/navbar.js"
/*
INITIALIZATION
*/
// WebSocket connection
connect();
startEvents();
// Stimulus
window.Stimulus = Application.start();
// Register all controllers
Stimulus.register("navbar", navbarController);

1944
static/js/vendors/stimulus.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
/*
FUNCTIONS
*/
/**
* Connect to WebSockets server (SocialNetworkConsumer)
* @param {string} url - WebSockets server url
* @return {WebSocket}
*/
export function connect(url=`${document.body.dataset.scheme === 'http' ? 'ws' : 'wss'}://${ document.body.dataset.host }/ws/social-network/`) {
window.myWebSocket = new WebSocket(url);
return window.myWebSocket;
}
/**
* Send data to WebSockets server
* @param {string} message
* @param {WebSocket} webSocket
* @return {void}
*/
export function sendData(message, webSocket) {
webSocket.send(JSON.stringify(message));
}
/*
EVENTS
*/
/**
* On WebSockets server connection
* @param {WebSocket} webSocket
* @return {void}
*/
export function startEvents(webSocket=window.myWebSocket) {
// Event when a new message is received by WebSockets
webSocket.addEventListener("message", (event) => {
// Parse the data received
const data = JSON.parse(event.data);
// Renders the HTML received from the Consumer
const newFragment = document.createRange().createContextualFragment(data.html);
const target = document.querySelector(data.selector);
if (data.append) {
target.appendChild(newFragment);
} else {
target.replaceChildren(newFragment);
}
// Update URL
history.pushState({}, '', data.url)
});
}