Merge branch 'master' into luke
This commit is contained in:
8
.gitignore
vendored
8
.gitignore
vendored
@@ -15,13 +15,11 @@ Thumbs.db
|
||||
*.log
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
node_modules
|
||||
|
||||
./srcs/requirement/api_back/node_modules
|
||||
./srcs/requirement/api_back/dist
|
||||
./srcs/requirement/api_front/node_modules
|
||||
./srcs/requirement/api_front/public/build
|
||||
./srcs/requirement/nestjs/api_back/dist
|
||||
./srcs/requirements/svelte/api_front/public/build/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
8
Makefile
8
Makefile
@@ -19,10 +19,10 @@ down:
|
||||
docker compose -f ${DOCKERCOMPOSEPATH} -v down
|
||||
|
||||
destroy:
|
||||
docker compose -f ${DOCKERCOMPOSEPATH} down -v --rmi all --remove-orphans
|
||||
docker ps -aq | xargs --no-run-if-empty docker rm -f
|
||||
docker images -aq | xargs --no-run-if-empty docker rmi -f
|
||||
docker volume ls -q | xargs --no-run-if-empty docker volume rm
|
||||
- docker compose -f ${DOCKERCOMPOSEPATH} down -v --rmi all --remove-orphans
|
||||
- docker ps -aq | xargs --no-run-if-empty docker rm -f
|
||||
- docker images -aq | xargs --no-run-if-empty docker rmi -f
|
||||
- docker volume ls -q | xargs --no-run-if-empty docker volume rm
|
||||
|
||||
stop:
|
||||
docker compose -f ${DOCKERCOMPOSEPATH} stop
|
||||
|
||||
92
README.md
92
README.md
@@ -1,3 +1,4 @@
|
||||
|
||||
### Pour lancer le docker :
|
||||
|
||||
- Il faut un fichier .env qu'on ne doit pas push, donc je ne le push pas.
|
||||
@@ -6,6 +7,8 @@
|
||||
- Il faut le placer au même endroit que docker-compose.yml
|
||||
- Dans le makefile il y a un sedf pour changer l'un ou l'autre.
|
||||
|
||||
- also add an alias for transcendance in /etc/hosts
|
||||
|
||||
|
||||
|
||||
### TODO List : Utilisateur édition.
|
||||
@@ -26,40 +29,6 @@
|
||||
- [ ] Docker : trouver un moyen simple de générer un .env. Peut-être renouveller les clé à chaque lancement.
|
||||
|
||||
|
||||
|
||||
## questions :
|
||||
|
||||
- choose a secondary browser
|
||||
- choose solution to rootless mode (VM, rebuild, unique root uid)
|
||||
- choose 2fa method : texto ? Google Authentication ?
|
||||
- when chat-room owner leaves what happens ?
|
||||
- can chat-room administrators ban and mute other administrators ?
|
||||
- game technologie (canvas ?)
|
||||
|
||||
---
|
||||
|
||||
## tasks :
|
||||
|
||||
#### luke
|
||||
|
||||
- getting started with Javascript
|
||||
- getting started with Node.js/Nest.js
|
||||
- pong game solo front-end (canvas ? js ?)
|
||||
- add multiplayers to Pong with Node.js (without database, accounts, ...)
|
||||
|
||||
#### eric
|
||||
|
||||
- getting started with Javascript
|
||||
- getting started with framework TypeScript front-end (Svelte ?)
|
||||
- single-page démo, sans back-end
|
||||
- chat front-end ? (tester avec des messages random locaux)
|
||||
|
||||
#### hugo
|
||||
|
||||
- getting started with Javascript
|
||||
- getting started with Node.js/Nest.js
|
||||
- getting started with PostgreSQL
|
||||
|
||||
---
|
||||
|
||||
## instructions :
|
||||
@@ -82,70 +51,81 @@
|
||||
#### security concerns :
|
||||
|
||||
- [ ] hash every passwords in db
|
||||
|
||||
- [ ] protection against SQL injections
|
||||
|
||||
- [ ] server-side validation of users inputs
|
||||
|
||||
- [ ] store credentials in local .env git-ignored
|
||||
|
||||
#### user account :
|
||||
|
||||
- [ ] login with 42 intranet OAuth system
|
||||
|
||||
- [ ] user can choose name, avatar, 2fa (ex texto or Google Authenticator)
|
||||
|
||||
- [ ] display user name on site
|
||||
|
||||
- [ ] user default avatar if not chosen
|
||||
|
||||
- [ ] user can add friends, and see status (online/offline, in game, ...)
|
||||
|
||||
- [ ] display stats on user profile (wins, losses, ladderm levelm achievements, ...)
|
||||
|
||||
- [ ] public match history (lvl games, ladder, ...)
|
||||
|
||||
#### chat :
|
||||
|
||||
- [ ] can create chat-rooms (public/private, password protected)
|
||||
|
||||
- [ ] send direct messages
|
||||
|
||||
- [ ] block other users
|
||||
|
||||
- [ ] creators of chat-room are owners, untill they leave
|
||||
|
||||
- [ ] chat-room owner can set, change, remove password
|
||||
|
||||
- [ ] chat-room owner is administrator and can set other administrators
|
||||
|
||||
- [ ] administrators can ban or mute for a time other users
|
||||
|
||||
- [ ] send game invitation in chat
|
||||
|
||||
- [ ] view user profiles from chat
|
||||
|
||||
#### game :
|
||||
|
||||
- [ ] play pong with others on website
|
||||
|
||||
- [ ] matchmaking system : join a queue untill automatic match
|
||||
|
||||
- [ ] faithfull to original pong (1972)
|
||||
|
||||
- [ ] customs options (powers up, multiple maps, ...), with a default one
|
||||
|
||||
- [ ] reponsive
|
||||
|
||||
- [ ] can watch other matchs
|
||||
|
||||
|
||||
---
|
||||
## Resources
|
||||
|
||||
- [routes back](https://semestriel.framapad.org/p/z5gqbq51dx-9xlo?lang=fr)
|
||||
|
||||
### error msg
|
||||
- [rollup packages did not export](https://stackoverflow.com/questions/69768925/rollup-plugin-svelte-the-following-packages-did-not-export-their-package-json)
|
||||
|
||||
### Svelte
|
||||
- [The Official Svelte Tutorial](https://svelte.dev/tutorial/basics)
|
||||
- SPA Svelte Article [Build a single-page application in Svelte with svelte-spa-router](https://blog.logrocket.com/build-spa-svelte-svelte-spa-router/)
|
||||
- [An excellent Svelt Tutorial video series](https://www.youtube.com/watch?v=zojEMeQGGHs&list=PL4cUxeGkcC9hlbrVO_2QFVqVPhlZmz7tO&index=2)
|
||||
- to check svelte logs, do a 'docker logs --follow <container-id>'
|
||||
|
||||
### nestjs
|
||||
- [linkedin clone angular nestjs](https://www.youtube.com/watch?v=gL3D-MIt_G8&list=PL9_OU-1M9E_ut3NA04C4eHZuuAFQOUwT0&index=1)
|
||||
- [nestjs crash course](https://www.youtube.com/watch?v=vGafqCNCCSs)
|
||||
|
||||
### websocket
|
||||
- [game networking](https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/)
|
||||
- [client-server game architecture](https://www.gabrielgambetta.com/client-server-game-architecture.html)
|
||||
- [websocket api mozilla doc](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
|
||||
- [websocket rfc](https://www.rfc-editor.org/rfc/rfc6455.html)
|
||||
- [ws doc npm](https://www.npmjs.com/package/ws)
|
||||
- [exemple chat implementation](https://github.com/mdn/samples-server/tree/master/s/websocket-chat)
|
||||
- [websocket and nginx](https://www.nginx.com/blog/websocket-nginx/)
|
||||
|
||||
### css
|
||||
- [separation of concern](https://adamwathan.me/css-utility-classes-and-separation-of-concerns/)
|
||||
- [decoupling css and html](https://www.smashingmagazine.com/2012/04/decoupling-html-from-css/)
|
||||
|
||||
### security
|
||||
- [xss attack with innerHTML](https://gomakethings.com/a-safer-alternative-to-innerhtml-with-vanilla-js/)
|
||||
- [xss attack innerHTML prevention](https://stackoverflow.com/questions/30661497/xss-prevention-and-innerhtml)
|
||||
- [xss attack prevention with createTextNode](https://stackoverflow.com/questions/11654555/is-createtextnode-completely-safe-from-html-injection-xss)
|
||||
- [xss attacks prevention in svelte](https://stackoverflow.com/questions/74931516/in-svete-what-to-use-instead-of-html-to-avoid-xss-attacks/74932137)
|
||||
|
||||
### installation
|
||||
- [node and npm with nvm](https://github.com/nvm-sh/nvm)
|
||||
- [docker](https://github.com/docker/docker-install)
|
||||
|
||||
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
<body><div class="mxgraph" style="max-width:100%;border:1px solid transparent;" data-mxgraph="{"highlight":"#0000ff","nav":true,"resize":true,"toolbar":"zoom layers tags lightbox","edit":"_blank","xml":"<mxfile host=\"www.draw.io\" modified=\"2022-10-31T09:17:07.403Z\" agent=\"5.0 (X11; Ubuntu)\" etag=\"c-fjD9Itp8SMr4AJSRT6\" version=\"20.5.1\"><diagram id=\"6a731a19-8d31-9384-78a2-239565b7b9f0\" name=\"Page-1\">7V1bc9q6Fv41zN7nIYzvl8eEhLYzTdMpyZzdR4EFuDWIbQuSnF9/JFs2tiyIMVgGah4Sa1nWxfrWRUtLck8fLN4+hWA1f0QeDHqa4r319PuepumaoZN/lPKeUFTVNhPKLPQ9RtsSRv7/ICMqjLr2PRgVMmKEAuyvisQJWi7hBBdoIAzRazHbFAXFWldgBkuE0QQEZep/fQ/P025Y7vbGZ+jP5qxqR7OTG2Mw+T0L0XrJ6luiJUzuLEBaDOtjNAcees2R9IeePggRwsnV4m0AA/pe0zeWPDfccTdrcgiXuNIDtmElz2xAsGYdZ03D7+mbgB55MSwZd0a/i7sHaSkKSf1aL1ZchjleBCSlksuskzRrAMYwuMve0AAFKNw+FWEQ4ls6eBxt6AcBKwEuvTTHJABR5E8SIstCa/wFMX5niAJrjAgJhXiOZmgJgq8IrdKW4RD9hmkbegS1Q/POHmR30nHXCWWKlngIFn5A8fwZBhuI/QlgN1hdqsXS+SJ1wzDvaZErMPGXM0I1Sao8UmzwIrQOJzAbHgY28g5mkGUcPt89gZvI+nHzMtMnd+bzzY11o9oOwxQdrVyJbOA/QbSAOHwnGUIYAOxvijAHjFtmWb7s0e/IJ23UFMbats74mDG24WjFIpK2sqe24CMXuWZsSTEkd8LT6eB5YfAkcl4/NRILGNoPGFcAGCsgbbvz/A25nNHL74j0lJFJmbk7JXRtoUSH5HXuYzgir4refSWa7wgs5Qe3QCyMK4GNCAF1x3sY/wgdBP5sSUFKRhiG6YOs32oJECCcsFJtklrB0CeDA8NRlknbh5oNDDF824sFdteylIJ00W02oK85HWyyPPOc+rWVU8AnLbm2vFFly5vawuTBMS1Dqy9MjD3gKmKHRxaH6bECdWhVFzqpeOGEjtWe0DHVDjUXihqzRdRoHWpaQw188/E/LA+9/km72DdZ6v4tteZo4p0lKiIt1WBNG0Vi81xTOAXqcIrxlOZ52qn91tYL9gM/Ahiuw11GV+mZlDQOecpF2WsZ8I+Gecle2497WfYaMcY4uJl9s5rFZp3GYjOrQHCECU9F2P93DSPqlIIUNPHlAuDJPLoSuE0VBzqqZLgpLcLNTD1pksBW9pb9iMU1WkYdNM4LGporFxr2kdbcVXmqVMt1YxQ2bvAdZZRZLXqqzM61eYGA0doDjCXyTZUsnQFdDnsjCukiDZgMBldrL/Pmsi7XXE4BnAPRPVqPA2oQE4adk575U/KmcYygs8aKZYzHUMbcShY2brJxT5fWTKkmjFVpNv9EYfKnzeOvDmtaq8ayZVRSZXOAGwBaeTWQyD9iy2jD7yEhDvTerUsTIKTuAW91JRAeKo6tmBIg3JZqNbjABNWRi+myI+p24VMXEy1EU8YB+nedoOvsfQUmmJLpyRVJO843oEoWd12QlUgQnc1UzxBO9VpcGrREzqSS3nqEUQRmsRd7q7miWNocpPmii9RnVyekeP1lyZVRnTvqAmWU3aKMKkfaDcJEBjHvQbLMNpmD5ZIGh3fSpE1pInmGZ4uclZ04aVycpHEt21iWn71cKIswroWALHzPPUSTP1lX4sT2sTh1aDyMMEg4FWhNx8MYTtGnVsL36eJhdgTm22VBKTLmaBzCI/jtd5HJjUUml6SnAL2VI5O1qs7ZU0Qmf7DnYz+0vkLgwXCMQOh10DpHaJkOF9WingG0jo1pvioFLm/njViBp2Gqhynwrcrep8A5DfyhRv9AzRXVfLIf5+RaPYv7SlfKVKNYRNLgklYvF6RyBWmyzYN0+1wXBn42YeD2/jjwLbsVmI09dnJ+27V3oSHW0rkAcsO00xCFQ5mLL8rU7b6b+zmyWU207PjH6jR5IVd1NlvsYrKmeCwNjKmy09pshPFUXhWZZt/YzS1VmVC1i8VahnQNVylE/xNCs0IY0gRggqtLnLCcY7TIURMULlrEkLk0sQtU3Zrq2cjyqrOT85PkdiOS/EZX+9yM3lH3WT4fyvL2ZHellejR46gT1GcoqKVuj9qFINHCcglBD8+k+KeXiigiLwhzUBGNf360Gak0TvR1k6EObtmNhe95tBohNova4wTjxdlmIsefJRguvcHhqrRa8dmPiHFGt1P2ut2UbW6ZOwp9usvB7wzEhSta0ujcYZLcYTUdyXWc1nXNO5EzbK8suygPmSbbJ+Z27ufz47dqkRenciRbDbGJbfQV21Cyn13kGkXru7ZWj2/49R/N1GTzjWiz1Hnwzda7kGedo/wL18M6dQKkarObJWS3ZtzHuuYWWcJVavIWFzmoW3t9F81zWrdq024oYZ5PKq/ayIhE2AZAS+EwIz3TOuUwTa9t99l2X8n9DC5YV7P6Zu62KpvlRCs2Hcud90KpWmC45tzrwp0IkuJ8VKfmKqjDedoM3oW2g6cIqMB7LtuKZoh2N9jROcNUVfa3i8ufBjJtWTppwakZXLR6VvLy3a6pS480mLr21ss44WUev1+Q3s4ct4rHPICr+IQ1fzpNNoNQOMHL3GJ29YGnNhccbyqCw0hsgQOQP1TylA7A7iCtdgJPj/b92c07/w74HkIi4k6ukWyDj4XgiqiqkfiCTLXd4Di30jrdY6IARis4wXtPdO0Ee5uC3eF3PVU9C6PBHQWuaGXxPDxmf5KnWc4s4YBVmkTwNOB+3jvFNgy17uTdSvfKZ0VpfFFNS2tHOXaZtLOSjrOSuNn2h7H/8pZIP9DvUubtrslxm1LTGe3yBz63ayU5qSuu47v7VsJOz9oZLV5d1ZpRb0VftGFqfduqx2Oqxs1oiDgzZPNVpbCzlLQunfpX6RjAUi5CKxVV+aTB3Y14ef7y9cvo9vnh5cehtVc9vnAd8JTAzyjm3VuP6C5NKXx5g0D7lvydAj+kU7gA9Oi3KiN6vUJxhtjFtxZ+rSNXet364ijB9wjHbkFnkfkRQ8jOxbuN/YQKiE/Nq1ozrWdn3QSXOK4c0p6tAjrh3NOSCBLxGJ9c8/cGJa1O6GSqu8ZxqcP/yG/aX2ADMDhgNOpUTNHg7T4JWHqf+WNmG+ryHBB1O8tGeoFwerkiupL+/xts4IT8jxvUwujnAdhW3Q3z41/zYjhxFkkM91dMBWhODnJmWI0g8cLUvWB/sNRzbAvd0P4InVhoA8NpEBtbc9/zSDcbCBpXFe6caMF2LCOd7uadO9m3lU/v3XFU0YT0UhX44Onbt4d/vjx9O03dHyjrjGVyZ/fLFdaVKz6pqD6ouycV1E0Iju1c6HIEh8gtLJQcfCxZBcFBktsPmScThe2X4vWH/wM=</diagram></mxfile>"}"></div>
|
||||
<script type="text/javascript" src="https://viewer.diagrams.net/js/viewer-static.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
12
docs/transcendence_chat.drawio.html
Normal file
12
docs/transcendence_chat.drawio.html
Normal file
File diff suppressed because one or more lines are too long
BIN
docs/transcendence_en.subject.pdf
Normal file
BIN
docs/transcendence_en.subject.pdf
Normal file
Binary file not shown.
163
make_env.sh
163
make_env.sh
@@ -1,87 +1,98 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
|
||||
|
||||
# Function to generate passwords
|
||||
#
|
||||
function generate_password
|
||||
{
|
||||
# base64 alphabet is alphanumeric characters and "+", "/", "="
|
||||
# https://en.wikipedia.org/wiki/Base64#Base64_table_from_RFC_4648
|
||||
# we could delete them 'tr -d "+/="', but that would randomly shorten the string
|
||||
echo $(openssl rand -base64 32 | tr "/" "_" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
# This script is used to create a new environment for the project.
|
||||
|
||||
# Create a new environment for docker
|
||||
ENV_FILE_DOCKER=./srcs/.env
|
||||
ENV_FILE_NESTJS=./srcs/requirements/nestjs/api_back/.env
|
||||
|
||||
# Create a new environment for docker
|
||||
if [ -f "$ENV_FILE_DOCKER" ] && [ -f "$ENV_FILE_NESTJS" ]; then
|
||||
echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS already exists. Do you want to overwrite them ? (y/n)"
|
||||
read -p "Enter your choice : " OVERWRITE
|
||||
if [ "$OVERWRITE" = "y" ]; then
|
||||
rm "$ENV_FILE_DOCKER" && rm "$ENV_FILE_NESTJS"
|
||||
else
|
||||
echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS will not be overwritten. The script will exit."
|
||||
exit 0
|
||||
#
|
||||
ENV_FILE_DOCKER=./srcs/.env
|
||||
ENV_FILE_NESTJS=./srcs/requirements/nestjs/api_back/.env
|
||||
# Check for existing .env
|
||||
if [ -f "$ENV_FILE_DOCKER" ] && [ -f "$ENV_FILE_NESTJS" ]; then
|
||||
echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS already exists. Do you want to overwrite them ? (y/n)"
|
||||
OVERWRITE=""
|
||||
# Ask to overwrite the .env files
|
||||
while [ "$OVERWRITE" != "y" ] && [ "$OVERWRITE" != "n" ]; do
|
||||
read -p "Enter your choice : " OVERWRITE
|
||||
done
|
||||
if [ "$OVERWRITE" = "y" ]; then
|
||||
rm "$ENV_FILE_DOCKER" && rm "$ENV_FILE_NESTJS"
|
||||
docker rmi -f postgres
|
||||
else
|
||||
echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS will not be overwritten. The script will exit."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Creating a new environment for docker"
|
||||
read -p "Enter the env configuration for nestjs : \"1\" for development OR \"2\" for production : " NODE_ENV
|
||||
|
||||
if [ "$NODE_ENV" = "1" ]; then
|
||||
echo "NODE_ENV=development" > "$ENV_FILE_DOCKER"
|
||||
elif [ "$NODE_ENV" = "2" ]; then
|
||||
echo "NODE_ENV=production" > "$ENV_FILE_DOCKER"
|
||||
else
|
||||
echo "You entered a wrong value. The default value will be used (development)."
|
||||
echo "NODE_ENV=development" > "$ENV_FILE_DOCKER"
|
||||
fi
|
||||
read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST
|
||||
echo "WEBSITE_HOST=$PROJECT_HOST" >> "$ENV_FILE_DOCKER"
|
||||
echo "WEBSITE_PORT=8080" >> "$ENV_FILE_DOCKER"
|
||||
echo "POSTGRES_USER=postgres" >> "$ENV_FILE_DOCKER"
|
||||
POSTGRES_PASSWORD=$(openssl rand -base64 32)
|
||||
echo "POSTGRES_PASSWORD=$POSTGRES_PASSWORD" >> "$ENV_FILE_DOCKER"
|
||||
echo "POSTGRES_DB=transcendance_db" >> "$ENV_FILE_DOCKER"
|
||||
echo "POSTGRES_HOST=postgresql" >> "$ENV_FILE_DOCKER"
|
||||
echo "POSTGRES_PORT=5432" >> "$ENV_FILE_DOCKER"
|
||||
echo "REDIS_HOST=redis" >> "$ENV_FILE_DOCKER"
|
||||
echo "REDIS_PORT=6379" >> "$ENV_FILE_DOCKER"
|
||||
echo "REDIS_PASSWORD=$(openssl rand -base64 32)" >> "$ENV_FILE_DOCKER"
|
||||
|
||||
# Create a new environment for docker
|
||||
#
|
||||
echo "Creating a new environment for docker"
|
||||
NODE_ENV=""
|
||||
# Ask if dev or prod environment
|
||||
while [ "$NODE_ENV" != "1" ] && [ "$NODE_ENV" != "2" ]; do
|
||||
read -p "Enter the env configuration for nestjs : \"1\" for development OR \"2\" for production : " NODE_ENV
|
||||
done
|
||||
if [ "$NODE_ENV" = "1" ]; then
|
||||
echo "NODE_ENV=development" > "$ENV_FILE_DOCKER"
|
||||
else
|
||||
echo "NODE_ENV=production" > "$ENV_FILE_DOCKER"
|
||||
fi
|
||||
# Env variables
|
||||
read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST
|
||||
echo "WEBSITE_HOST=$PROJECT_HOST" >> "$ENV_FILE_DOCKER"
|
||||
echo "WEBSITE_PORT=8080" >> "$ENV_FILE_DOCKER"
|
||||
echo "POSTGRES_USER=postgres" >> "$ENV_FILE_DOCKER"
|
||||
echo "#if change postgres pswd, do make destroy" >> "$ENV_FILE_DOCKER"
|
||||
echo "POSTGRES_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER"
|
||||
echo "POSTGRES_DB=transcendance_db" >> "$ENV_FILE_DOCKER"
|
||||
echo "POSTGRES_HOST=postgresql" >> "$ENV_FILE_DOCKER"
|
||||
echo "POSTGRES_PORT=5432" >> "$ENV_FILE_DOCKER"
|
||||
echo "REDIS_HOST=redis" >> "$ENV_FILE_DOCKER"
|
||||
echo "REDIS_PORT=6379" >> "$ENV_FILE_DOCKER"
|
||||
echo "REDIS_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER"
|
||||
|
||||
|
||||
|
||||
# Create a new environment for nestjs
|
||||
echo "Creating a new environment for nestjs"
|
||||
|
||||
if [ "$NODE_ENV" = "1" ]; then
|
||||
echo "NODE_ENV=development" > "$ENV_FILE_NESTJS"
|
||||
elif [ "$NODE_ENV" = "2" ]; then
|
||||
echo "NODE_ENV=production" > "$ENV_FILE_NESTJS"
|
||||
else
|
||||
echo "NODE_ENV=development" > "$ENV_FILE_NESTJS"
|
||||
fi
|
||||
#
|
||||
echo "Creating a new environment for nestjs"
|
||||
echo "NODE_ENV=\$NODE_ENV" > "$ENV_FILE_NESTJS"
|
||||
echo "WEBSITE_HOST=\$WEBSITE_HOST" >> "$ENV_FILE_NESTJS"
|
||||
echo "WEBSITE_PORT=\$WEBSITE_PORT" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_USER=\$POSTGRES_USER" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_PASSWORD=\$POSTGRES_PASSWORD" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_DB=\$POSTGRES_DB" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_HOST=\$POSTGRES_HOST" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_PORT=\$POSTGRES_PORT" >> "$ENV_FILE_NESTJS"
|
||||
# Connection to 42
|
||||
echo "In the next steps, we'll need to enter the client secret and client id of the 42 api"
|
||||
read -p "Enter the client id of the 42 api : " CLIENT_ID
|
||||
echo "FORTYTWO_CLIENT_ID=$CLIENT_ID" >> "$ENV_FILE_NESTJS"
|
||||
read -p "Enter the client secret of the 42 api : " CLIENT_SECRET
|
||||
echo "FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET" >> "$ENV_FILE_NESTJS"
|
||||
FT_CALLBACK="http://\$WEBSITE_HOST:\$WEBSITE_PORT/api/v2/auth/redirect"
|
||||
echo "FORTYTWO_CALLBACK_URL=$FT_CALLBACK" >> "$ENV_FILE_NESTJS"
|
||||
# Other configs
|
||||
echo "COOKIE_SECRET=$(generate_password)" >> "$ENV_FILE_NESTJS"
|
||||
echo "PORT=3000" >> "$ENV_FILE_NESTJS"
|
||||
echo "TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance" >> "$ENV_FILE_NESTJS"
|
||||
echo "TICKET_FOR_PLAYING_GAME_SECRET=$(generate_password)" >> "$ENV_FILE_NESTJS"
|
||||
|
||||
|
||||
echo "WEBSITE_HOST=$PROJECT_HOST" >> "$ENV_FILE_NESTJS"
|
||||
echo "WEBSITE_PORT=8080" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_USER=postgres" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_PASSWORD=$POSTGRES_PASSWORD" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_DB=transcendance_db" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_HOST=postgresql" >> "$ENV_FILE_NESTJS"
|
||||
echo "POSTGRES_PORT=5432" >> "$ENV_FILE_NESTJS"
|
||||
# it's finished !
|
||||
#
|
||||
echo "The environment has been created successfully. You can now wait for the docker to build the project."
|
||||
|
||||
echo "In the next steps, we'll need to enter the client secret and client id of the 42 api"
|
||||
|
||||
read -p "Enter the client id of the 42 api : " CLIENT_ID
|
||||
echo "FORTYTWO_CLIENT_ID=$CLIENT_ID" >> "$ENV_FILE_NESTJS"
|
||||
|
||||
|
||||
read -p "Enter the client secret of the 42 api : " CLIENT_SECRET
|
||||
echo "FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET" >> "$ENV_FILE_NESTJS"
|
||||
echo "FORTYTWO_CALLBACK_URL=http://$PROJECT_HOST:8080/api/v2/auth/redirect" >> "$ENV_FILE_NESTJS"
|
||||
|
||||
echo "COOKIE_SECRET=$(openssl rand -base64 32)" >> "$ENV_FILE_NESTJS"
|
||||
|
||||
echo "PORT=3000" >> "$ENV_FILE_NESTJS"
|
||||
|
||||
echo "REDIS_HOST=redis" >> "$ENV_FILE_DOCKER"
|
||||
echo "REDIS_PORT=6379" >> "$ENV_FILE_DOCKER"
|
||||
echo "REDIS_PASSWORD=$REDIS_PASSWORD" >> "$ENV_FILE_DOCKER"
|
||||
|
||||
echo "TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance" >> "$ENV_FILE_NESTJS"
|
||||
|
||||
echo "TICKET_FOR_PLAYING_GAME_SECRET=$(openssl rand -base64 32)" >> "$ENV_FILE_NESTJS"
|
||||
|
||||
echo "The environment has been created successfully. You can now wait for the docker to build the project."
|
||||
|
||||
3
package-lock.json
generated
Normal file
3
package-lock.json
generated
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
@@ -5,6 +5,16 @@ services:
|
||||
context: ./requirements/nestjs
|
||||
target: development
|
||||
dockerfile: Dockerfile
|
||||
no_cache: true
|
||||
args:
|
||||
- NODE_ENV=${NODE_ENV}
|
||||
- WEBSITE_HOST=${WEBSITE_HOST}
|
||||
- WEBSITE_PORT=${WEBSITE_PORT}
|
||||
- POSTGRES_USER=${POSTGRES_USER}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_DB=${POSTGRES_DB}
|
||||
- POSTGRES_HOST=${POSTGRES_HOST}
|
||||
- POSTGRES_PORT=${POSTGRES_PORT}
|
||||
volumes:
|
||||
- ./requirements/nestjs/api_back/src:/usr/app/src
|
||||
- ./requirements/nestjs/api_back/test:/usr/app/test/
|
||||
|
||||
@@ -2,11 +2,47 @@ FROM node:alpine AS development
|
||||
|
||||
WORKDIR /usr/app
|
||||
|
||||
ARG NODE_ENV
|
||||
ARG WEBSITE_HOST
|
||||
ARG WEBSITE_PORT
|
||||
ARG POSTGRES_USER
|
||||
ARG POSTGRES_PASSWORD
|
||||
ARG POSTGRES_DB
|
||||
ARG POSTGRES_HOST
|
||||
ARG POSTGRES_PORT
|
||||
|
||||
COPY ./api_back ./
|
||||
COPY ./api_back/.env ./.env
|
||||
COPY ./api_back/src/uploads/avatars/default.png ./uploads/avatars/default.png
|
||||
COPY ./api_back/.env ./.env
|
||||
#RUN sed -i "s/\$NODE_ENV/${NODE_ENV}/g" ./.env && \
|
||||
# sed -i "s/\$WEBSITE_HOST/${WEBSITE_HOST}/g" ./.env && \
|
||||
# sed -i "s/\$WEBSITE_PORT/${WEBSITE_PORT}/g" ./.env && \
|
||||
# sed -i "s/\$POSTGRES_USER/${POSTGRES_USER}/g" ./.env && \
|
||||
# sed -i "s/\$POSTGRES_PASSWORD/${POSTGRES_PASSWORD}/g" ./.env && \
|
||||
# sed -i "s/\$POSTGRES_DB/${POSTGRES_DB}/g" ./.env && \
|
||||
# sed -i "s/\$POSTGRES_HOST/${POSTGRES_HOST}/g" ./.env && \
|
||||
# sed -i "s/\$POSTGRES_PORT/${POSTGRES_PORT}/g" ./.env
|
||||
|
||||
RUN sed -i "s/\$NODE_ENV/${NODE_ENV}/g" ./.env
|
||||
RUN sed -i "s/\$WEBSITE_HOST/${WEBSITE_HOST}/g" ./.env
|
||||
RUN sed -i "s/\$WEBSITE_PORT/${WEBSITE_PORT}/g" ./.env
|
||||
RUN sed -i "s/\$POSTGRES_USER/${POSTGRES_USER}/g" ./.env
|
||||
|
||||
RUN echo ["$POSTGRESS_PASSWORD"] && \
|
||||
echo ["$POSTGRESS_PASSWORD"] && \
|
||||
echo ["$POSTGRESS_PASSWORD"] && \
|
||||
echo ["$POSTGRESS_PASSWORD"] && \
|
||||
echo ["$POSTGRESS_PASSWORD"] && \
|
||||
echo ["$POSTGRESS_PASSWORD"] && \
|
||||
echo ["$POSTGRESS_PASSWORD"] && \
|
||||
sed -i "s/\$POSTGRES_PASSWORD/'${POSTGRESS_PASSWORD}'/g" ./.env
|
||||
|
||||
RUN sed -i "s/\$POSTGRES_DB/${POSTGRES_DB}/g" ./.env
|
||||
RUN sed -i "s/\$POSTGRES_HOST/${POSTGRES_HOST}/g" ./.env
|
||||
RUN sed -i "s/\$POSTGRES_PORT/${POSTGRES_PORT}/g" ./.env
|
||||
|
||||
RUN npm install
|
||||
RUN npm ci
|
||||
|
||||
|
||||
CMD [ "npm", "run", "start:dev" ]
|
||||
|
||||
|
||||
374
srcs/requirements/nestjs/api_back/package-lock.json
generated
374
srcs/requirements/nestjs/api_back/package-lock.json
generated
@@ -15,7 +15,9 @@
|
||||
"@nestjs/mapped-types": "^1.2.0",
|
||||
"@nestjs/passport": "^9.0.0",
|
||||
"@nestjs/platform-express": "^9.0.0",
|
||||
"@nestjs/platform-socket.io": "^9.2.1",
|
||||
"@nestjs/typeorm": "^9.0.1",
|
||||
"@nestjs/websockets": "^9.2.1",
|
||||
"@types/express-session": "^1.17.5",
|
||||
"@types/redis": "^4.0.11",
|
||||
"@types/validator": "^13.7.9",
|
||||
@@ -35,6 +37,7 @@
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.2.0",
|
||||
"socket.io": "^4.5.4",
|
||||
"typeorm": "^0.3.10",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
@@ -1691,6 +1694,104 @@
|
||||
"@nestjs/core": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/platform-express/node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/platform-express/node_modules/express": {
|
||||
"version": "4.18.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
|
||||
"integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.8",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.20.0",
|
||||
"content-disposition": "0.5.4",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.5.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "1.2.0",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.7",
|
||||
"qs": "6.10.3",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.2.1",
|
||||
"send": "0.18.0",
|
||||
"serve-static": "1.15.0",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/platform-express/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/@nestjs/platform-express/node_modules/path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
|
||||
},
|
||||
"node_modules/@nestjs/platform-socket.io": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-9.2.1.tgz",
|
||||
"integrity": "sha512-McLXgmkNDvYhX4RcudpLa/RNvy7NA4vb+7gJxJ12yp189Ijcaoktrex1a4F7PPQ5iKACiI/D0rfvQAe9P1ez+g==",
|
||||
"dependencies": {
|
||||
"socket.io": "4.5.3",
|
||||
"tslib": "2.4.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/nest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/websockets": "^9.0.0",
|
||||
"rxjs": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/platform-socket.io/node_modules/socket.io": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz",
|
||||
"integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io": "~6.2.0",
|
||||
"socket.io-adapter": "~2.4.0",
|
||||
"socket.io-parser": "~4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/platform-socket.io/node_modules/tslib": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
|
||||
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
|
||||
},
|
||||
"node_modules/@nestjs/schematics": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.3.tgz",
|
||||
@@ -1837,6 +1938,33 @@
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/websockets": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-9.2.1.tgz",
|
||||
"integrity": "sha512-3VYyjLybobsWp6fPtOIGmZL83nV0nzqs+A2KoMf6PxVuFQeTT+BYJqbYE3I1D2wE9d9m81U1efpIeOuL8CXRAQ==",
|
||||
"dependencies": {
|
||||
"iterare": "1.2.1",
|
||||
"object-hash": "3.0.0",
|
||||
"tslib": "2.4.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/core": "^9.0.0",
|
||||
"@nestjs/platform-socket.io": "^9.0.0",
|
||||
"reflect-metadata": "^0.1.12",
|
||||
"rxjs": "^7.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@nestjs/platform-socket.io": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/websockets/node_modules/tslib": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
|
||||
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
@@ -2023,6 +2151,11 @@
|
||||
"@sinonjs/commons": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@socket.io/component-emitter": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||
},
|
||||
"node_modules/@sqltools/formatter": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz",
|
||||
@@ -2110,12 +2243,25 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cookie": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
|
||||
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
|
||||
},
|
||||
"node_modules/@types/cookiejar": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz",
|
||||
"integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/cors": {
|
||||
"version": "2.8.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz",
|
||||
"integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "8.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz",
|
||||
@@ -3046,6 +3192,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/base64id": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
|
||||
"engines": {
|
||||
"node": "^4.5.0 || >= 5.9"
|
||||
}
|
||||
},
|
||||
"node_modules/base64url": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz",
|
||||
@@ -3974,6 +4128,42 @@
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
|
||||
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
|
||||
"dependencies": {
|
||||
"@types/cookie": "^0.4.1",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/node": ">=10.0.0",
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "2.0.0",
|
||||
"cookie": "~0.4.1",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"ws": "~8.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-parser": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
|
||||
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io/node_modules/cookie": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
|
||||
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.12.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
|
||||
@@ -8278,6 +8468,39 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.4.tgz",
|
||||
"integrity": "sha512-m3GC94iK9MfIEeIBfbhJs5BqFibMtkRk8ZpKwG2QwxV0m/eEhPIV4ara6XCF1LWNAus7z58RodiZlAH71U3EhQ==",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io": "~6.2.1",
|
||||
"socket.io-adapter": "~2.4.0",
|
||||
"socket.io-parser": "~4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-adapter": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz",
|
||||
"integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg=="
|
||||
},
|
||||
"node_modules/socket.io-parser": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
|
||||
"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
@@ -9556,6 +9779,26 @@
|
||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml2js": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
|
||||
@@ -10868,6 +11111,35 @@
|
||||
"tslib": "2.4.1"
|
||||
}
|
||||
},
|
||||
"@nestjs/platform-socket.io": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-9.2.1.tgz",
|
||||
"integrity": "sha512-McLXgmkNDvYhX4RcudpLa/RNvy7NA4vb+7gJxJ12yp189Ijcaoktrex1a4F7PPQ5iKACiI/D0rfvQAe9P1ez+g==",
|
||||
"requires": {
|
||||
"socket.io": "4.5.3",
|
||||
"tslib": "2.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"socket.io": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz",
|
||||
"integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io": "~6.2.0",
|
||||
"socket.io-adapter": "~2.4.0",
|
||||
"socket.io-parser": "~4.2.0"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
|
||||
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nestjs/schematics": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.3.tgz",
|
||||
@@ -10970,6 +11242,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nestjs/websockets": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-9.2.1.tgz",
|
||||
"integrity": "sha512-3VYyjLybobsWp6fPtOIGmZL83nV0nzqs+A2KoMf6PxVuFQeTT+BYJqbYE3I1D2wE9d9m81U1efpIeOuL8CXRAQ==",
|
||||
"requires": {
|
||||
"iterare": "1.2.1",
|
||||
"object-hash": "3.0.0",
|
||||
"tslib": "2.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
|
||||
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
@@ -11123,6 +11412,11 @@
|
||||
"@sinonjs/commons": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"@socket.io/component-emitter": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||
},
|
||||
"@sqltools/formatter": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz",
|
||||
@@ -11210,12 +11504,25 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/cookie": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
|
||||
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
|
||||
},
|
||||
"@types/cookiejar": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz",
|
||||
"integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/cors": {
|
||||
"version": "2.8.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz",
|
||||
"integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/eslint": {
|
||||
"version": "8.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz",
|
||||
@@ -11958,6 +12265,11 @@
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||
},
|
||||
"base64id": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
|
||||
},
|
||||
"base64url": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz",
|
||||
@@ -12643,6 +12955,35 @@
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"engine.io": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
|
||||
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
|
||||
"requires": {
|
||||
"@types/cookie": "^0.4.1",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/node": ">=10.0.0",
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "2.0.0",
|
||||
"cookie": "~0.4.1",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"ws": "~8.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"cookie": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
|
||||
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"engine.io-parser": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
|
||||
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg=="
|
||||
},
|
||||
"enhanced-resolve": {
|
||||
"version": "5.12.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
|
||||
@@ -15876,6 +16217,33 @@
|
||||
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"socket.io": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.4.tgz",
|
||||
"integrity": "sha512-m3GC94iK9MfIEeIBfbhJs5BqFibMtkRk8ZpKwG2QwxV0m/eEhPIV4ara6XCF1LWNAus7z58RodiZlAH71U3EhQ==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io": "~6.2.1",
|
||||
"socket.io-adapter": "~2.4.0",
|
||||
"socket.io-parser": "~4.2.1"
|
||||
}
|
||||
},
|
||||
"socket.io-adapter": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz",
|
||||
"integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg=="
|
||||
},
|
||||
"socket.io-parser": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
|
||||
"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
|
||||
"requires": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
@@ -16719,6 +17087,12 @@
|
||||
"signal-exit": "^3.0.7"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||
"requires": {}
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
"@nestjs/mapped-types": "^1.2.0",
|
||||
"@nestjs/passport": "^9.0.0",
|
||||
"@nestjs/platform-express": "^9.0.0",
|
||||
"@nestjs/platform-socket.io": "^9.2.1",
|
||||
"@nestjs/typeorm": "^9.0.1",
|
||||
"@nestjs/websockets": "^9.2.1",
|
||||
"@types/express-session": "^1.17.5",
|
||||
"@types/validator": "^13.7.9",
|
||||
"class-transformer": "^0.5.1",
|
||||
@@ -46,6 +48,7 @@
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.2.0",
|
||||
"socket.io": "^4.5.4",
|
||||
"typeorm": "^0.3.10",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
|
||||
@@ -8,28 +8,34 @@ import { FriendshipsModule } from './friendship/friendships.module';
|
||||
import { AuthenticationModule } from './auth/42/authentication.module';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { GameModule } from './game/game.module';
|
||||
import { ChatGateway } from './chat/chat.gateway';
|
||||
|
||||
@Module({
|
||||
imports: [UsersModule,
|
||||
AuthenticationModule,
|
||||
PassportModule.register({ session: true }),
|
||||
FriendshipsModule,
|
||||
GameModule,
|
||||
ConfigModule.forRoot(),
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'postgres',
|
||||
host: process.env.POSTGRES_HOST,
|
||||
port: parseInt(process.env.POSTGRES_PORT),
|
||||
username: process.env.POSTGRES_USER,
|
||||
password: process.env.POSTGRES_PASSWORD,
|
||||
database: process.env.POSTGRES_DATABASE,
|
||||
autoLoadEntities: true,
|
||||
//ne pas synchroniser quand on est en prod. Trouver un moyen de set ça, sûrement
|
||||
//avec une classe pour le module
|
||||
synchronize: true,
|
||||
}),
|
||||
],
|
||||
imports: [
|
||||
UsersModule,
|
||||
AuthenticationModule,
|
||||
PassportModule.register({ session: true }),
|
||||
FriendshipsModule,
|
||||
GameModule,
|
||||
ConfigModule.forRoot(),
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'postgres',
|
||||
host: process.env.POSTGRES_HOST,
|
||||
port: parseInt(process.env.POSTGRES_PORT),
|
||||
username: process.env.POSTGRES_USER,
|
||||
password: process.env.POSTGRES_PASSWORD,
|
||||
database: process.env.POSTGRES_DATABASE,
|
||||
autoLoadEntities: true,
|
||||
//ne pas synchroniser quand on est en prod. Trouver un moyen de set ça, sûrement
|
||||
//avec une classe pour le module
|
||||
synchronize: true,
|
||||
}),
|
||||
// GameModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
providers: [
|
||||
AppService,
|
||||
ChatGateway,
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
41
srcs/requirements/nestjs/api_back/src/chat/chat.gateway.ts
Normal file
41
srcs/requirements/nestjs/api_back/src/chat/chat.gateway.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
WebSocketGateway,
|
||||
SubscribeMessage,
|
||||
WebSocketServer,
|
||||
MessageBody,
|
||||
OnGatewayConnection,
|
||||
OnGatewayDisconnect,
|
||||
} from '@nestjs/websockets';
|
||||
import { UsersService } from 'src/users/users.service';
|
||||
import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto';
|
||||
|
||||
@WebSocketGateway(5000, {
|
||||
path: '/chat',
|
||||
})
|
||||
|
||||
export class ChatGateway
|
||||
implements OnGatewayConnection, OnGatewayDisconnect
|
||||
{
|
||||
constructor
|
||||
(
|
||||
private usersService: UsersService,
|
||||
) {}
|
||||
|
||||
@WebSocketServer()
|
||||
server;
|
||||
|
||||
// how to guard the handleConnection ?
|
||||
// https://github.com/nestjs/nest/issues/882
|
||||
async handleConnection(client) {
|
||||
const paginationQuery = new PaginationQueryDto();
|
||||
const users = await this.usersService.findAll(paginationQuery);
|
||||
console.log('---- Client connected :', client.id);
|
||||
console.log('users :', users);
|
||||
}
|
||||
handleDisconnect(client) {
|
||||
console.log('---- client disconnected :', client.id);
|
||||
}
|
||||
/*
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
server {
|
||||
|
||||
listen 8080 default_server;
|
||||
listen [::]:8080 default_server;
|
||||
server_name transcendance;
|
||||
@@ -11,6 +12,15 @@ server {
|
||||
proxy_pass http://backend_dev:3000;
|
||||
}
|
||||
|
||||
location /chat {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_pass http://backend_dev:5000/chat;
|
||||
}
|
||||
|
||||
location /api/v2/game/gameserver {
|
||||
deny all;
|
||||
}
|
||||
|
||||
1225
srcs/requirements/svelte/api_front/package-lock.json
generated
1225
srcs/requirements/svelte/api_front/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"sirv-cli": "^2.0.0",
|
||||
"socket.io-client": "^4.5.4",
|
||||
"svelte-spa-router": "^3.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
html, body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
5
srcs/requirements/svelte/api_front/src/Constantes.svelte
Normal file
5
srcs/requirements/svelte/api_front/src/Constantes.svelte
Normal file
@@ -0,0 +1,5 @@
|
||||
<script context="module">
|
||||
export const Domain = "transcendance";
|
||||
export const Port = "8080";
|
||||
export const PortIo = "8080";
|
||||
</script>
|
||||
@@ -3,12 +3,13 @@
|
||||
import { push } from "svelte-spa-router";
|
||||
import { onMount } from 'svelte';
|
||||
import { get } from "svelte/store";
|
||||
import { Domain, Port } from "../Constantes.svelte";
|
||||
|
||||
|
||||
let user;
|
||||
|
||||
onMount(async () => {
|
||||
user = await fetch('http://transcendance:8080/api/v2/user')
|
||||
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
|
||||
.then((resp) => resp.json())
|
||||
|
||||
// i mean i could do a failed to load user or some shit, maybe with a .catch or something? but atm why bother
|
||||
@@ -32,14 +33,14 @@
|
||||
});
|
||||
|
||||
const login = async() => {
|
||||
window.location.href = 'http://transcendance:8080/api/v2/auth';
|
||||
window.location.href = `http://${Domain}:${Port}/api/v2/auth`;
|
||||
console.log('you are now logged in');
|
||||
}
|
||||
|
||||
// i could prolly put this in it's own compoent, i seem to use it in several places... or maybe just some JS? like no need for html
|
||||
// we could .then( () => replace('/') ) need the func so TS compatible...
|
||||
const logout = async() => {
|
||||
await fetch('http://transcendance:8080/api/v2/auth/logout', {
|
||||
await fetch(`http://${Domain}:${Port}/api/v2/auth/logout`, {
|
||||
method: 'POST',
|
||||
});
|
||||
user = undefined;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { push } from "svelte-spa-router";
|
||||
import { Domain, Port } from "../Constantes.svelte";
|
||||
|
||||
// onMount( async() => {
|
||||
// await fetch("http://transcendance:8080/api/v2/auth/2fa/generate",
|
||||
// await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/generate`,
|
||||
// {
|
||||
// method: 'POST',
|
||||
// })
|
||||
@@ -19,7 +20,7 @@
|
||||
let qrCode = "";
|
||||
let wrongCode = "";
|
||||
const fetchQrCodeImg = (async() => {
|
||||
await fetch("http://transcendance:8080/api/v2/auth/2fa/generate",
|
||||
await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/generate`,
|
||||
{
|
||||
method: 'POST',
|
||||
})
|
||||
@@ -31,7 +32,7 @@
|
||||
})()
|
||||
|
||||
const submitCode = async() => {
|
||||
const response = await fetch("http://transcendance:8080/api/v2/auth/2fa/check",
|
||||
const response = await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/check`,
|
||||
{
|
||||
method : 'POST',
|
||||
headers : {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import Header from '../../pieces/Header.svelte';
|
||||
import { fade, fly } from 'svelte/transition';
|
||||
import { Domain, Port } from "../../Constantes.svelte";
|
||||
|
||||
import * as pong from "./client/pong";
|
||||
import { gameState } from "./client/ws";
|
||||
@@ -34,9 +35,9 @@
|
||||
let idOfIntevalCheckTerminationOfTheMatch;
|
||||
|
||||
onMount( async() => {
|
||||
user = await fetch('http://transcendance:8080/api/v2/user')
|
||||
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
|
||||
.then( x => x.json() );
|
||||
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
|
||||
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`)
|
||||
.then( x => x.json() );
|
||||
options.playerOneUsername = user.username;
|
||||
})
|
||||
@@ -52,7 +53,7 @@
|
||||
showWaitPage = true;
|
||||
const matchOptions = pong.computeMatchOptions(options);
|
||||
|
||||
const responseWhenGrantToken = fetch("http://transcendance:8080/api/v2/game/ticket", {
|
||||
const responseWhenGrantToken = fetch(`http://${Domain}:${Port}/api/v2/game/ticket`, {
|
||||
method : "POST",
|
||||
headers : {'Content-Type': 'application/json'},
|
||||
body : JSON.stringify({
|
||||
@@ -140,13 +141,13 @@
|
||||
const showInvitation = async() => {
|
||||
showGameOption = false;
|
||||
showInvitations = true;
|
||||
invitations = await fetch("http://transcendance:8080/api/v2/game/invitations")
|
||||
invitations = await fetch(`http://${Domain}:${Port}/api/v2/game/invitations`)
|
||||
.then(x => x.json())
|
||||
invitations.length !== 0 ? isThereAnyInvitation = true : isThereAnyInvitation = false
|
||||
}
|
||||
|
||||
const rejectInvitation = async(invitation) => {
|
||||
await fetch("http://transcendance:8080/api/v2/game/decline",{
|
||||
await fetch(`http://${Domain}:${Port}/api/v2/game/decline`, {
|
||||
method: "POST",
|
||||
headers: { 'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
@@ -159,7 +160,7 @@
|
||||
}
|
||||
|
||||
const acceptInvitation = async(invitation : any) => {
|
||||
const res = await fetch("http://transcendance:8080/api/v2/game/accept",{
|
||||
const res = await fetch(`http://${Domain}:${Port}/api/v2/game/accept`, {
|
||||
method: "POST",
|
||||
headers: { 'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import Header from '../../pieces/Header.svelte';
|
||||
import MatchListElem from "../../pieces/MatchListElem.svelte";
|
||||
import { fade, fly } from 'svelte/transition';
|
||||
import { Domain, Port } from "../../Constantes.svelte";
|
||||
|
||||
import * as pongSpectator from "./client/pongSpectator";
|
||||
import { gameState } from "./client/ws";
|
||||
@@ -48,9 +49,9 @@
|
||||
let hiddenGame = true;
|
||||
|
||||
onMount( async() => {
|
||||
user = await fetch('http://transcendance:8080/api/v2/user')
|
||||
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
|
||||
.then( x => x.json() );
|
||||
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
|
||||
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`)
|
||||
.then( x => x.json() );
|
||||
// WIP: fetch for match list here
|
||||
matchList = dummyMatchList;
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import Header from "../../pieces/Header.svelte";
|
||||
import Header from "../../pieces/Header.svelte";
|
||||
import { Domain, Port } from "../../Constantes.svelte";
|
||||
|
||||
//user's stuff
|
||||
let currentUser;
|
||||
let allUsers = [];
|
||||
let idInterval;
|
||||
onMount( async() => {
|
||||
currentUser = await fetch('http://transcendance:8080/api/v2/user')
|
||||
currentUser = await fetch(`http://${Domain}:${Port}/api/v2/user`)
|
||||
.then( x => x.json() );
|
||||
allUsers = await fetch('http://transcendance:8080/api/v2/game/ranking')
|
||||
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/game/ranking`)
|
||||
.then( x => x.json() );
|
||||
idInterval = setInterval(fetchScores, 10000);
|
||||
})
|
||||
@@ -20,7 +21,7 @@
|
||||
})
|
||||
|
||||
function fetchScores() {
|
||||
fetch('http://transcendance:8080/api/v2/game/ranking')
|
||||
fetch(`http://${Domain}:${Port}/api/v2/game/ranking`)
|
||||
.then( x => x.json() )
|
||||
.then( x => allUsers = x );
|
||||
}
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
<script lang="ts">
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte';
|
||||
import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte';
|
||||
import { Domain, Port } from "../../Constantes.svelte";
|
||||
|
||||
import Chat from '../../pieces/chat/Chat.svelte';
|
||||
|
||||
let user;
|
||||
|
||||
onMount( async() => {
|
||||
// console.log('mounting profile display')
|
||||
user = await fetch('http://transcendance:8080/api/v2/user')
|
||||
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
|
||||
.then( (x) => x.json() );
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<Chat color="bisque"/>
|
||||
|
||||
<!-- is this if excessive? -->
|
||||
<div class="outer">
|
||||
<!-- OHHHH i could use #await instead of if and have an nice loading page! -->
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
|
||||
import { onMount } from "svelte";
|
||||
import { binding_callbacks } from "svelte/internal";
|
||||
import { binding_callbacks } from "svelte/internal";
|
||||
import { Domain, Port } from "../../Constantes.svelte";
|
||||
import Button from "../../pieces/Button.svelte";
|
||||
import DisplayAUser from "../../pieces/DisplayAUser.svelte";
|
||||
|
||||
@@ -38,7 +39,7 @@ could be a list of friends and if they're active but i can't see that yet
|
||||
onMount( async() => {
|
||||
// yea no idea what
|
||||
// i mean do i fetch user? i will for now
|
||||
user = await fetch('http://transcendance:8080/api/v2/user')
|
||||
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
|
||||
.then( (x) => x.json() );
|
||||
|
||||
// userBeingViewed = user;
|
||||
@@ -46,26 +47,26 @@ could be a list of friends and if they're active but i can't see that yet
|
||||
// console.log(user)
|
||||
// console.log(user.username)
|
||||
|
||||
myFriends = await fetch("http://transcendance:8080/api/v2/network/myfriends")
|
||||
myFriends = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`)
|
||||
.then( (x) => x.json() );
|
||||
|
||||
// console.log('my friends')
|
||||
// console.log(myFriends)
|
||||
|
||||
requestsMade = await fetch('http://transcendance:8080/api/v2/network/pending')
|
||||
requestsMade = await fetch(`http://${Domain}:${Port}/api/v2/network/pending`)
|
||||
.then( x => x.json() );
|
||||
|
||||
// console.log('Requests pending ');
|
||||
// console.log(requestsMade);
|
||||
|
||||
|
||||
requestsRecieved = await fetch('http://transcendance:8080/api/v2/network/received')
|
||||
requestsRecieved = await fetch(`http://${Domain}:${Port}/api/v2/network/received`)
|
||||
.then( x => x.json() );
|
||||
|
||||
// console.log('Requests received ');
|
||||
// console.log(requestsRecieved);
|
||||
|
||||
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
|
||||
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`)
|
||||
.then( x => x.json() );
|
||||
// console.log('got all users ' + allUsers)
|
||||
|
||||
@@ -74,20 +75,20 @@ could be a list of friends and if they're active but i can't see that yet
|
||||
|
||||
|
||||
const displayAllUsers = async() => {
|
||||
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
|
||||
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`)
|
||||
.then( x => x.json() );
|
||||
// console.log('got all users ' + allUsers)
|
||||
};
|
||||
|
||||
|
||||
const displayAllFriends = async() => {
|
||||
myFriends = await fetch('http://transcendance:8080/api/v2/network/myfriends')
|
||||
myFriends = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`)
|
||||
.then( x => x.json() );
|
||||
// console.log('got all friends ' + allFriends)
|
||||
};
|
||||
|
||||
const displayRequestsMade = async() => {
|
||||
requestsMade = await fetch('http://transcendance:8080/api/v2/network/pending')
|
||||
requestsMade = await fetch(`http://${Domain}:${Port}/api/v2/network/pending`)
|
||||
.then( x => x.json() );
|
||||
// console.log('got requests made ' + requestsMade)
|
||||
};
|
||||
@@ -106,7 +107,7 @@ could be a list of friends and if they're active but i can't see that yet
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
sentFriendRequest = await fetch("http://transcendance:8080/api/v2/network/myfriends", {
|
||||
sentFriendRequest = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`, {
|
||||
method : "POST",
|
||||
headers: { 'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
@@ -124,7 +125,7 @@ could be a list of friends and if they're active but i can't see that yet
|
||||
// sendUsername = userBeingViewed.username;
|
||||
|
||||
// prolly like fetch if you're friends or not?
|
||||
// GET http://transcendance:8080/api/v2/networks/myfriends?username=aUser but i need to make that as long as Cherif
|
||||
// GET `http://${Domain}:${Port}/api/v2/networks/myfriends?username=aUser` but i need to make that as long as Cherif
|
||||
// doesn't have a better option
|
||||
// like i want this thing to return the Friendship ID ideally
|
||||
};
|
||||
|
||||
@@ -55,4 +55,4 @@
|
||||
background-image: url('/img/wave-haikei.svg');
|
||||
} */
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import Card from '../../pieces/Card.svelte';
|
||||
import {onMount} from 'svelte';
|
||||
import { push } from 'svelte-spa-router';
|
||||
import { Domain, Port } from "../../Constantes.svelte";
|
||||
import Button from '../../pieces/Button.svelte';
|
||||
|
||||
let user;
|
||||
@@ -16,7 +17,7 @@
|
||||
let success = {username: '', avatar: '' };
|
||||
|
||||
onMount( async() => {
|
||||
user = await fetch('http://transcendance:8080/api/v2/user')
|
||||
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
|
||||
.then( (x) => x.json() );
|
||||
// do a .catch?
|
||||
|
||||
@@ -33,7 +34,7 @@
|
||||
// console.log('this is what is in the avatar before fetch')
|
||||
// console.log(avatar)
|
||||
|
||||
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
|
||||
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"})
|
||||
.then(response => {return response.blob()})
|
||||
.then(data => {
|
||||
const url = URL.createObjectURL(data);
|
||||
@@ -63,7 +64,7 @@
|
||||
else {
|
||||
errors.username = '';
|
||||
}
|
||||
await fetch('http://transcendance:8080/api/v2/user',{
|
||||
await fetch(`http://${Domain}:${Port}/api/v2/user`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
@@ -100,7 +101,7 @@
|
||||
// tmp
|
||||
console.log(data);
|
||||
|
||||
await fetch("http://transcendance:8080/api/v2/user/avatar",
|
||||
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`,
|
||||
{
|
||||
method : 'POST',
|
||||
body : data,
|
||||
@@ -108,7 +109,7 @@
|
||||
.then(() => uploadAvatarSuccess = true ) // for some reason it needs to be a function, i think a TS thing, not a promis otherwise
|
||||
.then(() => success.avatar = 'Your changes have been saved')
|
||||
.catch(() => errors.avatar = 'Sorry failed to upload your new Avatar' );
|
||||
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
|
||||
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"})
|
||||
.then(response => {return response.blob()})
|
||||
.then(data => {
|
||||
const url = URL.createObjectURL(data);
|
||||
|
||||
@@ -45,4 +45,4 @@
|
||||
background: white;
|
||||
border: 2px solid #45c496;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
import GenerateUserDisplay from './GenerateUserDisplay.svelte';
|
||||
import { Domain, Port } from "../Constantes.svelte";
|
||||
// import {updateGeneratedUser} from './GenerateUserDisplay.svelte';
|
||||
|
||||
export let aUsername;
|
||||
@@ -9,8 +10,8 @@
|
||||
|
||||
onMount( async() => {
|
||||
console.log('Display aUser username: '+ aUsername)
|
||||
// http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
|
||||
user = await fetch(`http://transcendance:8080/api/v2/user?username=${aUsername}`)
|
||||
//`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve`
|
||||
user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${aUsername}`)
|
||||
.then( (x) => x.json() );
|
||||
|
||||
// console.log('Display a user: ')
|
||||
@@ -26,15 +27,15 @@
|
||||
|
||||
const updateUser = async(updatedUser) => {
|
||||
console.log('Display Update aUser username: '+ updateUser)
|
||||
// http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
|
||||
user = await fetch(`http://transcendance:8080/api/v2/user?username=${updateUser}`)
|
||||
//`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve`
|
||||
user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${updateUser}`)
|
||||
.then( (x) => x.json() );
|
||||
};
|
||||
|
||||
// export const updateUser = async(updatedUser) => {
|
||||
// console.log('Display Update aUser username: '+ updateUser)
|
||||
// // http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
|
||||
// user = await fetch(`http://transcendance:8080/api/v2/user?username=${updateUser}`)
|
||||
// //`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve`
|
||||
// user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${updateUser}`)
|
||||
// .then( (x) => x.json() );
|
||||
// updateGeneratedUser(updateUser);
|
||||
|
||||
@@ -56,4 +57,4 @@
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
import { Domain, Port } from "../Constantes.svelte";
|
||||
|
||||
export let user;
|
||||
export let primary;
|
||||
@@ -11,7 +12,7 @@
|
||||
onMount( async() => {
|
||||
// using this for now cuz for some reason there is yet to be a way to fet another person's avatar
|
||||
if (primary) {
|
||||
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
|
||||
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"})
|
||||
.then(response => {return response.blob()})
|
||||
.then(data => {
|
||||
const url = URL.createObjectURL(data);
|
||||
@@ -253,4 +254,4 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { push } from "svelte-spa-router";
|
||||
import { location } from 'svelte-spa-router';
|
||||
import { Domain, Port } from "../Constantes.svelte";
|
||||
|
||||
import active from 'svelte-spa-router/active'
|
||||
// or i could leave them all and not display if they're active?
|
||||
|
||||
|
||||
let handleClickLogout = async () => {
|
||||
await fetch('http://transcendance:8080/api/v2/auth/logout', {
|
||||
await fetch(`http://${Domain}:${Port}/api/v2/auth/logout`, {
|
||||
method: 'POST',
|
||||
})
|
||||
// .then(resp => resp.json)
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import Layouts from './Chat_layouts.svelte';
|
||||
import { Domain, PortIo } from "../../Constantes.svelte";
|
||||
export let color = "transparent";
|
||||
|
||||
/* web sockets with socket.io
|
||||
*/
|
||||
import { onMount } from 'svelte';
|
||||
import io from 'socket.io-client';
|
||||
const socket = io(`http://${Domain}:${PortIo}`, {
|
||||
path: '/chat'
|
||||
});
|
||||
onMount(async => {
|
||||
socket.on('connect', function(){
|
||||
console.log("socket.io connected");
|
||||
});
|
||||
socket.on('disconnect', function(){
|
||||
console.log("socket.io disconnected");
|
||||
});
|
||||
socket.on('connect_error', function(){
|
||||
console.log("socket.io connect_error");
|
||||
});
|
||||
socket.on('connect_timeout', function(){
|
||||
console.log("socket.io connect_timeout");
|
||||
});
|
||||
socket.on('error', function(){
|
||||
console.log("socket.io error");
|
||||
});
|
||||
socket.on('reconnect', function(){
|
||||
console.log("socket.io reconnect");
|
||||
});
|
||||
socket.on('reconnect_attempt', function(){
|
||||
console.log("socket.io reconnect_attempt");
|
||||
});
|
||||
socket.on('reconnecting', function(){
|
||||
console.log("socket.io reconnecting");
|
||||
});
|
||||
socket.on('reconnect_error', function(){
|
||||
console.log("socket.io reconnect_error");
|
||||
});
|
||||
socket.on('reconnect_failed', function(){
|
||||
console.log("socket.io reconnect_failed");
|
||||
});
|
||||
socket.on('ping', function(){
|
||||
console.log("socket.io ping");
|
||||
});
|
||||
socket.on('pong', function(){
|
||||
console.log("socket.io pong");
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<Layouts color={color} />
|
||||
|
||||
<style></style>
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
export let color;
|
||||
export let layout;
|
||||
|
||||
</script>
|
||||
|
||||
<div class="{layout} chat_box" style="background-color: {color};">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* chat_box and default style
|
||||
*/
|
||||
.chat_box {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
padding: 0px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
border: 1px solid black;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
GLOBAL STYLES
|
||||
*/
|
||||
|
||||
|
||||
/* Hide scrollbar
|
||||
*/
|
||||
.chat_box :global(*) {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
.chat_box :global(*::-webkit-scrollbar) {
|
||||
display: none; /* Chrome, Safari and Opera */
|
||||
}
|
||||
|
||||
|
||||
/* for grid_box and all childrens
|
||||
*/
|
||||
.chat_box :global(.grid_box) {
|
||||
display: grid;
|
||||
margin: 5px;
|
||||
gap: 5px;
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
}
|
||||
.chat_box :global(.grid_box *) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
/* all p
|
||||
*/
|
||||
.chat_box :global(.grid_box p) {
|
||||
padding: 10px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
|
||||
/* all panel
|
||||
*/
|
||||
.chat_box :global(.panel) {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.chat_box :global(.panel > *) {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
GLOBAL UTILITIES
|
||||
*/
|
||||
|
||||
|
||||
/* __show_if_only_child
|
||||
*/
|
||||
.chat_box :global(.__show_if_only_child) {
|
||||
display: none;
|
||||
}
|
||||
.chat_box :global(.__show_if_only_child:only-child) {
|
||||
display: flex;
|
||||
color: rgb(100, 100, 100);
|
||||
}
|
||||
|
||||
|
||||
/* __center
|
||||
*/
|
||||
.chat_box :global(.__center) {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
|
||||
/* __border_top
|
||||
*/
|
||||
.chat_box :global(.__border_top) {
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
|
||||
/* __check_change_next
|
||||
*/
|
||||
.chat_box :global(.__check_change_next:checked ~ .__to_show) {
|
||||
display: flex;
|
||||
}
|
||||
.chat_box :global(.__check_change_next:checked ~ .__to_block),
|
||||
.chat_box :global(.__check_change_next:checked ~ .__to_block *) {
|
||||
pointer-events: none;
|
||||
color: rgb(100, 100, 100);
|
||||
}
|
||||
.chat_box :global(.__to_show) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
|
||||
<!--
|
||||
<Button
|
||||
bind:layout
|
||||
new_layout=""
|
||||
on_click={}
|
||||
my_class=""
|
||||
my_title=""
|
||||
>
|
||||
value
|
||||
</Button>
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
export let my_class = "";
|
||||
export let my_title = "";
|
||||
export let layout = "";
|
||||
export let new_layout = "";
|
||||
export let on_click = "";
|
||||
|
||||
function update_layout() {
|
||||
layout = new_layout;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<button on:click={update_layout} on:click={on_click} title={my_title} class={my_class}>
|
||||
<p><slot></slot></p>
|
||||
</button>
|
||||
|
||||
<style>
|
||||
|
||||
/*
|
||||
- default config
|
||||
- for btn list
|
||||
- for transparent btn
|
||||
- for deactivated btn
|
||||
- for icon
|
||||
- for 3 dots btn
|
||||
- for close btn
|
||||
- for back btn
|
||||
*/
|
||||
|
||||
|
||||
/* default config
|
||||
*/
|
||||
button {
|
||||
padding: 0px;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
border: none;
|
||||
background-color: rgb(220, 220, 220);
|
||||
}
|
||||
button p {
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
button:hover {
|
||||
background-color: rgb(200, 200, 200);
|
||||
}
|
||||
button:active {
|
||||
background-color: rgb(190, 190, 190);
|
||||
}
|
||||
|
||||
|
||||
/* for btn list
|
||||
*/
|
||||
.list:not(:hover) {
|
||||
background-color: rgb(240, 240, 240);
|
||||
}
|
||||
.list p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
/* for transparent btn
|
||||
*/
|
||||
.transparent:not(:hover) {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
/* for deactivated btn
|
||||
*/
|
||||
.deactivate {
|
||||
background-color: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
/* for icon
|
||||
*/
|
||||
.icon p {
|
||||
display: none;
|
||||
}
|
||||
.icon:not(:hover) {
|
||||
background-color: transparent;
|
||||
}
|
||||
.icon {
|
||||
width: 30px;
|
||||
height: 100%;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
|
||||
/* for 3 dots btn
|
||||
*/
|
||||
.dots::after {
|
||||
content: '\2807';
|
||||
font-size: 20px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
transform: translateY(-50%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
/* for close btn
|
||||
*/
|
||||
.close::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: calc(50% - 1px);
|
||||
left: 5px;
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
|
||||
/* for back btn
|
||||
*/
|
||||
.back::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: calc(50% - 6px - 1px);
|
||||
left: 6px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-left: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
|
||||
/* for blocked user
|
||||
https://www.fileformat.info/info/unicode/category/So/list.htm
|
||||
U+1F512 LOCK 🔒
|
||||
U+1F513 OPEN LOCK 🔓
|
||||
*/
|
||||
.blocked {
|
||||
padding-left: 30px;
|
||||
}
|
||||
.blocked::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: calc(50% - 2px);
|
||||
left: 10px;
|
||||
cursor: pointer;
|
||||
width: 13px;
|
||||
height: 10px;
|
||||
border-radius: 2px;
|
||||
background-color: rgb(110, 110, 110);
|
||||
}
|
||||
.blocked::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: calc(50% - 9px);
|
||||
left: 12px;
|
||||
cursor: pointer;
|
||||
width: 9px;
|
||||
height: 13px;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
border: 3px solid rgb(110, 110, 110);
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import Debug from './tmp_debug.svelte';
|
||||
|
||||
import ChatBox from './Chat_box_css.svelte';
|
||||
|
||||
import CloseLayout from './Layout_close.svelte';
|
||||
import HomeLayout from './Layout_home.svelte';
|
||||
import RoomLayout from './Layout_room.svelte';
|
||||
import NewLayout from './Layout_new.svelte';
|
||||
import SettingsLayout from './Layout_settings.svelte';
|
||||
import RoomsetLayout from './Layout_room_set.svelte';
|
||||
import ProtectedLayout from './Layout_protected.svelte';
|
||||
import CreateLayout from './Layout_create.svelte';
|
||||
import MuteLayout from './Layout_mute.svelte';
|
||||
import UserLayout from './Layout_user.svelte';
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
|
||||
/* global variables
|
||||
*/
|
||||
export let color;
|
||||
let room = "";
|
||||
let admin = false;
|
||||
let layout = "close";
|
||||
let layouts = ["home", "home"];
|
||||
|
||||
/* hold previous version of layout, to go back
|
||||
*/
|
||||
function set_layouts(layout)
|
||||
{
|
||||
if (layout === "close")
|
||||
return;
|
||||
if (layout === layouts[0])
|
||||
return;
|
||||
if (layout === layouts[1])
|
||||
layouts = [layout, "home"];
|
||||
else
|
||||
layouts = [layout, layouts[0]];
|
||||
}
|
||||
$: set_layouts(layout);
|
||||
|
||||
</script>
|
||||
|
||||
<ChatBox layout={layout} color={color}>
|
||||
|
||||
{#if layout === "home"}
|
||||
<HomeLayout bind:layout />
|
||||
|
||||
{:else if layout === "close"}
|
||||
<CloseLayout bind:layout />
|
||||
|
||||
{:else if layout === "room"}
|
||||
<RoomLayout bind:layout back={layouts[1]} />
|
||||
|
||||
{:else if layout === "new"}
|
||||
<NewLayout bind:layout back={layouts[1]} />
|
||||
|
||||
{:else if layout === "settings"}
|
||||
<SettingsLayout bind:layout back={layouts[1]} />
|
||||
|
||||
{:else if layout === "room_set"}
|
||||
<RoomsetLayout bind:layout back={layouts[1]} />
|
||||
|
||||
{:else if layout === "protected"}
|
||||
<ProtectedLayout bind:layout back={layouts[1]} />
|
||||
|
||||
{:else if layout === "create"}
|
||||
<CreateLayout bind:layout back={layouts[1]} />
|
||||
|
||||
{:else if layout === "mute"}
|
||||
<MuteLayout bind:layout back={layouts[1]} />
|
||||
|
||||
{:else if layout === "user"}
|
||||
<UserLayout bind:layout back={layouts[1]} />
|
||||
|
||||
{/if}
|
||||
|
||||
</ChatBox>
|
||||
|
||||
<!-- TMP DEBUG -->
|
||||
<Debug bind:layout bind:layouts />
|
||||
|
||||
<style></style>
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<script>
|
||||
|
||||
export let name;
|
||||
|
||||
</script>
|
||||
|
||||
<div class="chat_msg {name}">
|
||||
<p class="name">{name}</p>
|
||||
<p class="msg"><slot></slot></p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.chat_msg {
|
||||
/*
|
||||
white-space: pre-wrap;
|
||||
*/
|
||||
margin: 5px auto;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
/* all msg
|
||||
*/
|
||||
.chat_msg {
|
||||
margin-left: 0px;
|
||||
background-color: rgb(210, 210, 210);
|
||||
max-width: 80%;
|
||||
}
|
||||
.chat_msg p {
|
||||
padding: 0px;
|
||||
}
|
||||
.chat_msg p.name {
|
||||
margin: 0px;
|
||||
font-size: 12px;
|
||||
color: rgb(100, 100, 100);
|
||||
}
|
||||
.chat_msg p.msg {
|
||||
margin: 5px 0px;
|
||||
}
|
||||
.chat_msg p.msg :global(*) {
|
||||
display: inline;
|
||||
}
|
||||
/* msg perso
|
||||
*/
|
||||
.chat_msg.me {
|
||||
margin-right: 0px;
|
||||
margin-left: auto;
|
||||
background-color: rgb(210, 110, 10);
|
||||
}
|
||||
.chat_msg.me p.name {
|
||||
display: none;
|
||||
}
|
||||
/* msg server
|
||||
*/
|
||||
.chat_msg.SERVER {
|
||||
margin-left: auto;
|
||||
background-color: transparent;
|
||||
}
|
||||
.chat_msg.SERVER p.name {
|
||||
display: none;
|
||||
}
|
||||
.chat_msg.SERVER p.msg {
|
||||
margin: 0px auto;
|
||||
font-size: 12px;
|
||||
color: rgb(100, 100, 100);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
export let layout;
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
<Button bind:layout new_layout="home" my_class="chat">
|
||||
chat
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* layout "close"
|
||||
*/
|
||||
.grid_box :global(.chat) {grid-area: chat;}
|
||||
.grid_box {
|
||||
gap: 0px;
|
||||
grid:
|
||||
' chat ' auto
|
||||
/ auto ;
|
||||
}
|
||||
:global(.chat_box.close) .grid_box {
|
||||
margin: 0px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
GLOBAL STYLES
|
||||
*/
|
||||
|
||||
|
||||
/* Hide scrollbar
|
||||
*/
|
||||
.chat_box :global(*) {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
.chat_box :global(*::-webkit-scrollbar) {
|
||||
display: none; /* Chrome, Safari and Opera */
|
||||
}
|
||||
|
||||
|
||||
/* for grid_box and all childrens
|
||||
*/
|
||||
.chat_box :global(.grid_box) {
|
||||
display: grid;
|
||||
margin: 0px;
|
||||
gap: 5px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.chat_box :global(.grid_box *) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
/* all p
|
||||
*/
|
||||
.chat_box :global(.grid_box p) {
|
||||
padding: 10px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
|
||||
/* all panel
|
||||
*/
|
||||
.chat_box :global(.panel) {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.chat_box :global(.panel > *) {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
GLOBAL UTILITIES
|
||||
*/
|
||||
|
||||
|
||||
/* __show_if_only_child
|
||||
*/
|
||||
.chat_box :global(.__show_if_only_child) {
|
||||
display: none;
|
||||
}
|
||||
.chat_box :global(.__show_if_only_child:only-child) {
|
||||
display: flex;
|
||||
color: rgb(100, 100, 100);
|
||||
}
|
||||
|
||||
|
||||
/* __center
|
||||
*/
|
||||
.chat_box :global(.__center) {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
|
||||
/* __border_top
|
||||
*/
|
||||
.chat_box :global(.__border_top) {
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
|
||||
/* __check_change_next
|
||||
*/
|
||||
.chat_box :global(.__check_change_next:checked ~ .__to_show) {
|
||||
display: flex;
|
||||
}
|
||||
.chat_box :global(.__check_change_next:checked ~ .__to_block),
|
||||
.chat_box :global(.__check_change_next:checked ~ .__to_block *) {
|
||||
pointer-events: none;
|
||||
color: rgb(100, 100, 100);
|
||||
}
|
||||
.chat_box :global(.__to_show) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
export let layout = "";
|
||||
export let back = "";
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- create -->
|
||||
<Button my_class="create deactivate">
|
||||
create
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button bind:layout new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- panel_create -->
|
||||
<div class="panel panel_create">
|
||||
<form>
|
||||
<!-- name: -->
|
||||
<label for="chat_name"><p>new room name :</p></label>
|
||||
<input id="chat_name" required>
|
||||
<!-- [ ] pubic -->
|
||||
<input id="chat_public" type="radio" name="chat_create_type" checked>
|
||||
<label for="chat_public" class="_radio"><p>public</p></label>
|
||||
<!-- [ ] private -->
|
||||
<input id="chat_private" type="radio" name="chat_create_type">
|
||||
<label for="chat_private" class="_radio"><p>private</p></label>
|
||||
<!-- [ ] protected -->
|
||||
<input id="chat_protected" class="__check_change_next" type="radio" name="chat_create_type">
|
||||
<label for="chat_protected" class="_radio"><p>protected</p></label>
|
||||
<!-- [x] protected -->
|
||||
<div class="__to_show">
|
||||
<label for="chat_pswd"><p>choose a password :</p></label>
|
||||
<input id="chat_pswd" type="password" placeholder="minimum 8 characters" minlength="8">
|
||||
<p>confirm password :</p>
|
||||
<input type="password">
|
||||
</div>
|
||||
<input type="submit" value="⮡">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "create"
|
||||
*/
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
.grid_box :global(.create ) {grid-area: create;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.panel_create) {grid-area: panel_create;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back create close ' auto
|
||||
' panel_create panel_create panel_create ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
/* radio elements style check
|
||||
*/
|
||||
form input[type=radio] {
|
||||
display: none;
|
||||
}
|
||||
form label._radio {
|
||||
margin: 0px 20px 0px auto;
|
||||
padding-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
form label._radio p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
form label._radio::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: calc(50% - 6px);
|
||||
right: 0px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
border: 2px solid rgb(150, 150, 150);
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
}
|
||||
form input[type=radio]:checked
|
||||
+ label._radio::after {
|
||||
background-color: rgb(200, 200, 200);
|
||||
}
|
||||
|
||||
|
||||
/* submit
|
||||
*/
|
||||
form input[type=submit] {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
export let layout;
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- settings -->
|
||||
<Button bind:layout new_layout="settings" my_class="settings dots icon">
|
||||
settings
|
||||
</Button>
|
||||
|
||||
<!-- new -->
|
||||
<Button bind:layout new_layout="new" my_class="new transparent">
|
||||
new
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button bind:layout new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- panel home -->
|
||||
<div class="panel panel_home __border_top">
|
||||
<p class="title">list of your rooms :</p>
|
||||
<div class="room_list">
|
||||
<div class="__show_if_only_child">
|
||||
<p class="__center">/ you have no chat room yet /</p>
|
||||
</div>
|
||||
<!-- placeholders
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
a room
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
another room
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
placeholder
|
||||
</Button>
|
||||
------------- -->
|
||||
<!-- END placeholders -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "home"
|
||||
*/
|
||||
.grid_box :global(.settings ) {grid-area: settings;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.new ) {grid-area: new;}
|
||||
.grid_box :global(.panel_home) {grid-area: panel_home;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' settings new close ' auto
|
||||
' panel_home panel_home panel_home ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
/* panel home
|
||||
*/
|
||||
.panel_home p.title {
|
||||
margin: 10px auto 0px auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
export let layout = "";
|
||||
export let back = "";
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- user -->
|
||||
<Button my_class="user deactivate">
|
||||
<user>
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button bind:layout new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- panel_mute -->
|
||||
|
||||
<!-- MUTE -->
|
||||
<div class="panel panel_mute __border_top">
|
||||
<p class="__center">mute this user for a time :</p>
|
||||
<form>
|
||||
<!-- forever -->
|
||||
<input id="chat_mute_forever" class="__check_change_next" type="checkbox">
|
||||
<label for="chat_mute_forever" class="_checkbox"><p>forever</p></label>
|
||||
<div class="__to_block">
|
||||
<!-- minutes -->
|
||||
<label for="chat_mute_minutes" class="_select">
|
||||
<p>minutes :</p>
|
||||
<select id="chat_mute_minutes">
|
||||
<option value="01">00</option>
|
||||
<option value="01">01</option>
|
||||
<option value="02">02</option>
|
||||
<option value="03">03</option>
|
||||
<option value="04">04</option>
|
||||
<option value="05">05</option>
|
||||
<option value="06">06</option>
|
||||
<option value="07">07</option>
|
||||
<option value="10">10</option>
|
||||
<option value="11">11</option>
|
||||
<option value="12">12</option>
|
||||
<option value="13">13</option>
|
||||
<option value="14">14</option>
|
||||
<option value="15">15</option>
|
||||
<option value="16">16</option>
|
||||
<option value="17">17</option>
|
||||
<option value="20">20</option>
|
||||
<option value="21">21</option>
|
||||
<option value="22">22</option>
|
||||
<option value="23">23</option>
|
||||
<option value="24">24</option>
|
||||
<option value="25">25</option>
|
||||
<option value="26">26</option>
|
||||
<option value="27">27</option>
|
||||
<option value="30">30</option>
|
||||
<option value="31">31</option>
|
||||
<option value="32">32</option>
|
||||
<option value="33">33</option>
|
||||
<option value="34">34</option>
|
||||
<option value="35">35</option>
|
||||
<option value="36">36</option>
|
||||
<option value="37">37</option>
|
||||
<option value="40">40</option>
|
||||
<option value="41">41</option>
|
||||
<option value="42">42</option>
|
||||
<option value="43">43</option>
|
||||
<option value="44">44</option>
|
||||
<option value="45">45</option>
|
||||
<option value="46">46</option>
|
||||
<option value="47">47</option>
|
||||
<option value="50">50</option>
|
||||
<option value="51">51</option>
|
||||
<option value="52">52</option>
|
||||
<option value="53">53</option>
|
||||
<option value="54">54</option>
|
||||
<option value="55">55</option>
|
||||
<option value="56">56</option>
|
||||
<option value="57">57</option>
|
||||
<option value="60">60</option>
|
||||
</select>
|
||||
</label>
|
||||
<!-- hours -->
|
||||
<label for="chat_mute_hours" class="_select">
|
||||
<p>hours :</p>
|
||||
<select id="chat_mute_hours">
|
||||
<option value="01">00</option>
|
||||
<option value="01">01</option>
|
||||
<option value="02">02</option>
|
||||
<option value="03">03</option>
|
||||
<option value="04">04</option>
|
||||
<option value="05">05</option>
|
||||
<option value="06">06</option>
|
||||
<option value="07">07</option>
|
||||
<option value="10">10</option>
|
||||
<option value="11">11</option>
|
||||
<option value="12">12</option>
|
||||
<option value="13">13</option>
|
||||
<option value="14">14</option>
|
||||
<option value="15">15</option>
|
||||
<option value="16">16</option>
|
||||
<option value="17">17</option>
|
||||
<option value="20">20</option>
|
||||
<option value="21">21</option>
|
||||
<option value="22">22</option>
|
||||
<option value="23">23</option>
|
||||
<option value="24">24</option>
|
||||
<option value="25">25</option>
|
||||
<option value="26">26</option>
|
||||
<option value="27">27</option>
|
||||
<option value="30">30</option>
|
||||
<option value="31">31</option>
|
||||
<option value="32">32</option>
|
||||
<option value="33">33</option>
|
||||
<option value="34">34</option>
|
||||
<option value="35">35</option>
|
||||
<option value="36">36</option>
|
||||
<option value="37">37</option>
|
||||
<option value="40">40</option>
|
||||
<option value="41">41</option>
|
||||
<option value="42">42</option>
|
||||
<option value="43">43</option>
|
||||
<option value="44">44</option>
|
||||
<option value="45">45</option>
|
||||
<option value="46">46</option>
|
||||
<option value="47">47</option>
|
||||
<option value="50">50</option>
|
||||
<option value="51">51</option>
|
||||
<option value="52">52</option>
|
||||
<option value="53">53</option>
|
||||
<option value="54">54</option>
|
||||
<option value="55">55</option>
|
||||
<option value="56">56</option>
|
||||
<option value="57">57</option>
|
||||
<option value="60">60</option>
|
||||
</select>
|
||||
</label>
|
||||
<!-- days -->
|
||||
<label for="chat_mute_days" class="_select">
|
||||
<p>days :</p>
|
||||
<select id="chat_mute_days">
|
||||
<option value="00">00</option>
|
||||
<option value="01">01</option>
|
||||
<option value="02">02</option>
|
||||
<option value="03">03</option>
|
||||
<option value="04">04</option>
|
||||
<option value="05">05</option>
|
||||
<option value="06">06</option>
|
||||
<option value="07">07</option>
|
||||
<option value="10">10</option>
|
||||
<option value="11">11</option>
|
||||
<option value="12">12</option>
|
||||
<option value="13">13</option>
|
||||
<option value="14">14</option>
|
||||
<option value="15">15</option>
|
||||
<option value="16">16</option>
|
||||
<option value="17">17</option>
|
||||
<option value="20">20</option>
|
||||
<option value="21">21</option>
|
||||
<option value="22">22</option>
|
||||
<option value="23">23</option>
|
||||
<option value="24">24</option>
|
||||
<option value="25">25</option>
|
||||
<option value="26">26</option>
|
||||
<option value="27">27</option>
|
||||
<option value="30">30</option>
|
||||
<option value="31">31</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<input type="submit" value="⮡">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "mute"
|
||||
*/
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
.grid_box :global(.user ) {grid-area: user;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.panel_mute) {grid-area: panel_mute;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back user close ' auto
|
||||
' panel_mute panel_mute panel_mute ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
/* checkbox
|
||||
*/
|
||||
form input[type=checkbox] {
|
||||
display: none;
|
||||
}
|
||||
form label._checkbox {
|
||||
margin: 0px auto 0px 10px;
|
||||
padding-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
form label._checkbox::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: calc(50% - 6px);
|
||||
left: 0px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border: 2px solid rgb(150, 150, 150);
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
}
|
||||
form input[type=checkbox]:checked
|
||||
+ label._checkbox::after {
|
||||
background-color: rgb(200, 200, 200);
|
||||
}
|
||||
|
||||
|
||||
/* select
|
||||
*/
|
||||
form label._select {
|
||||
flex-direction: row;
|
||||
}
|
||||
form label._select p {
|
||||
margin: 0px;
|
||||
}
|
||||
form select {
|
||||
margin: auto auto auto 10px;
|
||||
background-color: rgb(220, 220, 220);
|
||||
border: none;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
form select:hover {
|
||||
background-color: rgb(200, 200, 200);
|
||||
}
|
||||
|
||||
|
||||
/* submit
|
||||
*/
|
||||
form input[type=submit] {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
export let layout = "";
|
||||
export let back = "";
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- new -->
|
||||
<Button my_class="new deactivate">
|
||||
new
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button bind:layout new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- panel_new -->
|
||||
<div class="panel panel_new __border_top">
|
||||
<Button bind:layout new_layout="create" my_class="create">
|
||||
create
|
||||
</Button>
|
||||
<p>join room :</p>
|
||||
<div class="public_rooms">
|
||||
<div class="__show_if_only_child">
|
||||
<p class="__center">/ there are no public rooms yet /</p>
|
||||
</div>
|
||||
<!-- placeholders
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
placeholder
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
join room
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
one room
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
another room
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
one room
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
another room
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
one room
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
another room
|
||||
</Button>
|
||||
<Button bind:layout new_layout="room" my_class="list">
|
||||
one more room
|
||||
</Button>
|
||||
------------- -->
|
||||
<!-- END placeholders -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "new"
|
||||
*/
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
.grid_box :global(.new ) {grid-area: new;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.panel_new) {grid-area: panel_new;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back new close ' auto
|
||||
' panel_new panel_new panel_new ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
export let layout = "";
|
||||
export let back = "";
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- room_name -->
|
||||
<Button my_class="room_name deactivate">
|
||||
<room_name>
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button bind:layout new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- panel_protected -->
|
||||
<div class="panel panel_protected __border_top">
|
||||
<p class="title __center">this room is protected</p>
|
||||
<form>
|
||||
<label for="chat_pswd"><p>password :</p></label>
|
||||
<input id="chat_pswd" type="password" required>
|
||||
<input type="submit" value="⮡">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "protected"
|
||||
*/
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
.grid_box :global(.room_name ) {grid-area: room_name;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.panel_protected) {grid-area: panel_protected;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back room_name close ' auto
|
||||
' panel_protected panel_protected panel_protected ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
/* submit
|
||||
*/
|
||||
form input[type=submit] {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
import Msg from './Chat_msg.svelte';
|
||||
import io from 'socket.io-client';
|
||||
|
||||
export let layout = "";
|
||||
export let back = "";
|
||||
|
||||
let msg = "";
|
||||
let text_area;
|
||||
let msgs = [];
|
||||
|
||||
function add_msg(from, the_msg)
|
||||
{
|
||||
msgs = [...msgs, { content: the_msg, name: from }];
|
||||
}
|
||||
|
||||
function send_msg()
|
||||
{
|
||||
msg = msg.trim();
|
||||
|
||||
if (msg.length > 0) {
|
||||
//socket.emit('sendmsg', msg);
|
||||
add_msg("me", msg);
|
||||
}
|
||||
|
||||
msg = "";
|
||||
text_area.focus();
|
||||
}
|
||||
|
||||
function send_msg_if(evt)
|
||||
{
|
||||
if (evt.shiftKey && evt.key === "Enter")
|
||||
{
|
||||
evt.preventDefault();
|
||||
send_msg();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- room_name -->
|
||||
<Button bind:layout new_layout="room_set" my_class="room_name transparent">
|
||||
<room_name>
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button bind:layout new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- msg -->
|
||||
<div class="panel panel_msg">
|
||||
<div class="msg_thread">
|
||||
{#each msgs as msg}
|
||||
<Msg name={msg.name}>{@html msg.content}</Msg>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- write -->
|
||||
<div class="panel_write">
|
||||
<div
|
||||
class="text_area"
|
||||
bind:innerHTML={msg}
|
||||
bind:this={text_area}
|
||||
on:keypress={send_msg_if}
|
||||
contenteditable="true"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- send -->
|
||||
<Button my_class="send" on_click={send_msg}>
|
||||
send
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "room"
|
||||
*/
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
.grid_box :global(.room_name ) {grid-area: room_name;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.panel_msg ) {grid-area: panel_msg;}
|
||||
.grid_box :global(.send ) {grid-area: send;}
|
||||
.grid_box :global(.panel_write) {grid-area: panel_write;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back room_name room_name close ' auto
|
||||
' panel_msg panel_msg panel_msg panel_msg ' 1fr
|
||||
' panel_write panel_write send send ' auto
|
||||
/ auto 1fr auto auto ;
|
||||
}
|
||||
|
||||
|
||||
/* write area
|
||||
*/
|
||||
.grid_box .panel_write {
|
||||
border: none;
|
||||
overflow: visible;
|
||||
}
|
||||
.grid_box .text_area {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
background-color: white;
|
||||
border: 1px solid black;
|
||||
}
|
||||
.grid_box .text_area:focus {
|
||||
height: auto;
|
||||
min-height: 100%;
|
||||
max-height: 300px;
|
||||
}
|
||||
.grid_box .panel_write .text_area :global(*) {
|
||||
display: block ruby;
|
||||
}
|
||||
|
||||
|
||||
/* msg area
|
||||
*/
|
||||
.grid_box .panel_msg {
|
||||
flex-direction: column-reverse;
|
||||
border: 1px solid black;
|
||||
}
|
||||
.grid_box .msg_thread {
|
||||
width: 100%;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
export let layout = "";
|
||||
export let back = "";
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- room_name -->
|
||||
<Button my_class="room_name deactivate">
|
||||
<room_name>
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button bind:layout new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- panel_room_set -->
|
||||
<div class="panel panel_room_set __border_top">
|
||||
<Button bind:layout new_layout="create" my_class="create">
|
||||
leave
|
||||
</Button>
|
||||
<p>room users :</p>
|
||||
<div class="room_users">
|
||||
<div class="__show_if_only_child">
|
||||
<p class="__center">/ there are no public rooms yet /</p>
|
||||
</div>
|
||||
<!-- placeholders
|
||||
------------- -->
|
||||
<Button bind:layout new_layout="user" my_class="list">
|
||||
user 1
|
||||
</Button>
|
||||
<Button bind:layout new_layout="user" my_class="list blocked">
|
||||
user 2
|
||||
</Button>
|
||||
<Button bind:layout new_layout="user" my_class="list">
|
||||
user 3
|
||||
</Button>
|
||||
<Button bind:layout new_layout="user" my_class="list">
|
||||
user 4
|
||||
</Button>
|
||||
<!-- END placeholders -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "room_set"
|
||||
*/
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
.grid_box :global(.room_name ) {grid-area: room_name;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.panel_room_set) {grid-area: panel_room_set;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back room_name close ' auto
|
||||
' panel_room_set panel_room_set panel_room_set ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
export let layout = "";
|
||||
export let back = "";
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- settings -->
|
||||
<Button my_class="room_name deactivate">
|
||||
settings
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button bind:layout new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- panel_settings -->
|
||||
<div class="panel panel_settings __border_top">
|
||||
<p>blocked users :</p>
|
||||
<div class="blocked_users">
|
||||
<div class="__show_if_only_child">
|
||||
<p class="__center">/ you have blocked no one /</p>
|
||||
</div>
|
||||
<!-- placeholders
|
||||
<Button bind:layout new_layout="user" my_class="list blocked">
|
||||
user 1
|
||||
</Button>
|
||||
<Button bind:layout new_layout="user" my_class="list blocked">
|
||||
user 2
|
||||
</Button>
|
||||
<Button bind:layout new_layout="user" my_class="list blocked">
|
||||
user 3
|
||||
</Button>
|
||||
<Button bind:layout new_layout="user" my_class="list blocked">
|
||||
user 4
|
||||
</Button>
|
||||
------------- -->
|
||||
<!-- END placeholders -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "settings"
|
||||
*/
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
.grid_box :global(.settings ) {grid-area: settings;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.panel_settings) {grid-area: panel_settings;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back settings close ' auto
|
||||
' panel_settings panel_settings panel_settings ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
|
||||
<script>
|
||||
|
||||
import Button from './Chat_button.svelte';
|
||||
export let layout = "";
|
||||
export let back = "";
|
||||
|
||||
let mute = "mute";
|
||||
let block = "block";
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- user -->
|
||||
<Button my_class="user deactivate">
|
||||
<user>
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button bind:layout new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- room_name -->
|
||||
{#if back === "room_set"}
|
||||
<Button my_class="room_name deactivate __border_top">
|
||||
<room_name>
|
||||
</Button>
|
||||
{/if}
|
||||
|
||||
<!-- panel_user -->
|
||||
<div class="panel panel_user __border_top">
|
||||
<p class="__center">user options :</p>
|
||||
<Button>
|
||||
view profile
|
||||
</Button>
|
||||
<Button>
|
||||
game invitation
|
||||
</Button>
|
||||
<Button>
|
||||
{block}
|
||||
</Button>
|
||||
|
||||
{#if back === "room_set"}
|
||||
<Button>
|
||||
make admin
|
||||
</Button>
|
||||
<Button>
|
||||
{mute}
|
||||
</Button>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "user"
|
||||
*/
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
.grid_box :global(.user ) {grid-area: user;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.room_name ) {grid-area: room_name;}
|
||||
.grid_box :global(.panel_user) {grid-area: panel_user;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back user close ' auto
|
||||
' room_name room_name room_name ' auto
|
||||
' panel_user panel_user panel_user ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
/* for line height
|
||||
*/
|
||||
.panel_user {
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<script>
|
||||
|
||||
export let layout = "";
|
||||
export let layouts = [];
|
||||
|
||||
</script>
|
||||
|
||||
<div style="display: flex; flex-direction: column; font-size: 12px; position: fixed; top: 20px; left: 20px; background-color: white;">
|
||||
<p>temp, for testing :</p>
|
||||
<button on:click={function(){layout = "close" }}>close</button>
|
||||
<button on:click={function(){layout = "home" }}>home</button>
|
||||
<button on:click={function(){layout = "room" }}>room</button>
|
||||
<button on:click={function(){layout = "new" }}>new</button>
|
||||
<button on:click={function(){layout = "settings" }}>settings</button>
|
||||
<button on:click={function(){layout = "room_set" }}>room_set</button>
|
||||
<button on:click={function(){layout = "protected"}}>protected</button>
|
||||
<button on:click={function(){layout = "create" }}>create</button>
|
||||
<button on:click={function(){layout = "mute" }}>mute</button>
|
||||
<button on:click={function(){
|
||||
layouts = ["settings", "settings"];
|
||||
layout = "user";
|
||||
}}>user from settings</button>
|
||||
<button on:click={function(){
|
||||
layouts = ["room_set", "room_set"];
|
||||
layout = "user";
|
||||
}}>user from room_set</button>
|
||||
</div>
|
||||
Reference in New Issue
Block a user