From 3fa3622cb745aa9263f9ce4b69e7d4ab6c395be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Fri, 3 Nov 2023 23:12:48 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9D=8C=20rmove=20cr,=20keep=20lf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/requirements.txt | 38 ++++++++++++++-------------- frontend/postcss.config.js | 12 ++++----- frontend/public/appointment_logo.svg | 20 +++++++-------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index 8c4b4fd5..245af1f1 100755 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,19 +1,19 @@ -alembic==1.9.3 -auth0-python==4.0.0 -caldav==1.0.1 -cryptography==39.0.1 -fastapi-auth0==0.3.2 -fastapi==0.91.0 -google-api-python-client==2.85.0 -google-auth-httplib2==0.1.0 -google-auth-oauthlib==1.0.0 -jinja2==3.1.2 -icalendar==5.0.4 -mysqlclient==2.1.1 -mysql-connector-python==8.0.32 -python-dotenv==1.0.0 -sentry-sdk==1.26.0 -sqlalchemy-utils==0.39.0 -sqlalchemy==1.4.40 -uvicorn==0.20.0 -validators==0.20.0 +alembic==1.9.3 +auth0-python==4.0.0 +caldav==1.0.1 +cryptography==39.0.1 +fastapi-auth0==0.3.2 +fastapi==0.91.0 +google-api-python-client==2.85.0 +google-auth-httplib2==0.1.0 +google-auth-oauthlib==1.0.0 +jinja2==3.1.2 +icalendar==5.0.4 +mysqlclient==2.1.1 +mysql-connector-python==8.0.32 +python-dotenv==1.0.0 +sentry-sdk==1.26.0 +sqlalchemy-utils==0.39.0 +sqlalchemy==1.4.40 +uvicorn==0.20.0 +validators==0.20.0 diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js index 485780a6..f1c8dac8 100644 --- a/frontend/postcss.config.js +++ b/frontend/postcss.config.js @@ -1,6 +1,6 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - } -} +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + } +} diff --git a/frontend/public/appointment_logo.svg b/frontend/public/appointment_logo.svg index b073221f..624d1fbb 100644 --- a/frontend/public/appointment_logo.svg +++ b/frontend/public/appointment_logo.svg @@ -1,10 +1,10 @@ - - - - - - - - - - + + + + + + + + + + From 809bce1ddffc1414942dc555e6448845b5c50b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Fri, 3 Nov 2023 23:18:37 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9D=8C=20remove=20cr,=20keep=20lf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .aws/task-definition.json | 332 +++++++-------- .editorconfig | 30 +- .github/ISSUE_TEMPLATE/bug_report.md | 62 +-- .github/ISSUE_TEMPLATE/config.yml | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 36 +- .github/PULL_REQUEST_TEMPLATE.md | 32 +- .github/workflows/aws.yml | 198 ++++----- README.md | 0 backend/.env.example | 148 +++---- backend/Dockerfile | 44 +- backend/requirements.txt | 0 backend/scripts/dev-entry.sh | 0 backend/scripts/entry.sh | 0 backend/src/appointment/main.py | 0 .../templates/email/confirm.jinja2 | 76 ++-- .../appointment/templates/email/invite.jinja2 | 8 +- backend/src/appointment/tmp/.gitignore | 2 +- frontend/.env.example | 36 +- frontend/.env.staging.example | 18 +- frontend/.eslintignore | 6 +- frontend/.eslintrc.js | 68 +-- frontend/.gitignore | 48 +-- frontend/Dockerfile | 24 +- frontend/README.md | 0 .../docker/etc/nginx/conf.d/appointments.conf | 86 ++-- frontend/jsconfig.json | 0 frontend/package.json | 0 frontend/public/index.html | 0 frontend/src/App.vue | 0 frontend/src/assets/fonts/Apache License.txt | 400 +++++++++--------- frontend/src/assets/main.css | 196 ++++----- frontend/src/definitions.js | 0 frontend/src/main.js | 0 frontend/src/router.js | 0 frontend/src/utils.js | 0 frontend/src/views/AppointmentsView.vue | 0 frontend/src/views/CalendarView.vue | 0 frontend/src/views/ProfileView.vue | 0 frontend/src/views/SettingsView.vue | 0 frontend/vue.config.js | 0 frontend/yarn.lock | 0 41 files changed, 926 insertions(+), 926 deletions(-) mode change 100755 => 100644 README.md mode change 100755 => 100644 backend/requirements.txt mode change 100755 => 100644 backend/scripts/dev-entry.sh mode change 100755 => 100644 backend/scripts/entry.sh mode change 100755 => 100644 backend/src/appointment/main.py mode change 100755 => 100644 frontend/.gitignore mode change 100755 => 100644 frontend/README.md mode change 100755 => 100644 frontend/jsconfig.json mode change 100755 => 100644 frontend/package.json mode change 100755 => 100644 frontend/public/index.html mode change 100755 => 100644 frontend/src/App.vue mode change 100755 => 100644 frontend/src/definitions.js mode change 100755 => 100644 frontend/src/main.js mode change 100755 => 100644 frontend/src/router.js mode change 100755 => 100644 frontend/src/utils.js mode change 100755 => 100644 frontend/src/views/AppointmentsView.vue mode change 100755 => 100644 frontend/src/views/CalendarView.vue mode change 100755 => 100644 frontend/src/views/ProfileView.vue mode change 100755 => 100644 frontend/src/views/SettingsView.vue mode change 100755 => 100644 frontend/vue.config.js mode change 100755 => 100644 frontend/yarn.lock diff --git a/.aws/task-definition.json b/.aws/task-definition.json index fab0b6f2..2cc01962 100644 --- a/.aws/task-definition.json +++ b/.aws/task-definition.json @@ -1,167 +1,167 @@ -{ - "taskDefinitionArn": "arn:aws:ecs:us-east-1:768512802988:task-definition/appointments-definition:24", - "containerDefinitions": [ - { - "name": "backend", - "image": "backend-latest", - "cpu": 0, - "portMappings": [ - { - "name": "backend-5000-tcp", - "containerPort": 5000, - "hostPort": 5000, - "protocol": "tcp", - "appProtocol": "http" - } - ], - "essential": true, - "environment": [ - { - "name": "FRONTEND_URL", - "value": "https://stage.appointment.day" - }, - { - "name": "SHORT_BASE_URL", - "value": "https://stage.apmt.day" - }, - { - "name": "TIER_BASIC_CALENDAR_LIMIT", - "value": "3" - }, - { - "name": "TIER_PLUS_CALENDAR_LIMIT", - "value": "5" - }, - { - "name": "TIER_PRO_CALENDAR_LIMIT", - "value": "10" - }, - { - "name": "LOG_USE_STREAM", - "value": "True" - }, - { - "name": "LOG_LEVEL", - "value": "INFO" - }, - { - "name": "APP_ENV", - "value": "stage" - }, - { - "name": "SENTRY_DSN", - "value": "https://5dddca3ecc964284bb8008bc2beef808@o4505428107853824.ingest.sentry.io/4505428124827648" - } - ], - "secrets": [ - { - "name": "DATABASE_SECRETS", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/db-mysql-Ixf6qD" - }, - { - "name": "AUTH0_SECRETS", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/auth0-0gzF6d" - }, - { - "name": "DB_ENC_SECRET", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/db-secret-CYKglI" - }, - { - "name": "SMTP_SECRETS", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/socketlabs-UYmjaC" - }, - { - "name": "GOOGLE_OAUTH_SECRETS", - "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/google-cal-oauth-VevaSo" - } - ], - "mountPoints": [], - "volumesFrom": [], - "logConfiguration": { - "logDriver": "awslogs", - "options": { - "awslogs-create-group": "true", - "awslogs-group": "/ecs/appointments-definition", - "awslogs-region": "us-east-1", - "awslogs-stream-prefix": "ecs" - } - } - }, - { - "name": "frontend", - "image": "frontend-latest", - "cpu": 0, - "portMappings": [ - { - "name": "frontend-80-tcp", - "containerPort": 80, - "hostPort": 80, - "protocol": "tcp", - "appProtocol": "http" - } - ], - "essential": true, - "environment": [], - "mountPoints": [], - "volumesFrom": [], - "logConfiguration": { - "logDriver": "awslogs", - "options": { - "awslogs-create-group": "true", - "awslogs-group": "/ecs/appointments-definition", - "awslogs-region": "us-east-1", - "awslogs-stream-prefix": "ecs" - } - } - } - ], - "family": "appointments-definition", - "executionRoleArn": "arn:aws:iam::768512802988:role/apointments-ci-role", - "networkMode": "awsvpc", - "revision": 24, - "volumes": [], - "status": "ACTIVE", - "requiresAttributes": [ - { - "name": "com.amazonaws.ecs.capability.logging-driver.awslogs" - }, - { - "name": "ecs.capability.execution-role-awslogs" - }, - { - "name": "com.amazonaws.ecs.capability.ecr-auth" - }, - { - "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19" - }, - { - "name": "ecs.capability.execution-role-ecr-pull" - }, - { - "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18" - }, - { - "name": "ecs.capability.task-eni" - }, - { - "name": "com.amazonaws.ecs.capability.docker-remote-api.1.29" - } - ], - "placementConstraints": [], - "compatibilities": [ - "EC2", - "FARGATE" - ], - "requiresCompatibilities": [ - "FARGATE" - ], - "cpu": "512", - "memory": "1024", - "runtimePlatform": { - "cpuArchitecture": "X86_64", - "operatingSystemFamily": "LINUX" - }, - "registeredAt": "2023-03-15T22:19:59.642Z", - "registeredBy": "arn:aws:iam::768512802988:user/melissa", - "tags": [] +{ + "taskDefinitionArn": "arn:aws:ecs:us-east-1:768512802988:task-definition/appointments-definition:24", + "containerDefinitions": [ + { + "name": "backend", + "image": "backend-latest", + "cpu": 0, + "portMappings": [ + { + "name": "backend-5000-tcp", + "containerPort": 5000, + "hostPort": 5000, + "protocol": "tcp", + "appProtocol": "http" + } + ], + "essential": true, + "environment": [ + { + "name": "FRONTEND_URL", + "value": "https://stage.appointment.day" + }, + { + "name": "SHORT_BASE_URL", + "value": "https://stage.apmt.day" + }, + { + "name": "TIER_BASIC_CALENDAR_LIMIT", + "value": "3" + }, + { + "name": "TIER_PLUS_CALENDAR_LIMIT", + "value": "5" + }, + { + "name": "TIER_PRO_CALENDAR_LIMIT", + "value": "10" + }, + { + "name": "LOG_USE_STREAM", + "value": "True" + }, + { + "name": "LOG_LEVEL", + "value": "INFO" + }, + { + "name": "APP_ENV", + "value": "stage" + }, + { + "name": "SENTRY_DSN", + "value": "https://5dddca3ecc964284bb8008bc2beef808@o4505428107853824.ingest.sentry.io/4505428124827648" + } + ], + "secrets": [ + { + "name": "DATABASE_SECRETS", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/db-mysql-Ixf6qD" + }, + { + "name": "AUTH0_SECRETS", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/auth0-0gzF6d" + }, + { + "name": "DB_ENC_SECRET", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/db-secret-CYKglI" + }, + { + "name": "SMTP_SECRETS", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/socketlabs-UYmjaC" + }, + { + "name": "GOOGLE_OAUTH_SECRETS", + "valueFrom": "arn:aws:secretsmanager:us-east-1:768512802988:secret:staging/appointment/google-cal-oauth-VevaSo" + } + ], + "mountPoints": [], + "volumesFrom": [], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/appointments-definition", + "awslogs-region": "us-east-1", + "awslogs-stream-prefix": "ecs" + } + } + }, + { + "name": "frontend", + "image": "frontend-latest", + "cpu": 0, + "portMappings": [ + { + "name": "frontend-80-tcp", + "containerPort": 80, + "hostPort": 80, + "protocol": "tcp", + "appProtocol": "http" + } + ], + "essential": true, + "environment": [], + "mountPoints": [], + "volumesFrom": [], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/appointments-definition", + "awslogs-region": "us-east-1", + "awslogs-stream-prefix": "ecs" + } + } + } + ], + "family": "appointments-definition", + "executionRoleArn": "arn:aws:iam::768512802988:role/apointments-ci-role", + "networkMode": "awsvpc", + "revision": 24, + "volumes": [], + "status": "ACTIVE", + "requiresAttributes": [ + { + "name": "com.amazonaws.ecs.capability.logging-driver.awslogs" + }, + { + "name": "ecs.capability.execution-role-awslogs" + }, + { + "name": "com.amazonaws.ecs.capability.ecr-auth" + }, + { + "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19" + }, + { + "name": "ecs.capability.execution-role-ecr-pull" + }, + { + "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18" + }, + { + "name": "ecs.capability.task-eni" + }, + { + "name": "com.amazonaws.ecs.capability.docker-remote-api.1.29" + } + ], + "placementConstraints": [], + "compatibilities": [ + "EC2", + "FARGATE" + ], + "requiresCompatibilities": [ + "FARGATE" + ], + "cpu": "512", + "memory": "1024", + "runtimePlatform": { + "cpuArchitecture": "X86_64", + "operatingSystemFamily": "LINUX" + }, + "registeredAt": "2023-03-15T22:19:59.642Z", + "registeredBy": "arn:aws:iam::768512802988:user/melissa", + "tags": [] } \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index a3dff5a5..8e378874 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,15 +1,15 @@ -root = true - -[*] -end_of_line = lf -insert_final_newline = true - -[*.py] -charset = utf-8 -indent_style = space -indent_size = 4 - -[*.{vue,html,css,js,json,yml}] -charset = utf-8 -indent_style = space -indent_size = 2 +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +[*.py] +charset = utf-8 +indent_style = space +indent_size = 4 + +[*.{vue,html,css,js,json,yml}] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index ca08eaa4..96c7e601 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,31 +1,31 @@ ---- -name: Bug report -labels: bug -about: Create a report to help us improve - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: - -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**System (please complete the following information):** - -- OS: [e.g. Windows 10] -- Browser Version [e.g. Firefox 114.0b8 (64-Bit)] - -**Additional context** -Add any other context about the problem here. +--- +name: Bug report +labels: bug +about: Create a report to help us improve + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**System (please complete the following information):** + +- OS: [e.g. Windows 10] +- Browser Version [e.g. Firefox 114.0b8 (64-Bit)] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 3ba13e0c..ac2e8b47 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1 +1 @@ -blank_issues_enabled: false +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index d3b8683a..cfedea62 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,18 +1,18 @@ ---- -name: Feature request -labels: enhancement -about: Suggest an idea for this project - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. +--- +name: Feature request +labels: enhancement +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7ddc6c56..d0c67874 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,16 +1,16 @@ - - -## Description of the Change - - - -## Benefits - - - -## Applicable Issues - - + + +## Description of the Change + + + +## Benefits + + + +## Applicable Issues + + diff --git a/.github/workflows/aws.yml b/.github/workflows/aws.yml index 28a11ead..61582104 100644 --- a/.github/workflows/aws.yml +++ b/.github/workflows/aws.yml @@ -1,99 +1,99 @@ -# This workflow will build and push a new container image to Amazon ECR, -# and then will deploy a new task definition to Amazon ECS, when there is a push to the "staging" branch. - -name: Deploy to Stage Environment - -# Stop any pending jobs -concurrency: - group: staging - cancel-in-progress: true - -on: - push: - branches: [ "stage" ] - -env: - AWS_REGION: us-east-1 - ECR_REPOSITORY: appointments - ECS_SERVICE: appointments-service - ECS_CLUSTER: appointments - ECS_TASK_DEFINITION: .aws/task-definition.json - - CONTAINER_FRONTEND: frontend - CONTAINER_BACKEND: backend - -permissions: - contents: read - -jobs: - deploy: - name: Build & Deploy - runs-on: ubuntu-latest - environment: - name: staging - url: https://stage.appointment.day - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ env.AWS_REGION }} - - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v1 - - - name: Build, tag, and push backend to Amazon ECR - id: build-backend - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - IMAGE_TAG: backend-${{ github.sha }} - run: | - # Build a docker container and - # push it to ECR so that it can - # be deployed to ECS. - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./backend -f ./backend/deploy.dockerfile - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - echo "image_backend=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT - - - name: Build, tag, and push frontend to Amazon ECR - id: build-frontend - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - IMAGE_TAG: frontend-${{ github.sha }} - run: | - # Build a docker container and - # push it to ECR so that it can - # be deployed to ECS. - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./frontend -f ./frontend/deploy.dockerfile - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - echo "image_frontend=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT - - - name: Fill in the new backend image ID in the Amazon ECS task definition - id: task-def-backend - uses: aws-actions/amazon-ecs-render-task-definition@v1 - with: - task-definition: ${{ env.ECS_TASK_DEFINITION }} - container-name: ${{ env.CONTAINER_BACKEND }} - image: ${{ steps.build-backend.outputs.image_backend }} - - - name: Fill in the new frontend image ID in the Amazon ECS task definition - id: task-def-frontend - uses: aws-actions/amazon-ecs-render-task-definition@v1 - with: - task-definition: ${{ steps.task-def-backend.outputs.task-definition }} - container-name: ${{ env.CONTAINER_FRONTEND }} - image: ${{ steps.build-frontend.outputs.image_frontend }} - - - name: Deploy Amazon ECS task definition - uses: aws-actions/amazon-ecs-deploy-task-definition@v1 - with: - task-definition: ${{ steps.task-def-frontend.outputs.task-definition }} - service: ${{ env.ECS_SERVICE }} - cluster: ${{ env.ECS_CLUSTER }} - wait-for-service-stability: true +# This workflow will build and push a new container image to Amazon ECR, +# and then will deploy a new task definition to Amazon ECS, when there is a push to the "staging" branch. + +name: Deploy to Stage Environment + +# Stop any pending jobs +concurrency: + group: staging + cancel-in-progress: true + +on: + push: + branches: [ "stage" ] + +env: + AWS_REGION: us-east-1 + ECR_REPOSITORY: appointments + ECS_SERVICE: appointments-service + ECS_CLUSTER: appointments + ECS_TASK_DEFINITION: .aws/task-definition.json + + CONTAINER_FRONTEND: frontend + CONTAINER_BACKEND: backend + +permissions: + contents: read + +jobs: + deploy: + name: Build & Deploy + runs-on: ubuntu-latest + environment: + name: staging + url: https://stage.appointment.day + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build, tag, and push backend to Amazon ECR + id: build-backend + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: backend-${{ github.sha }} + run: | + # Build a docker container and + # push it to ECR so that it can + # be deployed to ECS. + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./backend -f ./backend/deploy.dockerfile + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + echo "image_backend=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT + + - name: Build, tag, and push frontend to Amazon ECR + id: build-frontend + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: frontend-${{ github.sha }} + run: | + # Build a docker container and + # push it to ECR so that it can + # be deployed to ECS. + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./frontend -f ./frontend/deploy.dockerfile + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + echo "image_frontend=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT + + - name: Fill in the new backend image ID in the Amazon ECS task definition + id: task-def-backend + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: ${{ env.ECS_TASK_DEFINITION }} + container-name: ${{ env.CONTAINER_BACKEND }} + image: ${{ steps.build-backend.outputs.image_backend }} + + - name: Fill in the new frontend image ID in the Amazon ECS task definition + id: task-def-frontend + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: ${{ steps.task-def-backend.outputs.task-definition }} + container-name: ${{ env.CONTAINER_FRONTEND }} + image: ${{ steps.build-frontend.outputs.image_frontend }} + + - name: Deploy Amazon ECS task definition + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: ${{ steps.task-def-frontend.outputs.task-definition }} + service: ${{ env.ECS_SERVICE }} + cluster: ${{ env.ECS_CLUSTER }} + wait-for-service-stability: true diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/backend/.env.example b/backend/.env.example index 0c2ed570..2e009756 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -1,74 +1,74 @@ -# Appointment backend configuration. - -# -- GENERAL -- -# Logging level: DEBUG|INFO|WARNING|ERROR|CRITICAL -LOG_LEVEL=ERROR -LOG_USE_STREAM=1 - -# -- FRONTEND -- -FRONTEND_URL=http://localhost:8080 -# Leave blank for no short url -SHORT_BASE_URL= - -# -- DATABASE -- -DATABASE_URL= -DATABASE_SECRETS= -# Secret phrase for database encryption (e.g. create it by running `openssl rand -hex 32`) -DB_SECRET= - -# -- AUTH0 -- -# Management API -AUTH0_API_CLIENT_ID= -AUTH0_API_SECRET= -# Auth API -AUTH0_API_DOMAIN= -AUTH0_API_AUDIENCE= -# Role keys, configurable in Auth0 User Management -> Roles -AUTH0_API_ROLE_ADMIN= -AUTH0_API_ROLE_BASIC= -AUTH0_API_ROLE_PLUS= -AUTH0_API_ROLE_PRO= - -# -- MAIL -- -# Connection security: SSL|STARTTLS|NONE -SMTP_SECURITY=SSL -# Address and port of the SMTP server -SMTP_URL= -SMTP_PORT= -# SMTP user credentials -SMTP_USER= -SMTP_PASS= -# Authorized email address for sending emails -SMTP_SENDER= - -# -- TIERS -- -# Max number of calendars to be simultanously connected for members of the basic tier -TIER_BASIC_CALENDAR_LIMIT=3 -# Max number of calendars to be simultanously connected for members of the plus tier -TIER_PLUS_CALENDAR_LIMIT=5 -# Max number of calendars to be simultanously connected for members of the pro tier -TIER_PRO_CALENDAR_LIMIT=10 - -# -- GOOGLE AUTH -- -GOOGLE_AUTH_CLIENT_ID= -GOOGLE_AUTH_SECRET= -GOOGLE_AUTH_PROJECT_ID= -GOOGLE_AUTH_CALLBACK=http://localhost:5000/google/callback - -# -- SIGNED URL SECRET -- -# Shared secret for url signing (e.g. create it by running `openssl rand -hex 32`) -SIGNED_SECRET= -# If empty, sentry will be disabled -SENTRY_DSN= -# Possible values: prod, dev -APP_ENV=dev - -# -- TESTING -- -AUTH0_TEST_USER= -AUTH0_TEST_PASS= -CALDAV_TEST_PRINCIPAL_URL= -CALDAV_TEST_CALENDAR_URL= -CALDAV_TEST_USER= -CALDAV_TEST_PASS= -GOOGLE_TEST_USER= -GOOGLE_TEST_PASS= +# Appointment backend configuration. + +# -- GENERAL -- +# Logging level: DEBUG|INFO|WARNING|ERROR|CRITICAL +LOG_LEVEL=ERROR +LOG_USE_STREAM=1 + +# -- FRONTEND -- +FRONTEND_URL=http://localhost:8080 +# Leave blank for no short url +SHORT_BASE_URL= + +# -- DATABASE -- +DATABASE_URL= +DATABASE_SECRETS= +# Secret phrase for database encryption (e.g. create it by running `openssl rand -hex 32`) +DB_SECRET= + +# -- AUTH0 -- +# Management API +AUTH0_API_CLIENT_ID= +AUTH0_API_SECRET= +# Auth API +AUTH0_API_DOMAIN= +AUTH0_API_AUDIENCE= +# Role keys, configurable in Auth0 User Management -> Roles +AUTH0_API_ROLE_ADMIN= +AUTH0_API_ROLE_BASIC= +AUTH0_API_ROLE_PLUS= +AUTH0_API_ROLE_PRO= + +# -- MAIL -- +# Connection security: SSL|STARTTLS|NONE +SMTP_SECURITY=SSL +# Address and port of the SMTP server +SMTP_URL= +SMTP_PORT= +# SMTP user credentials +SMTP_USER= +SMTP_PASS= +# Authorized email address for sending emails +SMTP_SENDER= + +# -- TIERS -- +# Max number of calendars to be simultanously connected for members of the basic tier +TIER_BASIC_CALENDAR_LIMIT=3 +# Max number of calendars to be simultanously connected for members of the plus tier +TIER_PLUS_CALENDAR_LIMIT=5 +# Max number of calendars to be simultanously connected for members of the pro tier +TIER_PRO_CALENDAR_LIMIT=10 + +# -- GOOGLE AUTH -- +GOOGLE_AUTH_CLIENT_ID= +GOOGLE_AUTH_SECRET= +GOOGLE_AUTH_PROJECT_ID= +GOOGLE_AUTH_CALLBACK=http://localhost:5000/google/callback + +# -- SIGNED URL SECRET -- +# Shared secret for url signing (e.g. create it by running `openssl rand -hex 32`) +SIGNED_SECRET= +# If empty, sentry will be disabled +SENTRY_DSN= +# Possible values: prod, dev +APP_ENV=dev + +# -- TESTING -- +AUTH0_TEST_USER= +AUTH0_TEST_PASS= +CALDAV_TEST_PRINCIPAL_URL= +CALDAV_TEST_CALENDAR_URL= +CALDAV_TEST_USER= +CALDAV_TEST_PASS= +GOOGLE_TEST_USER= +GOOGLE_TEST_PASS= diff --git a/backend/Dockerfile b/backend/Dockerfile index 473c5c7d..dfe1219f 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,23 +1,23 @@ -FROM python:3.11-buster - -RUN mkdir app -WORKDIR /app - -ENV PATH="${PATH}:/root/.local/bin" -ENV PYTHONPATH=. - -RUN mkdir scripts - -COPY requirements.txt . -COPY pyproject.toml . -COPY alembic.ini.example alembic.ini -COPY scripts/dev-entry.sh scripts/dev-entry.sh - -# Dev only -COPY .env . - -RUN pip install --upgrade pip -RUN pip install . - -EXPOSE 5000 +FROM python:3.11-buster + +RUN mkdir app +WORKDIR /app + +ENV PATH="${PATH}:/root/.local/bin" +ENV PYTHONPATH=. + +RUN mkdir scripts + +COPY requirements.txt . +COPY pyproject.toml . +COPY alembic.ini.example alembic.ini +COPY scripts/dev-entry.sh scripts/dev-entry.sh + +# Dev only +COPY .env . + +RUN pip install --upgrade pip +RUN pip install . + +EXPOSE 5000 CMD ["/bin/sh", "./scripts/dev-entry.sh"] \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt old mode 100755 new mode 100644 diff --git a/backend/scripts/dev-entry.sh b/backend/scripts/dev-entry.sh old mode 100755 new mode 100644 diff --git a/backend/scripts/entry.sh b/backend/scripts/entry.sh old mode 100755 new mode 100644 diff --git a/backend/src/appointment/main.py b/backend/src/appointment/main.py old mode 100755 new mode 100644 diff --git a/backend/src/appointment/templates/email/confirm.jinja2 b/backend/src/appointment/templates/email/confirm.jinja2 index 33915edc..de43f357 100644 --- a/backend/src/appointment/templates/email/confirm.jinja2 +++ b/backend/src/appointment/templates/email/confirm.jinja2 @@ -1,38 +1,38 @@ - - -

- {{ attendee.name|title }} ({{ attendee.email }}) just requested this time slot from your schedule: {{ date }}. -

-

- Click here to confirm the booking request:
- Confirm Booking -

-

- Or here if you want to deny it:
- Deny Booking -

-

- This message is sent from Thunderbird Appointment. -

- - + + +

+ {{ attendee.name|title }} ({{ attendee.email }}) just requested this time slot from your schedule: {{ date }}. +

+

+ Click here to confirm the booking request:
+ Confirm Booking +

+

+ Or here if you want to deny it:
+ Deny Booking +

+

+ This message is sent from Thunderbird Appointment. +

+ + diff --git a/backend/src/appointment/templates/email/invite.jinja2 b/backend/src/appointment/templates/email/invite.jinja2 index 0cb90875..932ce49c 100644 --- a/backend/src/appointment/templates/email/invite.jinja2 +++ b/backend/src/appointment/templates/email/invite.jinja2 @@ -1,5 +1,5 @@ - - -

This message is sent from Appointment.

- + + +

This message is sent from Appointment.

+ \ No newline at end of file diff --git a/backend/src/appointment/tmp/.gitignore b/backend/src/appointment/tmp/.gitignore index a6c57f5f..933daa68 100644 --- a/backend/src/appointment/tmp/.gitignore +++ b/backend/src/appointment/tmp/.gitignore @@ -1 +1 @@ -*.json +*.json diff --git a/frontend/.env.example b/frontend/.env.example index 555a6525..582f788b 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -1,18 +1,18 @@ -# Appointment frontend configuration. - -# -- Frontend -- -VUE_APP_BASE_URL=localhost:8080 -VUE_APP_SHORT_BASE_URL=localhost:8080/user - -# -- Backend API -- -VUE_APP_API_URL=localhost -VUE_APP_API_PORT=8090 -VUE_APP_API_SECURE=false - -# -- Auth0 -- -VUE_APP_AUTH0_DOMAIN= -VUE_APP_AUTH0_CLIENT_ID= -VUE_APP_AUTH0_AUDIENCE= - -# -- Sentry -- -VUE_APP_SENTRY_DSN= +# Appointment frontend configuration. + +# -- Frontend -- +VUE_APP_BASE_URL=localhost:8080 +VUE_APP_SHORT_BASE_URL=localhost:8080/user + +# -- Backend API -- +VUE_APP_API_URL=localhost +VUE_APP_API_PORT=8090 +VUE_APP_API_SECURE=false + +# -- Auth0 -- +VUE_APP_AUTH0_DOMAIN= +VUE_APP_AUTH0_CLIENT_ID= +VUE_APP_AUTH0_AUDIENCE= + +# -- Sentry -- +VUE_APP_SENTRY_DSN= diff --git a/frontend/.env.staging.example b/frontend/.env.staging.example index 2a707c36..1133075f 100644 --- a/frontend/.env.staging.example +++ b/frontend/.env.staging.example @@ -1,9 +1,9 @@ -# Production env config, do not put secrets in here !! -VUE_APP_API_URL=stage.appointment.day/api/v1/ -VUE_APP_BASE_URL=stage.appointment.day -VUE_APP_API_SECURE=true -VUE_APP_SHORT_BASE_URL=https://stage.apmt.day - -VUE_APP_AUTH0_DOMAIN=thunderbird.eu.auth0.com -VUE_APP_AUTH0_CLIENT_ID=Dvw6O6hPwXg7jZD7p7yAAnLXR2PXiQHF -VUE_APP_AUTH0_AUDIENCE=http://127.0.0.1:8000/ +# Production env config, do not put secrets in here !! +VUE_APP_API_URL=stage.appointment.day/api/v1/ +VUE_APP_BASE_URL=stage.appointment.day +VUE_APP_API_SECURE=true +VUE_APP_SHORT_BASE_URL=https://stage.apmt.day + +VUE_APP_AUTH0_DOMAIN=thunderbird.eu.auth0.com +VUE_APP_AUTH0_CLIENT_ID=Dvw6O6hPwXg7jZD7p7yAAnLXR2PXiQHF +VUE_APP_AUTH0_AUDIENCE=http://127.0.0.1:8000/ diff --git a/frontend/.eslintignore b/frontend/.eslintignore index 466c1d81..27160a72 100644 --- a/frontend/.eslintignore +++ b/frontend/.eslintignore @@ -1,4 +1,4 @@ -src/assets -src/elements/arts -src/locales +src/assets +src/elements/arts +src/locales node_modules \ No newline at end of file diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js index d7fa82a2..23174004 100644 --- a/frontend/.eslintrc.js +++ b/frontend/.eslintrc.js @@ -1,34 +1,34 @@ -module.exports = { - env: { - browser: true, - es2021: true, - }, - extends: [ - 'plugin:vue/vue3-essential', - 'airbnb-base', - ], - overrides: [], - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - }, - plugins: [ - 'vue', - ], - rules: { - 'import/extensions': ['error', 'ignorePackages', { - '': 'never', - js: 'never', - vue: 'off', // TODO: once migrated to Vite, we should set this to 'always' - }], - 'max-len': ['error', { code: 120 }], - 'no-param-reassign': 'off', - }, - settings: { - 'import/resolver': { - webpack: { - config: require.resolve('@vue/cli-service/webpack.config.js'), - }, - }, - }, -}; +module.exports = { + env: { + browser: true, + es2021: true, + }, + extends: [ + 'plugin:vue/vue3-essential', + 'airbnb-base', + ], + overrides: [], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, + plugins: [ + 'vue', + ], + rules: { + 'import/extensions': ['error', 'ignorePackages', { + '': 'never', + js: 'never', + vue: 'off', // TODO: once migrated to Vite, we should set this to 'always' + }], + 'max-len': ['error', { code: 120 }], + 'no-param-reassign': 'off', + }, + settings: { + 'import/resolver': { + webpack: { + config: require.resolve('@vue/cli-service/webpack.config.js'), + }, + }, + }, +}; diff --git a/frontend/.gitignore b/frontend/.gitignore old mode 100755 new mode 100644 index 694a5904..90f89baa --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,24 +1,24 @@ -.DS_Store -node_modules -/dist -.yarn - - -# local env files -.env.local -.env.*.local - -# Log files -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* - -# Editor directories and files -.idea -.vscode -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? +.DS_Store +node_modules +/dist +.yarn + + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 6294c3ca..e2bf6d97 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,13 +1,13 @@ -FROM node:lts-alpine - -WORKDIR /app - -ENV PATH /app/node_modules/.bin:$PATH - -# Get git -RUN apk add --no-cache git - -COPY . . -RUN yarn install - +FROM node:lts-alpine + +WORKDIR /app + +ENV PATH /app/node_modules/.bin:$PATH + +# Get git +RUN apk add --no-cache git + +COPY . . +RUN yarn install + CMD vue-cli-service serve \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md old mode 100755 new mode 100644 diff --git a/frontend/docker/etc/nginx/conf.d/appointments.conf b/frontend/docker/etc/nginx/conf.d/appointments.conf index fe3c3c97..f1865df5 100644 --- a/frontend/docker/etc/nginx/conf.d/appointments.conf +++ b/frontend/docker/etc/nginx/conf.d/appointments.conf @@ -1,44 +1,44 @@ -server { - listen 80; - listen [::]:80; - server_name localhost; - - #access_log /var/log/nginx/host.access.log main; - - # Backend API proxy - location ^~ /api/v1/ { - # Remove our fake /api/v1/ prefix for FastAPI - rewrite ^/api/v1/(.*)$ /$1 break; - proxy_pass http://127.0.0.1:5000; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_http_version 1.1; - } - # Frontend Vue static files - location / { - root /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - #auth_basic "Restricted Content"; - #auth_basic_user_file /etc/nginx/.htpasswd; - } - - #error_page 404 /404.html; - - # redirect server error pages to the static page /50x.html - # - #error_page 500 502 503 504 /50x.html; - #location = /50x.html { - # root /usr/share/nginx/html; - #} -} - -# Stage Shortlink Redirect -server { - listen 80; - listen [::]:80; - server_name stage.apmt.local stage.apmt.day; - location / { - # Transform stage.apmt.day/ to stage.appointment.day/user/ - rewrite ^(.*)$ https://stage.appointment.day/user$1 redirect; - } +server { + listen 80; + listen [::]:80; + server_name localhost; + + #access_log /var/log/nginx/host.access.log main; + + # Backend API proxy + location ^~ /api/v1/ { + # Remove our fake /api/v1/ prefix for FastAPI + rewrite ^/api/v1/(.*)$ /$1 break; + proxy_pass http://127.0.0.1:5000; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + # Frontend Vue static files + location / { + root /usr/share/nginx/html; + try_files $uri $uri/ /index.html; + #auth_basic "Restricted Content"; + #auth_basic_user_file /etc/nginx/.htpasswd; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + #error_page 500 502 503 504 /50x.html; + #location = /50x.html { + # root /usr/share/nginx/html; + #} +} + +# Stage Shortlink Redirect +server { + listen 80; + listen [::]:80; + server_name stage.apmt.local stage.apmt.day; + location / { + # Transform stage.apmt.day/ to stage.appointment.day/user/ + rewrite ^(.*)$ https://stage.appointment.day/user$1 redirect; + } } \ No newline at end of file diff --git a/frontend/jsconfig.json b/frontend/jsconfig.json old mode 100755 new mode 100644 diff --git a/frontend/package.json b/frontend/package.json old mode 100755 new mode 100644 diff --git a/frontend/public/index.html b/frontend/public/index.html old mode 100755 new mode 100644 diff --git a/frontend/src/App.vue b/frontend/src/App.vue old mode 100755 new mode 100644 diff --git a/frontend/src/assets/fonts/Apache License.txt b/frontend/src/assets/fonts/Apache License.txt index 989e2c59..b1fac45f 100644 --- a/frontend/src/assets/fonts/Apache License.txt +++ b/frontend/src/assets/fonts/Apache License.txt @@ -1,201 +1,201 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and limitations under the License. \ No newline at end of file diff --git a/frontend/src/assets/main.css b/frontend/src/assets/main.css index a4a62b1a..6b81ca77 100644 --- a/frontend/src/assets/main.css +++ b/frontend/src/assets/main.css @@ -1,98 +1,98 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - - -@layer base { - input, select, textarea { - @apply transition-all dark:text-white bg-white dark:bg-gray-700 !border-gray-300 dark:!border-gray-500 focus:!ring-teal-500 focus:!border-teal-500 checked:!border-teal-500; - } - - hr { - @apply border-t-gray-300 dark:border-t-gray-500 - } - - @font-face { - font-family: 'Raleway'; - src: url('./fonts/Raleway-Regular.ttf'); - font-weight: 400; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-LightItalic.ttf'); - font-weight: 300; - font-style: italic; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-Light.ttf'); - font-weight: 300; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-Italic.ttf'); - font-weight: 400; - font-style: italic; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-Regular.ttf'); - font-weight: 400; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-MediumItalic.ttf'); - font-weight: 500; - font-style: italic; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-Medium.ttf'); - font-weight: 500; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-SemiBoldItalic.ttf'); - font-weight: 600; - font-style: italic; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-SemiBold.ttf'); - font-weight: 600; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-BoldItalic.ttf'); - font-weight: 700; - font-style: italic; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-Bold.ttf'); - font-weight: 700; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-ExtraBoldItalic.ttf'); - font-weight: 800; - font-style: italic; - } - @font-face { - font-family: 'Open Sans'; - src: url('./fonts/OpenSans-ExtraBold.ttf'); - font-weight: 800; - } -} - -@layer components { - .position-center { - @apply top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2; - } - .flex-center { - @apply flex justify-center items-center; - } - .place-holder { - @apply placeholder:text-gray-300 dark:placeholder:text-gray-500; - } -} +@tailwind base; +@tailwind components; +@tailwind utilities; + + +@layer base { + input, select, textarea { + @apply transition-all dark:text-white bg-white dark:bg-gray-700 !border-gray-300 dark:!border-gray-500 focus:!ring-teal-500 focus:!border-teal-500 checked:!border-teal-500; + } + + hr { + @apply border-t-gray-300 dark:border-t-gray-500 + } + + @font-face { + font-family: 'Raleway'; + src: url('./fonts/Raleway-Regular.ttf'); + font-weight: 400; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-LightItalic.ttf'); + font-weight: 300; + font-style: italic; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-Light.ttf'); + font-weight: 300; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-Italic.ttf'); + font-weight: 400; + font-style: italic; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-Regular.ttf'); + font-weight: 400; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-MediumItalic.ttf'); + font-weight: 500; + font-style: italic; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-Medium.ttf'); + font-weight: 500; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-SemiBoldItalic.ttf'); + font-weight: 600; + font-style: italic; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-SemiBold.ttf'); + font-weight: 600; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-BoldItalic.ttf'); + font-weight: 700; + font-style: italic; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-Bold.ttf'); + font-weight: 700; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-ExtraBoldItalic.ttf'); + font-weight: 800; + font-style: italic; + } + @font-face { + font-family: 'Open Sans'; + src: url('./fonts/OpenSans-ExtraBold.ttf'); + font-weight: 800; + } +} + +@layer components { + .position-center { + @apply top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2; + } + .flex-center { + @apply flex justify-center items-center; + } + .place-holder { + @apply placeholder:text-gray-300 dark:placeholder:text-gray-500; + } +} diff --git a/frontend/src/definitions.js b/frontend/src/definitions.js old mode 100755 new mode 100644 diff --git a/frontend/src/main.js b/frontend/src/main.js old mode 100755 new mode 100644 diff --git a/frontend/src/router.js b/frontend/src/router.js old mode 100755 new mode 100644 diff --git a/frontend/src/utils.js b/frontend/src/utils.js old mode 100755 new mode 100644 diff --git a/frontend/src/views/AppointmentsView.vue b/frontend/src/views/AppointmentsView.vue old mode 100755 new mode 100644 diff --git a/frontend/src/views/CalendarView.vue b/frontend/src/views/CalendarView.vue old mode 100755 new mode 100644 diff --git a/frontend/src/views/ProfileView.vue b/frontend/src/views/ProfileView.vue old mode 100755 new mode 100644 diff --git a/frontend/src/views/SettingsView.vue b/frontend/src/views/SettingsView.vue old mode 100755 new mode 100644 diff --git a/frontend/vue.config.js b/frontend/vue.config.js old mode 100755 new mode 100644 diff --git a/frontend/yarn.lock b/frontend/yarn.lock old mode 100755 new mode 100644