diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000..ed782df5be Binary files /dev/null and b/.DS_Store differ diff --git a/.aws/credentials b/.aws/credentials new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.github/workflows/deploy-image.yml b/.github/workflows/deploy-image.yml new file mode 100644 index 0000000000..39503ab7e3 --- /dev/null +++ b/.github/workflows/deploy-image.yml @@ -0,0 +1,122 @@ +name: Deploy to VM + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + + # - name: Set AWS credentials + # uses: aws-actions/configure-aws-credentials@v1 + # with: + # aws-access-key-id: ${{ secrets.AWS_EC2_ACCESS_KEY_ID }} + # aws-secret-access-key: ${{ secrets.AWS_EC2_SECRET_ACCESS_KEY }} + # aws-region: eu-west-2 + + # - name: Check SSH Connection + # run: | + # ssh -i ${{secrets.SSH_PRIVATE_KEY}} -o StrictHostKeyChecking=no -o BatchMode=yes -o ConnectTimeout=10 ${{ secrets.USERNAME }}@${{ secrets.AWS_HOST }} exit + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Create tag for image + id: create_tag + run: | + TAG=$(date +'%Y%m%d%H%M%S') + echo "::set-output name=tag::$TAG" + + - name: Build Docker image + run: | + cd server + docker build -t olhadanylevska/video-server:${{ steps.create_tag.outputs.tag }} . + cd .. + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Push Docker image to Docker Hub + run: | + docker push olhadanylevska/video-server:${{ steps.create_tag.outputs.tag }} + + - name: Checkout code + uses: actions/checkout@v2 + + # # Install Docker + # - name: Install Docker + # with: + # host: ${{ secrets.AWS_HOST }} + # username: ${{ secrets.USERNAME }} + # key: ${{ secrets.SSH_PRIVATE_KEY } + # run: | + # sudo apt-get update + # sudo apt-get install -y docker.io + # sudo usermod -aG docker $USER + # sudo systemctl restart docker + + - name: Install Docker on remote server + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + sudo apt-get update + sudo apt-get install -y docker.io + sudo usermod -aG docker $USER + sudo systemctl restart docker + + + - name: Check Docker daemon on remote server + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + docker info + + - name: Clear images and pull new image + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + docker system prune -a -f + docker pull olhadanylevska/video-server:${{ steps.create_tag.outputs.tag }} + + - name: Identify and stop previous container + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + CONTAINER_ID=$(docker ps -q --filter "ancestor=olhadanylevska/video-server:${{ steps.create_tag.outputs.tag }}") + if [ ! -z "$CONTAINER_ID" ]; then + docker stop $CONTAINER_ID + docker rm $CONTAINER_ID + fi + + - name: Run container on VM server + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + docker run -d \ + -e DB_USER=${{ secrets.RDS_DB_USER }} \ + -e DB_HOST=${{ secrets.RDS_DB_HOST }} \ + -e DB_PASSWORD=${{ secrets.RDS_DB_PASSWORD }} \ + -e DB_PORT=${{ secrets.RDS_DB_PORT }} \ + -p 80:3000 \ + olhadanylevska/video-server:${{ steps.create_tag.outputs.tag }} diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml new file mode 100644 index 0000000000..fc44e45a62 --- /dev/null +++ b/.github/workflows/frontend.yml @@ -0,0 +1,46 @@ +name: Deploy Frontend + +on: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./client + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + + - name: Clear npm cache + run: npm cache clean -f + + - name: Install dependencies + run: npm install + + - name: Build Website + run: npm run build + + - name: Debug + run: ls -la build + + - name: Set 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: eu-west-2 + + - name: Copy to S3 + run: | + aws configure set aws_access_key_id ${{ secrets.AWS_ACCESS_KEY_ID }} + aws configure set aws_secret_access_key ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws configure set default.region eu-west-2 + aws s3 sync ./build/ s3://video-app-olha diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..8d1171d79b --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +node_modules +.env + +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc \ No newline at end of file diff --git a/100.md b/100.md deleted file mode 100644 index 315051c307..0000000000 --- a/100.md +++ /dev/null @@ -1,97 +0,0 @@ -# Level 100 - Week 1 - Front End - -By the end of this level you will have a React website that - -- Fulfils all of the requirements in the ReadMe -- Uses static data for the website - -## Project - -You will find an empty project in the `client` directory for you to work in. - -To run the project you should first run these commands - -``` -cd client -npm install -``` - -then you can launch the website with - -``` -npm run start -``` - -## Static Data - -By static data, we mean that we will use a javascript variable to hold the data that we would expect to get from the API. - -You can find an example of this data in `exampleresponse.json` at the root of this repository. - -## Design - -You are welcome to use [Bootstrap](https://getbootstrap.com/docs/4.0/getting-started/introduction/) or any other design framework to help you build this app. - -## Required Features - -1. Videos should be loaded from a local javascript variable containing the data included in `exampleresponse.json` -2. For each video, display a React component that contains - - The videos title - - An embedded video - - The number of votes the video has - - A button that when clicked removes the video -3. On each video submission there should be two buttons - - "Up Vote" - This increases the vote score when clicked - - "Down Vote" - This decreases the vote score when clicked -4. On the page there must be another React component that will add a Video. - - It should include fields to add a - - Title - - Url - - When a button is clicked the video should be added to the list -5. Your website must follow accessibility guidelines (see below for more details) - -## Sample Solution - -Here is an example solution of the Front End: - -https://vid-rec2.netlify.app/ - -**Note:** You can design the website to look however you like. - -## Accessible Guidelines - -1. Run a [Lighthouse test](https://supercooldesign.co.uk/blog/how-to-run-a-lighthouse-audit) on your prototype in Chrome -2. Follow the suggestions to fix the accessibility errors until your score is green. Save your result as HTML and include it in your Pull Request to show your work. -3. Add a title to your iframe and make the value the title of the video -4. Add a focus state with CSS to highlight what control is active -5. Tab through your page and make sure you can click all the controls without using a mouse (edited) - -## Embedding Videos from YouTube - -Instructions about how to embed a YouTube video can be found here - -https://support.google.com/youtube/answer/171780?hl=en - -You can embed videos from YouTube by using a HTML feature called `iframe`s. - -```HTML - -``` - -Place that HTML snippet in a React component and replace "`VIDEO_ID_GOES_HERE`" with the ID of the video you want to display to embed a video. - -The ID of a video can be found by looking at the URL of the video. For example, for the video - -```html -https://www.youtube.com/watch?v=FUeyrEN14Rk -``` - -The ID would be - -```html -FUeyrEN14Rk -``` - -## Before you commit your changes - -Read this [article on .gitignore](https://sabe.io/blog/git-ignore-node_modules). Use .gitignore to ensure you do not commit any `node_modules` directories to your repository. diff --git a/199.md b/199.md deleted file mode 100644 index 09b55c5521..0000000000 --- a/199.md +++ /dev/null @@ -1,29 +0,0 @@ -# Level 150 - Week 1 - Front End - Stretch Goals - -Here are some additional tasks for you to complete should you finish everything in Level 100 - -You can work on them in any order - -## 1) Ordering Results - -When you load the data, order it so that the video with the most upvotes is at the top and least is are the bottom. - -## 2) Data Validation - -When a video is added, make sure that the title is not empty and that the url is a valid YouTube URL - -## 3) Uploaded Date - -When a user uploads a video store the date and time that they posted it at. - -Add when the video was uploaded to the Video React component - -## 4) Material UI - -As a further stretch goal, consider adding the Material UI library - -https://material-ui.com/ - -Material UI is a _Design System_ that can help you to design great looking websites and apps. When using a design system you should use the guidelines that they put in place. You can read more about these guidelines here: - -https://material.io/ diff --git a/200.md b/200.md deleted file mode 100644 index 379d220bd8..0000000000 --- a/200.md +++ /dev/null @@ -1,134 +0,0 @@ -# Level 200 - Week 2 - Back End - -In the second week of this project you are creating the API for your Video website. - -## How to read this guide - -Below are separate headings for each endpoint. Each of them are separated into the `HTTP Request Method` type and the route that the endpoint should exist on. - -For a recap on about HTTP Request Methods you can read here -https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods - -For example, for the first endpoint - -- `GET` is the request method -- "/" is the route - -On Line 8 of `server.js` you can find an example of the first endpoint that you will need to make. - -## Project - -Before starting this project you should run these commands to install the project - -```sh -cd server -npm install -``` - -to run the server you can use - -```sh -npm run dev -``` - -To confirm your server is running go to - -```url -http://127.0.0.1:5000/ -``` - -in your browser. If the server is running you'll see a message saying - -```json -{ "express": "Your Backend Service is Running" } -``` - -## Sample Solution - -Here is an example solution for the Back End: - -https://video-rec.herokuapp.com - -## Endpoints - -Your website should have the following four endpoints. - -### `GET` "/" - -This endpoint is used to return all of the videos - -#### Example Response - -See `exampleresponse.json` - -### `POST` "/" - -This endpoint is used to add a video to the API. - -Both fields - title and url - must be included and be valid for this to succeed. - -**Note:** When a video is added, you must attach a unique ID to so that it can later be deleted - -#### Expected Data - -```json -{ - "title": "", - "url": "" -} -``` - -#### Example Response - -If successful: - -```json -{ - "id": 523523 -} -``` - -If not successful - -```json -{ - "result": "failure", - "message": "Video could not be saved" -} -``` - -### `GET` "/{id}" - -Returns the video with the ID contained within the `{id}` parameter - -#### Example Response - -```json -{ - "id": 1, - "title": "Never Gonna Give You Up", - "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", - "rating": 23 -} -``` - -### `DELETE` "/{id}" - -Deletes the video with the ID container within the `{id}` parameter - -#### Example Response - -If successful: - -```json -{} -``` - -if not successful: - -```json -{ - "result": "failure", - "message": "Video could not be deleted" -} -``` diff --git a/250.md b/250.md deleted file mode 100644 index e7646e2b9e..0000000000 --- a/250.md +++ /dev/null @@ -1,21 +0,0 @@ -# Level 250 - Week 2 - Connecting Front End and Back End - -In this step you should connect your React and Node apps so that data is stored and retrieved from the API - -When completed, you should not be reading data from a local variable in your React app, you should be using `fetch` to retrieve your data from the API you have just built. - -## Local Development - -Since you're working on your API locally you'll need to use an a local url. By default this will be configure to - -```url -http://127.0.0.1/5000 -``` - -When you have your server running you should be able to test if it's working by going to that url and viewing all of the videos in your API. - -## Tips - -Checkout this cheatsheet to help you with the types of requests you'll need to be using with `fetch` - -https://www.freecodecamp.org/news/fetch-api-cheatsheet/ diff --git a/299.md b/299.md deleted file mode 100644 index c5880e6170..0000000000 --- a/299.md +++ /dev/null @@ -1,33 +0,0 @@ -# Level 299 - Week 2 - Back End - Stretch Goals - -## 1) Ordered Data - Back End - -When you return all of the videos from endpoint you should add an optional parameter that will change the ordering of the data - -```sh -/?order=asc -``` - -and - -```sh -/?order=desc -``` - -When you receive `asc` the videos should be returned in ascending order by the number of votes. i.e. starting with the lowest number of votes. - -When you receive `desc` the videos should be returned in descending order by the number of votes. i.e. starting with the highest number of votes. - -If no parameter is passed, the order should be descending. - -## 2) Ordered Data - Front End - -When you've completed the Back End portion of this work, add a button to your React App that allows the user to choose to either - -- Order the content by ascending - -or - -- Order the content by descending - -When the button is clicked, the ordered should toggle between ascending and descending. diff --git a/300.md b/300.md deleted file mode 100644 index 79ec767a7c..0000000000 --- a/300.md +++ /dev/null @@ -1,22 +0,0 @@ -# Level 300 - Week 3 - Database - -In this final stage of the project you will be adding a database to your API so that data is persisted. - -You can use any database of your choosing - most likely PostgreSQL or MongoDB. - -## Setting up your Database - -To setup your database you can use either - -- MongoDB - - Using MongoDB Atlas - - https://www.mongodb.com/cloud/atlas -- PostgreSQL - - Using Heroku - - https://dev.to/prisma/how-to-setup-a-free-postgresql-database-on-heroku-1dc1 - -Ask for help on Slack if you need help with this - -## Success Criteria - -When this stage has been completed all of your data should exist only in your database - no data should be stored in your API or in your React app diff --git a/399.md b/399.md deleted file mode 100644 index 581c1e6145..0000000000 --- a/399.md +++ /dev/null @@ -1 +0,0 @@ -# Level 300 - Week 3 - Database - Stretch Goals diff --git a/999.md b/999.md deleted file mode 100644 index 31bc47d131..0000000000 --- a/999.md +++ /dev/null @@ -1 +0,0 @@ -# Level 999 - Stretch Goals diff --git a/README.md b/README.md index c26d98e330..63f4256262 100644 --- a/README.md +++ b/README.md @@ -73,3 +73,45 @@ You are welcome to use [Bootstrap](https://getbootstrap.com/docs/4.0/getting-sta Fork this repository and then clone it to your computer. Progress to Level 100 when you are ready. + + + +name: Node.js Deployment + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Update and Upgrade EC2 inst + run: | + sudo apt update + sudo apt upgrade -y + + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 12 + + - name: Install Dependencies + run: | + npm install + + - name: rsync deployments + uses: burnett01/rsync-deployments@6.0.0 + with: + switches: -avzr --exclude=node_modules --delete + path: ./server/ + remote_path: ~/.video-app/ + remote_host: ${{ secrets.AWS_HOST }} + remote_port: 22 + remote_user: ${{ secrets.USERNAME }} + remote_key: ${{ secrets.SSH_PRIVATE_KEY }} diff --git a/client/.DS_Store b/client/.DS_Store new file mode 100644 index 0000000000..5008ddfcf5 Binary files /dev/null and b/client/.DS_Store differ diff --git a/client/.terraform.lock.hcl b/client/.terraform.lock.hcl new file mode 100644 index 0000000000..68cd645e4c --- /dev/null +++ b/client/.terraform.lock.hcl @@ -0,0 +1,24 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.37.0" + hashes = [ + "h1:CQeYyWigNz838zjXKYH9VDkpjqlGB0phcM742YXiNh4=", + "zh:00f40a3d9593476693a7a72d993fd289f7be374fe3f2799776c6296eb6ff890a", + "zh:1010a9fbf55852a8da3473de4ec0f1fcf29efa85d66f61cbe2b086dbbd7747ae", + "zh:103a5674d1eb1cff05fe35e9baa9875afd18d740868b63f9c0c25eadb5eb4eb7", + "zh:270ac1b7a1327c1456a43df44c0b5cc3e26ed6d8861a709adeea1da684a563f5", + "zh:424362c02c8917c0586f3dd49aca27b7e0c21f5a23374b7045e9be3b5646c028", + "zh:549fa2ea187964ab9a0c354310947ead30e09b3199db1ff377c21d7547d78299", + "zh:6492d2ccc7f7d60e83cd8b7244adc53f30efc17d84b1ffc1b8fd6c385f8255fd", + "zh:66fb7b3b8a357071d26c5996c16d426edf07502a05ac86f4a6f73646ee7d1bbb", + "zh:6ecc05fb466d06ea8945564d2cdb8c2a8827d8cfca1550e9fb7eac0e95920196", + "zh:7932360b627b211dad937d278a8692a6c52bd6c0a71e4ec9e94ccbe825053822", + "zh:97ed1b4a18842c4d56a735329e87b4ef91a47e820e5a5c3c2dd64e293408bfc8", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:d5e022052011e1984b9c2f8bc5a6b05c909e3b5bf40c3baddf191bf90e3169c2", + "zh:d7e9488b2ce5904efb91c8577b3fe9b0cd599c4cd508f1f163f292930f54fdf0", + "zh:e57cd93d5cd81dd0f446076af6e47a53ce83df2947ec64ed39a1090d4bdf8f0b", + ] +} diff --git a/client/build/asset-manifest.json b/client/build/asset-manifest.json new file mode 100644 index 0000000000..78a587df98 --- /dev/null +++ b/client/build/asset-manifest.json @@ -0,0 +1,13 @@ +{ + "files": { + "main.css": "/static/css/main.e34a664f.css", + "main.js": "/static/js/main.55683642.js", + "index.html": "/index.html", + "main.e34a664f.css.map": "/static/css/main.e34a664f.css.map", + "main.55683642.js.map": "/static/js/main.55683642.js.map" + }, + "entrypoints": [ + "static/css/main.e34a664f.css", + "static/js/main.55683642.js" + ] +} \ No newline at end of file diff --git a/client/build/favicon.ico b/client/build/favicon.ico new file mode 100644 index 0000000000..66f7840a36 Binary files /dev/null and b/client/build/favicon.ico differ diff --git a/client/build/index.html b/client/build/index.html new file mode 100644 index 0000000000..99be6caee4 --- /dev/null +++ b/client/build/index.html @@ -0,0 +1 @@ +React App
\ No newline at end of file diff --git a/client/build/manifest.json b/client/build/manifest.json new file mode 100644 index 0000000000..6d7198cf29 --- /dev/null +++ b/client/build/manifest.json @@ -0,0 +1,8 @@ +{ + "short_name": "To Do App", + "name": "To Do App", + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/client/build/robots.txt b/client/build/robots.txt new file mode 100644 index 0000000000..e9e57dc4d4 --- /dev/null +++ b/client/build/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/client/build/static/css/main.e34a664f.css b/client/build/static/css/main.e34a664f.css new file mode 100644 index 0000000000..82438b2807 --- /dev/null +++ b/client/build/static/css/main.e34a664f.css @@ -0,0 +1,2 @@ +body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.App{text-align:center}.background{background:linear-gradient(336deg,#220c49,#060011);height:100%;left:0;position:fixed;top:0;width:100%;z-index:-1}.image-heart{width:1.5rem}.cards-holder{border:"solid white 2px";display:flex;flex-direction:row;flex-wrap:wrap;gap:2rem;justify-content:center;margin-bottom:3rem}.card{background:#fff;background:linear-gradient(336deg,hsla(0,0%,100%,.716),hsla(0,0%,100%,.24));border:1px solid #fff;padding:1rem;text-align:left;width:32rem}.video-holder{padding-top:56.25%;position:relative;width:30rem}.text-holder{align-self:flex-end}.card-buttons{display:flex;flex-direction:row;justify-content:space-between}.delete-button{align-self:self-end;background-color:rgba(225,51,51,.8);border:1px solid #fff;border-radius:2rem;box-shadow:0 3px 8px rgba(0,0,0,.24);color:#fff;padding:.3rem .8rem}.delete-button:hover{background-color:#e50c0c}h4{color:#fff;margin-bottom:.6rem;margin-top:1rem}.down,.up{background-color:rgba(48,13,81,.6);border:none;color:#fff;height:2rem;margin-top:.5rem}.up{border-radius:1rem 0 0 1rem;border-right:1px solid #9b84a5;padding-left:1rem}.down,.up{border-top:1px solid #fff}.down{border-radius:0 1rem 1rem 0}.tumb-up{margin-right:.5rem;padding-bottom:.3rem;width:1rem}.rate{text-align:right}.tumb-down{margin-left:.5rem;margin-right:.5rem;-webkit-transform:scale(-1);transform:scale(-1);width:1rem}.form-holder{flex-direction:column;margin-bottom:2rem;min-height:10rem}.form-holder,form{align-items:center;display:flex;justify-content:center;width:100%}form{flex-direction:row;flex-wrap:wrap;gap:.5rem;margin-top:1rem;min-height:6rem}.form-holder input{background-color:hsla(0,0%,100%,.2);border:1px solid #9d8bb8;border-radius:2rem;color:#fff;height:2.5rem;margin-right:1rem;padding-left:1rem;padding-right:1rem;width:20rem}.form-holder ::-webkit-input-placeholder{color:hsla(0,0%,100%,.6);font-size:12px;padding-left:1rem}.form-holder ::placeholder{color:hsla(0,0%,100%,.6);font-size:12px;padding-left:1rem}.form-holder input:hover{background-color:hsla(0,0%,100%,.5)}.form-holder input:focus{background-color:hsla(0,0%,100%,.8);border-color:#fff;color:#303030;outline-width:0}.form-holder button{background:#453069;background:linear-gradient(336deg,#453069 15%,#8469b5);border:1px solid hsla(0,0%,100%,.6);border-radius:2rem;box-shadow:0 3px 8px rgba(0,0,0,.5);color:#fff;height:2.5rem;width:10rem}.form-holder button:hover{background:#765ca3;background:linear-gradient(336deg,#765ca3 15%,#c198e2)}h3{color:#fff;font-size:18px;width:80%}.main-button-to-add{background:#453069;background:linear-gradient(336deg,#453069 15%,#8469b5);border:1px solid hsla(0,0%,100%,.6);border-radius:2rem;box-shadow:0 3px 8px rgba(0,0,0,.5);color:#fff;height:2.5rem;margin-bottom:1.5rem;width:10rem}.main-button-to-add:focus{outline-width:0}.main-button-to-add:hover{height:2.6rem;width:10.2rem}h1{color:#4f405c;font-size:40px;margin-bottom:2rem;margin-top:2rem}.react-player{left:0;position:absolute;top:0}.sorting-holder{color:#fff;font-size:18px;margin:0 auto;text-align:end;width:82%}.sorting-ratings-button{background-color:hsla(0,0%,72%,.59);border:none;border-radius:.4rem;margin-bottom:1rem;margin-left:.5rem;padding:.1rem .3rem .3rem;width:2rem}.sorting-ratings-button img{width:1rem}@media only screen and (max-width:844px){.react-player{left:0;position:absolute;top:0}.video-holder{padding-top:56.25%;position:relative;width:100%}.card{padding:.5rem;width:96%}form{min-height:10rem;width:100%}h1{font-size:28px}} +/*# sourceMappingURL=main.e34a664f.css.map*/ \ No newline at end of file diff --git a/client/build/static/css/main.e34a664f.css.map b/client/build/static/css/main.e34a664f.css.map new file mode 100644 index 0000000000..644d4aca4b --- /dev/null +++ b/client/build/static/css/main.e34a664f.css.map @@ -0,0 +1 @@ +{"version":3,"file":"static/css/main.e34a664f.css","mappings":"AAAA,KAKE,kCAAmC,CACnC,iCAAkC,CAJlC,mIAEY,CAHZ,QAMF,CAEA,KACE,uEAEF,CCZA,KACE,iBACF,CAEA,YACE,kDAAmF,CAKnF,WAAY,CAFZ,MAAO,CAFP,cAAe,CACf,KAAM,CAEN,UAAW,CAEX,UACF,CAEA,aACE,YACF,CAEA,cAME,wBAAyB,CALzB,YAAa,CACb,kBAAmB,CACnB,cAAe,CAEf,QAAS,CADT,sBAAuB,CAGvB,kBACF,CAIA,MAIE,eAA8B,CAC9B,2EAA6H,CAC7H,qBAAuB,CAHvB,YAAa,CAFb,eAAgB,CAChB,WAKF,CAEA,cAGE,kBAAmB,CADnB,iBAAkB,CADlB,WAIF,CAEA,aACE,mBACF,CAEA,cACE,YAAa,CACb,kBAAmB,CACnB,6BACF,CAEA,eACE,mBAAoB,CAKpB,mCAAuC,CAFvC,qBAAuB,CAFvB,kBAAmB,CAKnB,oCAA2C,CAF3C,UAAY,CAFZ,mBAKF,CAEA,qBACE,wBACF,CAEA,GAGE,UAAY,CAFZ,mBAAqB,CACrB,eAEF,CAEA,UAGE,kCAAsC,CADtC,WAAY,CAIZ,UAAY,CAFZ,WAAY,CACZ,gBAEF,CAEA,IACE,2BAA4B,CAE5B,8BAA0C,CAD1C,iBAIF,CAEA,UAJE,yBAOF,CAHA,MACE,2BAEF,CAEA,SAGE,kBAAoB,CADpB,oBAAsB,CADtB,UAGF,CAEA,MACE,gBACF,CAEA,WAOE,iBAAmB,CADnB,kBAAoB,CAHpB,2BAAgC,CAChC,mBAAwB,CACxB,UAGF,CAEA,aAKE,qBAAsB,CAFtB,kBAAmB,CADnB,gBAMF,CAEA,kBAHE,kBAAmB,CAHnB,YAAa,CAEb,sBAAuB,CALvB,UAoBF,CAXA,KAKE,kBAAmB,CACnB,cAAe,CACf,SAAW,CAJX,eAAgB,CADhB,eASF,CAEA,mBAME,mCAAyC,CADzC,wBAAoC,CADpC,kBAAmB,CAKnB,UAAY,CAPZ,aAAc,CACd,iBAAkB,CAIlB,iBAAkB,CAClB,kBAAmB,CAPnB,WASF,CAEA,yCACE,wBAA8B,CAE9B,cAAe,CADf,iBAEF,CAJA,2BACE,wBAA8B,CAE9B,cAAe,CADf,iBAEF,CAEA,yBACE,mCACF,CAEA,yBACE,mCAAyC,CAGzC,iBAAgC,CAFhC,aAAsB,CACtB,eAEF,CAEA,oBAME,kBAA4B,CAC5B,sDAA0F,CAH1F,mCAAyC,CADzC,kBAAmB,CAKnB,mCAA0C,CAH1C,UAAY,CAHZ,aAAc,CADd,WAQF,CAEA,0BACE,kBAA6B,CAC7B,sDACF,CAEA,GACE,UAAY,CACZ,cAAe,CACf,SACF,CAEA,oBAOE,kBAA4B,CAC5B,sDAA0F,CAH1F,mCAAyC,CADzC,kBAAmB,CAKnB,mCAA0C,CAH1C,UAAY,CAHZ,aAAc,CAFd,oBAAqB,CACrB,WAQF,CAEA,0BACE,eACF,CAEA,0BAEE,aAAc,CADd,aAEF,CAEA,GAIE,aAAsB,CAHtB,cAAe,CAEf,kBAAmB,CADnB,eAGF,CAEA,cAGE,MAAO,CAFP,iBAAkB,CAClB,KAEF,CAEA,gBACE,UAAY,CAIZ,cAAe,CAFf,aAAc,CACd,cAAe,CAFf,SAIF,CAEA,wBACE,mCAA0C,CAK1C,WAAY,CAFZ,mBAAqB,CAGrB,kBAAmB,CACnB,iBAAmB,CALnB,yBAAmB,CAEnB,UAKF,CAEA,4BACE,UACF,CAGA,yCACE,cAGE,MAAO,CAFP,iBAAkB,CAClB,KAGF,CAEA,cAGE,kBAAmB,CADnB,iBAAkB,CADlB,UAIF,CAEA,MAEE,aAAe,CADf,SAEF,CAEA,KAEE,gBAAiB,CADjB,UAEF,CAEA,GACE,cACF,CAGF","sources":["index.css","App.css"],"sourcesContent":["body {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n monospace;\n}",".App {\n text-align: center;\n}\n\n.background {\n background: linear-gradient(336deg, rgba(34, 12, 73, 1) 0%, rgba(6, 0, 17, 1) 100%);\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: -1;\n}\n\n.image-heart {\n width: 1.5rem;\n}\n\n.cards-holder {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: center;\n gap: 2rem;\n border: \"solid white 2px\";\n margin-bottom: 3rem;\n}\n\n\n\n.card {\n text-align: left;\n width: 32rem;\n padding: 1rem;\n background: rgb(255, 255, 255);\n background: linear-gradient(336deg, rgba(255, 255, 255, 0.7161458333333333) 0%, rgba(255, 255, 255, 0.2399553571428571) 100%);\n border: 1px solid white;\n}\n\n.video-holder {\n width: 30rem;\n position: relative;\n padding-top: 56.25%;\n /* 720 / 1280 = 0.5625 */\n}\n\n.text-holder {\n align-self: flex-end;\n}\n\n.card-buttons {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n}\n\n.delete-button {\n align-self: self-end;\n border-radius: 2rem;\n padding: 0.3rem 0.8rem 0.3rem 0.8rem;\n border: 1px solid white;\n color: white;\n background-color: rgb(225, 51, 51, 80%);\n box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;\n}\n\n.delete-button:hover {\n background-color: rgb(229, 12, 12);\n}\n\nh4 {\n margin-bottom: 0.6rem;\n margin-top: 1rem;\n color: white;\n}\n\n.up,\n.down {\n border: none;\n background-color: rgb(48, 13, 81, 60%);\n height: 2rem;\n margin-top: 0.5rem;\n color: white;\n}\n\n.up {\n border-radius: 1rem 0 0 1rem;\n padding-left: 1rem;\n border-right: 1px solid rgb(155, 132, 165);\n border-top: solid 1px white;\n\n}\n\n.down {\n border-radius: 0 1rem 1rem 0;\n border-top: solid 1px white;\n}\n\n.tumb-up {\n width: 1rem;\n padding-bottom: 0.3rem;\n margin-right: 0.5rem;\n}\n\n.rate {\n text-align: right;\n}\n\n.tumb-down {\n -moz-transform: scale(-1, -1);\n -o-transform: scale(-1, -1);\n -webkit-transform: scale(-1, -1);\n transform: scale(-1, -1);\n width: 1rem;\n margin-right: 0.5rem;\n margin-left: 0.5rem;\n}\n\n.form-holder {\n width: 100%;\n min-height: 10rem;\n margin-bottom: 2rem;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n}\n\nform {\n width: 100%;\n min-height: 6rem;\n margin-top: 1rem;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n gap: 0.5rem;\n justify-content: center;\n align-items: center;\n\n}\n\n.form-holder input {\n width: 20rem;\n height: 2.5rem;\n margin-right: 1rem;\n border-radius: 2rem;\n border: rgb(157, 139, 184) solid 1px;\n background-color: rgb(255, 255, 255, 20%);\n padding-left: 1rem;\n padding-right: 1rem;\n color: white;\n}\n\n.form-holder ::placeholder {\n color: rgb(255, 255, 255, 60%);\n padding-left: 1rem;\n font-size: 12px;\n}\n\n.form-holder input:hover {\n background-color: rgb(255, 255, 255, 50%);\n}\n\n.form-holder input:focus {\n background-color: rgb(255, 255, 255, 80%);\n color: rgb(48, 48, 48);\n outline-width: 0;\n border-color: rgb(255, 255, 255);\n}\n\n.form-holder button {\n width: 10rem;\n height: 2.5rem;\n border-radius: 2rem;\n border: rgb(255, 255, 255, 60%) solid 1px;\n color: white;\n background: rgb(69, 48, 105);\n background: linear-gradient(336deg, rgba(69, 48, 105, 1) 15%, rgba(132, 105, 181, 1) 100%);\n box-shadow: rgba(0, 0, 0, 50%) 0px 3px 8px;\n}\n\n.form-holder button:hover {\n background: rgb(118, 92, 163);\n background: linear-gradient(336deg, rgba(118, 92, 163, 1) 15%, rgba(193, 152, 226, 1) 100%);\n}\n\nh3 {\n color: white;\n font-size: 18px;\n width: 80%;\n}\n\n.main-button-to-add {\n margin-bottom: 1.5rem;\n width: 10rem;\n height: 2.5rem;\n border-radius: 2rem;\n border: rgb(255, 255, 255, 60%) solid 1px;\n color: white;\n background: rgb(69, 48, 105);\n background: linear-gradient(336deg, rgba(69, 48, 105, 1) 15%, rgba(132, 105, 181, 1) 100%);\n box-shadow: rgba(0, 0, 0, 50%) 0px 3px 8px;\n}\n\n.main-button-to-add:focus {\n outline-width: 0;\n}\n\n.main-button-to-add:hover {\n width: 10.2rem;\n height: 2.6rem;\n}\n\nh1 {\n font-size: 40px;\n margin-top: 2rem;\n margin-bottom: 2rem;\n color: rgb(79, 64, 92);\n}\n\n.react-player {\n position: absolute;\n top: 0;\n left: 0;\n}\n\n.sorting-holder {\n color: white;\n width: 82%;\n margin: 0 auto;\n text-align: end;\n font-size: 18px;\n}\n\n.sorting-ratings-button {\n background-color: rgba(184, 184, 184, 59%);\n padding: 0.3rem;\n padding-top: 0.1rem;\n border-radius: 0.4rem;\n width: 2rem;\n border: none;\n margin-bottom: 1rem;\n margin-left: 0.5rem;\n\n}\n\n.sorting-ratings-button img {\n width: 1rem;\n}\n\n\n@media only screen and (max-width: 844px) {\n .react-player {\n position: absolute;\n top: 0;\n left: 0;\n\n }\n\n .video-holder {\n width: 100%;\n position: relative;\n padding-top: 56.25%;\n /* 720 / 1280 = 0.5625 */\n }\n\n .card {\n width: 96%;\n padding: 0.5rem;\n }\n\n form {\n width: 100%;\n min-height: 10rem;\n }\n\n h1 {\n font-size: 28px;\n }\n\n\n}"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/client/build/static/js/main.55683642.js b/client/build/static/js/main.55683642.js new file mode 100644 index 0000000000..072d73fb46 --- /dev/null +++ b/client/build/static/js/main.55683642.js @@ -0,0 +1,3 @@ +/*! For license information please see main.55683642.js.LICENSE.txt */ +!function(){var e={948:function(e){"use strict";var t=function(e){return function(e){return!!e&&"object"===typeof e}(e)&&!function(e){var t=Object.prototype.toString.call(e);return"[object RegExp]"===t||"[object Date]"===t||function(e){return e.$$typeof===n}(e)}(e)};var n="function"===typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function r(e,t){return!1!==t.clone&&t.isMergeableObject(e)?u((n=e,Array.isArray(n)?[]:{}),e,t):e;var n}function o(e,t,n){return e.concat(t).map((function(e){return r(e,n)}))}function a(e){return Object.keys(e).concat(function(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter((function(t){return e.propertyIsEnumerable(t)})):[]}(e))}function l(e,t){try{return t in e}catch(n){return!1}}function i(e,t,n){var o={};return n.isMergeableObject(e)&&a(e).forEach((function(t){o[t]=r(e[t],n)})),a(t).forEach((function(a){(function(e,t){return l(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))})(e,a)||(l(e,a)&&n.isMergeableObject(t[a])?o[a]=function(e,t){if(!t.customMerge)return u;var n=t.customMerge(e);return"function"===typeof n?n:u}(a,n)(e[a],t[a],n):o[a]=r(t[a],n))})),o}function u(e,n,a){(a=a||{}).arrayMerge=a.arrayMerge||o,a.isMergeableObject=a.isMergeableObject||t,a.cloneUnlessOtherwiseSpecified=r;var l=Array.isArray(n);return l===Array.isArray(e)?l?a.arrayMerge(e,n,a):i(e,n,a):r(n,a)}u.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array");return e.reduce((function(e,n){return u(e,n,t)}),{})};var c=u;e.exports=c},102:function(e){function t(e,t){e.onload=function(){this.onerror=this.onload=null,t(null,e)},e.onerror=function(){this.onerror=this.onload=null,t(new Error("Failed to load "+this.src),e)}}function n(e,t){e.onreadystatechange=function(){"complete"!=this.readyState&&"loaded"!=this.readyState||(this.onreadystatechange=null,t(null,e))}}e.exports=function(e,r,o){var a=document.head||document.getElementsByTagName("head")[0],l=document.createElement("script");"function"===typeof r&&(o=r,r={}),r=r||{},o=o||function(){},l.type=r.type||"text/javascript",l.charset=r.charset||"utf8",l.async=!("async"in r)||!!r.async,l.src=e,r.attrs&&function(e,t){for(var n in t)e.setAttribute(n,t[n])}(l,r.attrs),r.text&&(l.text=""+r.text),("onload"in l?t:n)(l,o),l.onload||t(l,o),a.appendChild(l)}},781:function(e,t,n){"use strict";n.r(t);var r=Number.isNaN||function(e){return"number"===typeof e&&e!==e};function o(e,t){if(e.length!==t.length)return!1;for(var n=0;n