From c1e2a1fd428447b36af2b5214efacecde3cde701 Mon Sep 17 00:00:00 2001 From: Brieuc Dubois <brieuc.a.dubois@student.uclouvain.be> Date: Mon, 21 Oct 2024 13:48:15 +0000 Subject: [PATCH] Pre-commit hooks and CI linting for every commit --- .githooks/pre-commit | 15 ++++ .gitlab-ci.yml | 27 +++++-- backend/app/database.py | 1 - backend/app/hashing.py | 74 ++++++++++++------- backend/app/main.py | 74 ++++++++++++------- backend/app/test_main.py | 62 +++++++--------- frontend/.prettierignore | 1 + frontend/package-lock.json | 12 --- frontend/package.json | 4 +- frontend/postcss.config.js | 10 +-- frontend/rollup.config.js | 1 + frontend/src/lib/api/apiInstance.ts | 2 +- frontend/src/lib/api/sessions.ts | 4 +- frontend/src/lib/api/tests.ts | 1 + frontend/src/lib/api/users.ts | 1 + frontend/src/lib/components/header.svelte | 4 +- .../components/header/localSelector.svelte | 7 +- .../sessions/editParticipants.svelte | 2 +- .../lib/components/sessions/message.svelte | 1 + .../lib/components/sessions/writebox.svelte | 2 +- .../src/lib/components/surveys/gapfill.svelte | 3 +- frontend/src/lib/types/surveyQuestion.ts | 2 +- frontend/src/routes/+layout.svelte | 2 + frontend/src/routes/login/+page.svelte | 20 ++++- frontend/static/site.webmanifest | 12 ++- 25 files changed, 208 insertions(+), 136 deletions(-) create mode 100755 .githooks/pre-commit diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 00000000..05097f86 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,15 @@ +#!/bin/sh + +git stash -q --keep-index + +cd frontend +npm run format +npm run lint +cd .. + +black backend +black --check backend + +git stash pop -q + +exit 0 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6227ab74..0f8e3602 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,17 +1,30 @@ -default: - image: docker:latest - services: - - docker:dind - before_script: - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - stages: + - lint - build +lint_frontend: + stage: lint + image: node + script: + - cd frontend + - npm install + - npm run lint + +lint_backend: + stage: lint + image: registry.gitlab.com/pipeline-components/black:latest + script: + - black --check --verbose -- . + build: stage: build only: - main + image: docker:latest + services: + - docker:dind + before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY parallel: matrix: - COMPONENT: [frontend, backend] diff --git a/backend/app/database.py b/backend/app/database.py index 79b9f0f0..3536ec2a 100644 --- a/backend/app/database.py +++ b/backend/app/database.py @@ -17,4 +17,3 @@ def get_db(): yield db finally: db.close() - diff --git a/backend/app/hashing.py b/backend/app/hashing.py index 45969d83..76047147 100644 --- a/backend/app/hashing.py +++ b/backend/app/hashing.py @@ -15,18 +15,12 @@ import crud pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") -reuseable_oauth = OAuth2PasswordBearer( - tokenUrl="/login", - scheme_name="JWT" -) +reuseable_oauth = OAuth2PasswordBearer(tokenUrl="/login", scheme_name="JWT") -reuseable_refresh_oauth = OAuth2PasswordBearer( - tokenUrl="/refresh", - scheme_name="JWT" -) +reuseable_refresh_oauth = OAuth2PasswordBearer(tokenUrl="/refresh", scheme_name="JWT") -class Hasher(): +class Hasher: @staticmethod def verify_password(plain_password, hashed_password): return pwd_context.verify(plain_password, hashed_password) @@ -40,13 +34,22 @@ def create_access_token(user: models.User, expires_delta: int = -1) -> str: if expires_delta > 0: expires_delta = int(datetime.now(UTC).timestamp()) + expires_delta else: - expires_delta = int((datetime.now( - UTC) + timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES)).timestamp()) - - to_encode = {"exp": expires_delta, "sub": str( - user.id), "type": user.type, "email": user.email, "nickname": user.nickname, "is_active": user.is_active} - encoded_jwt = jwt.encode( - to_encode, config.JWT_SECRET_KEY, config.ALGORITHM) + expires_delta = int( + ( + datetime.now(UTC) + + timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES) + ).timestamp() + ) + + to_encode = { + "exp": expires_delta, + "sub": str(user.id), + "type": user.type, + "email": user.email, + "nickname": user.nickname, + "is_active": user.is_active, + } + encoded_jwt = jwt.encode(to_encode, config.JWT_SECRET_KEY, config.ALGORITHM) return encoded_jwt @@ -54,20 +57,30 @@ def create_refresh_token(user: models.User, expires_delta: int = -1) -> str: if expires_delta > 0: expires_delta = int(datetime.now(UTC).timestamp()) + expires_delta else: - expires_delta = int((datetime.now( - UTC) + timedelta(minutes=config.REFRESH_TOKEN_EXPIRE_MINUTES)).timestamp()) - - to_encode = {"exp": expires_delta, "sub": str( - user.id), "type": user.type, "email": user.email, "nickname": user.nickname, "is_active": user.is_active} - encoded_jwt = jwt.encode( - to_encode, config.JWT_REFRESH_SECRET_KEY, config.ALGORITHM) + expires_delta = int( + ( + datetime.now(UTC) + + timedelta(minutes=config.REFRESH_TOKEN_EXPIRE_MINUTES) + ).timestamp() + ) + + to_encode = { + "exp": expires_delta, + "sub": str(user.id), + "type": user.type, + "email": user.email, + "nickname": user.nickname, + "is_active": user.is_active, + } + encoded_jwt = jwt.encode(to_encode, config.JWT_REFRESH_SECRET_KEY, config.ALGORITHM) return encoded_jwt def get_jwt_user(token: str = Depends(reuseable_oauth), db: Session = Depends(get_db)): try: - payload = jwt.decode(token, config.JWT_SECRET_KEY, - algorithms=[config.ALGORITHM]) + payload = jwt.decode( + token, config.JWT_SECRET_KEY, algorithms=[config.ALGORITHM] + ) token_data = schemas.TokenPayload(**payload) if token_data.exp is None or token_data.sub is None: @@ -81,12 +94,19 @@ def get_jwt_user(token: str = Depends(reuseable_oauth), db: Session = Depends(ge except jwte.ExpiredSignatureError: raise HTTPException(status_code=401, detail="Token has expired") - except (jwte.JWTError, jwte.ExpiredSignatureError, ValidationError, ValueError) as e: + except ( + jwte.JWTError, + jwte.ExpiredSignatureError, + ValidationError, + ValueError, + ) as e: print(e) raise HTTPException(status_code=403, detail="Invalid token") return db_user -def get_jwt_user_from_refresh_token(token: str = Depends(reuseable_refresh_oauth), db: Session = Depends(get_db)): +def get_jwt_user_from_refresh_token( + token: str = Depends(reuseable_refresh_oauth), db: Session = Depends(get_db) +): return get_jwt_user(token, db) diff --git a/backend/app/main.py b/backend/app/main.py index 5dd053f1..0071d391 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -121,7 +121,12 @@ def register( if db_user: raise HTTPException(status_code=400, detail="User already registered") - user_data = schemas.UserCreate(email=email, password=password, nickname=nickname, type=models.UserType.TUTOR.value if tutor else models.UserType.STUDENT.value) + user_data = schemas.UserCreate( + email=email, + password=password, + nickname=nickname, + type=models.UserType.TUTOR.value if tutor else models.UserType.STUDENT.value, + ) user = crud.create_user(db=db, user=user_data) @@ -399,32 +404,38 @@ def create_weekly_survey( db_user = crud.get_user(db, user_id) if db_user is None: raise HTTPException(status_code=404, detail="User not found") - + return crud.create_user_survey_weekly(db, user_id, survey).id -@usersRouter.post('/{user_id}/contacts/{contact_id}/bookings', status_code=status.HTTP_201_CREATED) + +@usersRouter.post( + "/{user_id}/contacts/{contact_id}/bookings", status_code=status.HTTP_201_CREATED +) def create_booking( - user_id: int, - contact_id: int, - booking: schemas.SessionBookingCreate, - db: Session = Depends(get_db), - current_user: schemas.User = Depends(get_jwt_user), - ): - if ( - not check_user_level(current_user, models.UserType.ADMIN) - and current_user.id != user_id - ): - raise HTTPException( - status_code=401, - detail="You do not have permission to create a booking for this user", - ) - db_user = crud.get_user(db, user_id) - if db_user is None: - raise HTTPException(status_code=404, detail="User not found") - db_contact = crud.get_user(db, contact_id) - if db_contact is None: - raise HTTPException(status_code=404, detail="Contact not found") - return crud.create_session_with_users(db, [db_user, db_contact], booking.start_time, booking.end_time).id + user_id: int, + contact_id: int, + booking: schemas.SessionBookingCreate, + db: Session = Depends(get_db), + current_user: schemas.User = Depends(get_jwt_user), +): + if ( + not check_user_level(current_user, models.UserType.ADMIN) + and current_user.id != user_id + ): + raise HTTPException( + status_code=401, + detail="You do not have permission to create a booking for this user", + ) + db_user = crud.get_user(db, user_id) + if db_user is None: + raise HTTPException(status_code=404, detail="User not found") + db_contact = crud.get_user(db, contact_id) + if db_contact is None: + raise HTTPException(status_code=404, detail="Contact not found") + return crud.create_session_with_users( + db, [db_user, db_contact], booking.start_time, booking.end_time + ).id + @sessionsRouter.post("", response_model=schemas.Session) def create_session( @@ -495,6 +506,7 @@ def update_session( crud.update_session(db, session, session_id) + @sessionsRouter.get("/{session_id}/download/messages") def download_session( session_id: int, @@ -507,7 +519,8 @@ def download_session( if not check_user_level(current_user, models.UserType.ADMIN): raise HTTPException( - status_code=401, detail="You do not have permission to download this session" + status_code=401, + detail="You do not have permission to download this session", ) data = crud.get_messages(db, session_id) @@ -521,7 +534,13 @@ def download_session( output.seek(0) - return StreamingResponse(output, media_type="text/csv", headers={"Content-Disposition": f"attachment; filename={session_id}-messages.csv"}) + return StreamingResponse( + output, + media_type="text/csv", + headers={ + "Content-Disposition": f"attachment; filename={session_id}-messages.csv" + }, + ) @sessionsRouter.post( @@ -792,6 +811,7 @@ def propagate_presence( return + @studyRouter.post("/", status_code=status.HTTP_201_CREATED) def study_create( study: schemas.StudyCreate, @@ -804,6 +824,7 @@ def study_create( ) return crud.create_study(db, study).id + @websocketRouter.websocket("/sessions/{session_id}") async def websocket_session( session_id: int, @@ -1154,6 +1175,7 @@ def get_survey_responses( return crud.get_survey_responses(db, survey_id) + v1Router.include_router(authRouter) v1Router.include_router(usersRouter) v1Router.include_router(sessionsRouter) diff --git a/backend/app/test_main.py b/backend/app/test_main.py index 90ac9fab..dc5a19d6 100644 --- a/backend/app/test_main.py +++ b/backend/app/test_main.py @@ -15,9 +15,7 @@ def test_read_main(): def test_webhook_create(): response = client.post( "/api/v1/webhooks/sessions", - headers={ - "X-Cal-Signature-256": config.CALCOM_SECRET - }, + headers={"X-Cal-Signature-256": config.CALCOM_SECRET}, json={ "triggerEvent": "BOOKING_CREATED", "createdAt": "2023-05-24T09:30:00.538Z", @@ -27,44 +25,34 @@ def test_webhook_create(): "description": "", "additionalNotes": "", "customInputs": {}, - "startTime": (datetime.datetime.now() + datetime.timedelta(days=1, hours=1)).isoformat(), - "endTime": (datetime.datetime.now() + datetime.timedelta(days=1, hours=2)).isoformat(), + "startTime": ( + datetime.datetime.now() + datetime.timedelta(days=1, hours=1) + ).isoformat(), + "endTime": ( + datetime.datetime.now() + datetime.timedelta(days=1, hours=2) + ).isoformat(), "organizer": { "id": 5, "name": "Pro Example", "email": "pro@example.com", "username": "pro", "timeZone": "Asia/Kolkata", - "language": { - "locale": "en" - }, - "timeFormat": "h:mma" + "language": {"locale": "en"}, + "timeFormat": "h:mma", }, "responses": { - "name": { - "label": "your_name", - "value": "John Doe" - }, + "name": {"label": "your_name", "value": "John Doe"}, "email": { "label": "email_address", - "value": "john.doe@example.com" + "value": "john.doe@example.com", }, "location": { "label": "location", - "value": { - "optionValue": "", - "value": "inPerson" - } - }, - "notes": { - "label": "additional_notes" + "value": {"optionValue": "", "value": "inPerson"}, }, - "guests": { - "label": "additional_guests" - }, - "rescheduleReason": { - "label": "reschedule_reason" - } + "notes": {"label": "additional_notes"}, + "guests": {"label": "additional_guests"}, + "rescheduleReason": {"label": "reschedule_reason"}, }, "userFieldsResponses": {}, "attendees": [ @@ -72,9 +60,7 @@ def test_webhook_create(): "email": "admin@admin.tld", "name": "John Doe", "timeZone": "Asia/Kolkata", - "language": { - "locale": "en" - } + "language": {"locale": "en"}, } ], "location": "Calcom HQ", @@ -84,7 +70,7 @@ def test_webhook_create(): "externalId": "https://caldav.icloud.com/1234567/calendars/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/", "userId": 5, "eventTypeId": None, - "credentialId": 1 + "credentialId": 1, }, "hideCalendarNotes": False, "requiresConfirmation": None, @@ -99,7 +85,7 @@ def test_webhook_create(): "success": 1, "failures": 0, "errors": [], - "warnings": [] + "warnings": [], } ], "eventTitle": "60min", @@ -109,10 +95,12 @@ def test_webhook_create(): "length": 60, "bookingId": 91, "metadata": {}, - "status": "ACCEPTED" - } - } + "status": "ACCEPTED", + }, + }, ) - assert response.status_code == 202, (response.status_code, - response.content.decode("utf-8")) + assert response.status_code == 202, ( + response.status_code, + response.content.decode("utf-8"), + ) diff --git a/frontend/.prettierignore b/frontend/.prettierignore index cc41cea9..5c95eabf 100644 --- a/frontend/.prettierignore +++ b/frontend/.prettierignore @@ -2,3 +2,4 @@ pnpm-lock.yaml package-lock.json yarn.lock +static/ diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 10e0d526..eea21621 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -2428,18 +2428,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", diff --git a/frontend/package.json b/frontend/package.json index d51f1c91..db37ad4f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -7,8 +7,8 @@ "build": "vite build", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "prettier --check . && eslint .", - "format": "prettier --write ." + "lint": "prettier --check .", + "format": "prettier --write . --log-level warn" }, "devDependencies": { "@rollup/plugin-json": "^6.1.0", diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js index 2e7af2b7..0f772168 100644 --- a/frontend/postcss.config.js +++ b/frontend/postcss.config.js @@ -1,6 +1,6 @@ export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +}; diff --git a/frontend/rollup.config.js b/frontend/rollup.config.js index 983b1302..4c0caa2b 100644 --- a/frontend/rollup.config.js +++ b/frontend/rollup.config.js @@ -1,4 +1,5 @@ import json from '@rollup/plugin-json'; +import svelte from 'rollup-plugin-svelte'; export default { plugins: [json(), svelte({})] diff --git a/frontend/src/lib/api/apiInstance.ts b/frontend/src/lib/api/apiInstance.ts index 50c4f346..2053a846 100644 --- a/frontend/src/lib/api/apiInstance.ts +++ b/frontend/src/lib/api/apiInstance.ts @@ -2,7 +2,7 @@ import axios from 'axios'; import config from '$lib/config'; import { writable, get } from 'svelte/store'; -export let access_cookie = writable(''); +export const access_cookie = writable(''); export const axiosPublicInstance = axios.create({ ...axios.defaults, diff --git a/frontend/src/lib/api/sessions.ts b/frontend/src/lib/api/sessions.ts index 31e47b1f..00078a5d 100644 --- a/frontend/src/lib/api/sessions.ts +++ b/frontend/src/lib/api/sessions.ts @@ -45,7 +45,7 @@ export async function createMessageAPI( id: number, content: string, metadata: { message: string; date: number }[] -): Promise<any | null> { +): Promise<number | null> { const response = await axiosInstance.post(`/sessions/${id}/messages`, { content, metadata }); if (response.status !== 201) { @@ -61,7 +61,7 @@ export async function updateMessageAPI( message_id: string, content: string, metadata: { message: string; date: number }[] -): Promise<any | null> { +): Promise<number | null> { const response = await axiosInstance.post(`/sessions/${id}/messages`, { message_id, content, diff --git a/frontend/src/lib/api/tests.ts b/frontend/src/lib/api/tests.ts index 043e832e..f95de8df 100644 --- a/frontend/src/lib/api/tests.ts +++ b/frontend/src/lib/api/tests.ts @@ -1,5 +1,6 @@ import { axiosInstance } from './apiInstance'; +// eslint-disable-next-line @typescript-eslint/no-explicit-any export async function sendTestVocabularyAPI(data: any): Promise<boolean> { const response = await axiosInstance.post(`/tests/vocabulary`, { content: data }); diff --git a/frontend/src/lib/api/users.ts b/frontend/src/lib/api/users.ts index b5d3ced3..0d6a1bbc 100644 --- a/frontend/src/lib/api/users.ts +++ b/frontend/src/lib/api/users.ts @@ -113,6 +113,7 @@ export async function createUserAPI( return response.data; } +// eslint-disable-next-line @typescript-eslint/no-explicit-any export async function patchUserAPI(user_id: number, data: any): Promise<boolean> { try { const response = await axiosInstance.patch(`/users/${user_id}`, data); diff --git a/frontend/src/lib/components/header.svelte b/frontend/src/lib/components/header.svelte index 3f320e1f..6f8db00f 100644 --- a/frontend/src/lib/components/header.svelte +++ b/frontend/src/lib/components/header.svelte @@ -31,7 +31,7 @@ <Icon src={Bars3} class="h-5 w-5" /> </div> <ul - tabindex="0" + tabindex="-1" class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow bg-base-100 rounded-box w-52" > {#if $user} @@ -46,7 +46,7 @@ <li><a href="/">Item 3</a></li> {/if} <li> - <a>{$t('header.language')}</a> + <span>{$t('header.language')}</span> <ul class="p-2"> <LocalSelector /> </ul> diff --git a/frontend/src/lib/components/header/localSelector.svelte b/frontend/src/lib/components/header/localSelector.svelte index e0873d08..ed5fe0cf 100644 --- a/frontend/src/lib/components/header/localSelector.svelte +++ b/frontend/src/lib/components/header/localSelector.svelte @@ -1,10 +1,7 @@ <script lang="ts"> - import { locale, locales, t } from '$lib/services/i18n'; + import { locale, locales } from '$lib/services/i18n'; import { get } from 'svelte/store'; - let classes = ''; - export { classes as class }; - function onChange(value: string) { if (value !== get(locale)) { // TODO: Should be in place @@ -18,4 +15,4 @@ {#each $locales as name (name)} <li><button on:click={() => onChange(name)}>{name}</button></li> {/each} -<!-- </ul> --> \ No newline at end of file +<!-- </ul> --> diff --git a/frontend/src/lib/components/sessions/editParticipants.svelte b/frontend/src/lib/components/sessions/editParticipants.svelte index 8d561f27..e8776f1d 100644 --- a/frontend/src/lib/components/sessions/editParticipants.svelte +++ b/frontend/src/lib/components/sessions/editParticipants.svelte @@ -5,7 +5,7 @@ import Select from 'svelte-select'; import { get } from 'svelte/store'; import { onMount } from 'svelte'; - import { Icon, Language, XMark } from 'svelte-hero-icons'; + import { Icon, XMark } from 'svelte-hero-icons'; import { t } from '$lib/services/i18n'; import config from '$lib/config'; diff --git a/frontend/src/lib/components/sessions/message.svelte b/frontend/src/lib/components/sessions/message.svelte index 51708dc8..1e6c6e94 100644 --- a/frontend/src/lib/components/sessions/message.svelte +++ b/frontend/src/lib/components/sessions/message.svelte @@ -195,6 +195,7 @@ > {/if} {:else} + <!-- eslint-disable-next-line svelte/no-at-html-tags --> {@html linkifyHtml(sanitize(part.text), { className: 'underline', target: '_blank' })} {/if} {/each} diff --git a/frontend/src/lib/components/sessions/writebox.svelte b/frontend/src/lib/components/sessions/writebox.svelte index 40613786..280fbf12 100644 --- a/frontend/src/lib/components/sessions/writebox.svelte +++ b/frontend/src/lib/components/sessions/writebox.svelte @@ -80,7 +80,7 @@ placeholder={disabled ? $t('chatbox.disabled') : $t('chatbox.placeholder')} {disabled} bind:value={message} - on:keypress={(e) => keyPress()} + on:keypress={() => keyPress()} on:keypress={async (e) => { if (e.key === 'Enter' && !e.shiftKey) { await sendMessage(); diff --git a/frontend/src/lib/components/surveys/gapfill.svelte b/frontend/src/lib/components/surveys/gapfill.svelte index be1cffaa..5dbe48ec 100644 --- a/frontend/src/lib/components/surveys/gapfill.svelte +++ b/frontend/src/lib/components/surveys/gapfill.svelte @@ -11,8 +11,7 @@ bind:value={content} on:input={(event) => onInput(event.target.value)} maxlength={length} - /><!-- - -->{#each Array.from({ length }) as _, i} + /><!-- -->{#each Array.from({ length }) as _, i} <label>{content[i] || '_'}</label> {/each} </span> diff --git a/frontend/src/lib/types/surveyQuestion.ts b/frontend/src/lib/types/surveyQuestion.ts index eb85c8ca..51e1e83d 100644 --- a/frontend/src/lib/types/surveyQuestion.ts +++ b/frontend/src/lib/types/surveyQuestion.ts @@ -35,7 +35,7 @@ export default class SurveyQuestion { return null; } - let options = []; + const options = []; if (data.option1) options.push(data.option1); if (data.option2) options.push(data.option2); if (data.option3) options.push(data.option3); diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index d83fe749..a7c90acd 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -8,6 +8,8 @@ export let data; User.parseFromServer(data); + + console.log(2); </script> <svelte:head> diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte index 3acabede..ea3e8952 100644 --- a/frontend/src/routes/login/+page.svelte +++ b/frontend/src/routes/login/+page.svelte @@ -23,7 +23,7 @@ } </script> -<div class="flex justify-center items-center h-screen"> +<div class="flex justify-center items-center h-screen"> <div class="flex flex-col w-full max-w-md rounded-box shadow-xl bg-base-200 gap-4 p-6"> <h1 class="text-3xl font-bold self-center">{$t('login.title')}</h1> @@ -53,7 +53,14 @@ <span class="label-text">{$t('login.email')}</span> </div> - <input type="text" id="email" name="email" class="input input-bordered" bind:value={email} required /> + <input + type="text" + id="email" + name="email" + class="input input-bordered" + bind:value={email} + required + /> </label> <label class="form-control"> @@ -63,7 +70,14 @@ <a class="label-text link link-secondary">{$t('login.forgotPassword')}</a> --> </div> - <input type="password" id="password" name="password" class="input input-bordered" bind:value={password} required /> + <input + type="password" + id="password" + name="password" + class="input input-bordered" + bind:value={password} + required + /> </label> <!-- <div class="form-control"> diff --git a/frontend/static/site.webmanifest b/frontend/static/site.webmanifest index 45dc8a20..52a2fe3f 100755 --- a/frontend/static/site.webmanifest +++ b/frontend/static/site.webmanifest @@ -1 +1,11 @@ -{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file +{ + "name": "", + "short_name": "", + "icons": [ + { "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, + { "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} -- GitLab