diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index abfb6c4..d7e67fc 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -2,48 +2,61 @@ name: Docker on: push: - # Publish `main` as Docker `latest` image. - branches: - - main + branches: [ "main" ] + pull_request: + branches: [ "main" ] + workflow_dispatch: + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: ghcr.io + # github.repository as / + IMAGE_NAME: ${{ github.repository }} jobs: # Push image to GitHub Packages. # See also https://docs.docker.com/docker-hub/builds/ - push: - - runs-on: ubuntu-20.04 + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write steps: - - name: Checkout - uses: actions/checkout@v2 + - name: Checkout repository + uses: actions/checkout@v4 + + # Workaround: https://github.com/docker/build-push-action/issues/461 + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3 - - name: Login to DockerHub - uses: docker/login-action@v1 + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 with: - username: ${{ secrets.DOCKERHUB_USER }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Setup Docker build - id: buildx - uses: docker/setup-buildx-action@v1 - - - name: Build and push backend - id: docker_build_backend - uses: docker/build-push-action@v2 + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 with: - context: ./lasvecka-python - file: ./lasvecka-python/prod.Dockerfile - push: true - tags: gudchs/lasvecka_backend:latest - - - name: Build and push frontend - id: docker_build_frontend - uses: docker/build-push-action@v2 + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v5 with: - context: ./lasvecka-react - file: ./lasvecka-react/prod.Dockerfile - push: true - tags: gudchs/lasvecka_frontend:latest - - - name: Image digest - run: echo ${{ steps.docker_build.outputs.digest }} + context: ./lasvecka-node + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/dev.docker-compose.yaml b/dev.docker-compose.yaml index 21ba620..db729a4 100644 --- a/dev.docker-compose.yaml +++ b/dev.docker-compose.yaml @@ -1,23 +1,12 @@ -version: '2' +version: "3" services: - backend: - container_name: lasvecka-python + app: + container_name: lasvecka-node build: - context: ./lasvecka-python - dockerfile: dev.Dockerfile - ports: - - 5000:5000 - volumes: - - ./backend:/lasvecka-python - - frontend: - container_name: lasvecka-react - build: - context: ./lasvecka-react - dockerfile: dev.Dockerfile - stdin_open: true + context: ./lasvecka-node + dockerfile: Dockerfile ports: - 3000:3000 volumes: - - ./frontend:/usr/src/lasveckor/frontend + - ./data:/usr/src/app/data diff --git a/lasvecka-node/Dockerfile b/lasvecka-node/Dockerfile new file mode 100644 index 0000000..e702d08 --- /dev/null +++ b/lasvecka-node/Dockerfile @@ -0,0 +1,19 @@ +FROM node:lts + +# Create app directory +WORKDIR /usr/src/app + +# Install app dependencies +# A wildcard is used to ensure both package.json AND package-lock.json are copied +# where available (npm@5+) +COPY package*.json ./ + +RUN npm install +# If you are building your code for production +# RUN npm ci --only=production + +# Bundle app source +COPY . . + +EXPOSE 3000 +CMD [ "node", "index.js" ] \ No newline at end of file diff --git a/lasvecka-node/calc_date.js b/lasvecka-node/calc_date.js new file mode 100644 index 0000000..1cbbd69 --- /dev/null +++ b/lasvecka-node/calc_date.js @@ -0,0 +1,81 @@ +const moment = require('moment'); +const fs = require('fs'); +const scrape = require('./lasveckor_scraper.js'); +var dateDict = {}; + +// check if data.json exists +if (!fs.existsSync('./data/data.json')) { + scrape().then((res) => { + dateDict = res + }); +} else { + dateDict = JSON.parse(fs.readFileSync('./data/data.json')); + + //check if it was updated after 1/7 this year and if 1/7 has occured this year + let updated = moment(dateDict["updated"]); + let firstOfJuly = moment().month(6).date(1); + if (updated.isBefore(firstOfJuly) && moment().isAfter(firstOfJuly)) { + scrape().then((res) => { + dateDict = res + }); + } +} + +function readDatePeriod(currDate) { + let soughtDate = ""; + let diff = -1000; + for (let dat in dateDict) { + // if dat is updated, easter_start, easter_end or ord_cont then skip + if (dat === "updated" || dat === "easter_start" || dat === "easter_end" || dat === "ord_cont") { + continue; + } + let deltaT = moment(dat).diff(currDate, 'days'); + if (deltaT === 0) { + return { date: dat, type: dateDict[dat] }; + } else if (deltaT > diff && deltaT < 0) { + soughtDate = dat; + diff = deltaT; + } + } + return { date: soughtDate, type: dateDict[soughtDate] }; +} + +function handleEaster(easterStartDiff, easterEndDiff) { + if (easterStartDiff >= 0 && easterEndDiff <= 0) { + return "Självstudier"; + } else if (easterEndDiff > 0) { + let weeks = Math.floor(easterEndDiff / 7); + return "Lv " + (weeks + 4); + } +} + +function computeTime() { + // Find date where value is easter_start, easter_end and ord_cont in json file + let EASTER_START = dateDict["easter_start"] + let ORD_CONT = dateDict["ord_cont"] + let currentDate = moment(); + let easterEndCheck = currentDate.diff(ORD_CONT, 'days'); + let easterStartCheck = currentDate.diff(EASTER_START, 'days'); + let { date: dat, type: typ } = readDatePeriod(currentDate); + if (typ === "exam_period") { + let deltaT = currentDate.diff(moment(dat), 'days'); + if (deltaT > 7) { + return "Självstudier"; + } else { + return "Tentavecka"; + } + } + if (easterEndCheck >= 0 || easterStartCheck >= 0) { + return handleEaster(easterStartCheck, easterEndCheck); + } else { + let deltaT = currentDate.diff(moment(dat), 'days'); + let weeks = Math.floor(deltaT / 7); + if (weeks > 7) { + return "Självstudier"; + } else { + return "LV " + (weeks + 1); + } + } +} + +module.exports = computeTime; \ No newline at end of file diff --git a/lasvecka-node/data/data.json b/lasvecka-node/data/data.json new file mode 100644 index 0000000..401a159 --- /dev/null +++ b/lasvecka-node/data/data.json @@ -0,0 +1 @@ +{"2023-08-28":"study_period","2023-10-21":"exam_period","2023-10-30":"study_period","2024-01-08":"exam_period","2024-01-15":"study_period","2024-03-09":"exam_period","2024-03-18":"study_period","easter_start":"2024-04-03","easter_end":"2024-04-05","ord_cont":"2024-04-08","2024-05-25":"exam_period","updated":"2023-11-06"} \ No newline at end of file diff --git a/lasvecka-node/index.js b/lasvecka-node/index.js new file mode 100644 index 0000000..6aadcc7 --- /dev/null +++ b/lasvecka-node/index.js @@ -0,0 +1,91 @@ +const express = require('express'); +const moment = require('moment'); +const app = express(); +const computeTime = require('./calc_date.js'); +const port = process.env.PORT || 3000; + +app.use(express.static('public')); + +app.get('/', (req, res) => { + let studyweek = computeTime(); + let studyweekNum = studyweek.replace('LV ', '').replace('Självstudier', 'S').replace('Tentavecka', 'T'); + // eg. 2023-W45 + let week = moment().format('YYYY-[W]WW'); + let data = { studyweek, week, studyweekNum }; + res.send(render(data)); +}); + +app.get('/api', (req, res) => { + res.send(computeTime()); +}); + +app.listen(port, () => { + console.log(`App listening at http://localhost:${port}`) +}) + +const render = (data) => { + const html = ` + + + + + läsvecka.nu | ${data.studyweek} + + + + + + + + + + + + + + +`; + return html.replace(/\n/g, '').replace(/\r/g, '').replace(/\t/g, '').replace(/ {2,}/g, ''); +} \ No newline at end of file diff --git a/lasvecka-node/lasveckor_scraper.js b/lasvecka-node/lasveckor_scraper.js new file mode 100644 index 0000000..c25144c --- /dev/null +++ b/lasvecka-node/lasveckor_scraper.js @@ -0,0 +1,51 @@ +const fs = require('fs'); +const axios = require('axios'); + +async function scrape() { + console.log("Scraping data from student.chalmers.se") + let url = "https://www.student.chalmers.se/sp/academic_year_list" + + const response = await axios.get(url, { responseType: "arraybuffer" }) + let data = response.data.toString('latin1'); + + data = data.replace(/\n/g, '').replace(/\r/g, '').replace(/\t/g, ''); + data = data.match(/(.*?)<\/table>/s)[0] + + // some things to make it nicer + data = data.replace(/<\/tr>/g, '\n') + data = data.replace(//g, '') + data = data.replace(//g, '') + data = data.replace(/
/g, '') + data = data.replace(/<\/td>/g, '') + data = data.split('\n') + + let result = {} + for (let i = 0; i < data.length; i++) { + let line = data[i] + if (line.startsWith('Läsperiod')) { + let date = line.match(/(\d{4}-\d{2}-\d{2})/)[0] + result[date] = "study_period" + } else if (line.startsWith('Tentamensperiod')) { + let date = line.match(/(\d{4}-\d{2}-\d{2})/)[0] + result[date] = "exam_period" + } else if (line.startsWith("Omtentamensperiod påsk")) { + let date1 = line.match(/(\d{4}-\d{2}-\d{2})/)[0] + let date2 = line.match(/(\d{4}-\d{2}-\d{2})/g)[1] + result["easter_start"] = date1 + result["easter_end"] = date2 + + var easter_start = new Date(date1) + // find first monday after easter + while (easter_start.getDay() != 1) { + easter_start.setDate(easter_start.getDate() + 1) + } + result["ord_cont"] = easter_start.toISOString().slice(0, 10) + } + } + + result["updated"] = new Date().toISOString().slice(0, 10) + await fs.promises.writeFile('./data/data.json', JSON.stringify(result)) + return result +} + +module.exports = scrape; \ No newline at end of file diff --git a/lasvecka-node/package-lock.json b/lasvecka-node/package-lock.json new file mode 100644 index 0000000..7345148 --- /dev/null +++ b/lasvecka-node/package-lock.json @@ -0,0 +1,738 @@ +{ + "name": "lasvecka-node", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "lasvecka-node", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^1.6.0", + "express": "^4.18.2", + "moment": "^2.29.4" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + } + } +} diff --git a/lasvecka-node/package.json b/lasvecka-node/package.json new file mode 100644 index 0000000..e41e3de --- /dev/null +++ b/lasvecka-node/package.json @@ -0,0 +1,16 @@ +{ + "name": "lasvecka-node", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^1.6.0", + "express": "^4.18.2", + "moment": "^2.29.4" + } +} diff --git a/lasvecka-node/public/android-chrome-192x192.png b/lasvecka-node/public/android-chrome-192x192.png new file mode 100644 index 0000000..7c4847e Binary files /dev/null and b/lasvecka-node/public/android-chrome-192x192.png differ diff --git a/lasvecka-node/public/android-chrome-512x512.png b/lasvecka-node/public/android-chrome-512x512.png new file mode 100644 index 0000000..1bd741c Binary files /dev/null and b/lasvecka-node/public/android-chrome-512x512.png differ diff --git a/lasvecka-node/public/apple-touch-icon.png b/lasvecka-node/public/apple-touch-icon.png new file mode 100644 index 0000000..3bf7c06 Binary files /dev/null and b/lasvecka-node/public/apple-touch-icon.png differ diff --git a/lasvecka-node/public/favicon-16x16.png b/lasvecka-node/public/favicon-16x16.png new file mode 100644 index 0000000..735ced4 Binary files /dev/null and b/lasvecka-node/public/favicon-16x16.png differ diff --git a/lasvecka-node/public/favicon-32x32.png b/lasvecka-node/public/favicon-32x32.png new file mode 100644 index 0000000..01d004e Binary files /dev/null and b/lasvecka-node/public/favicon-32x32.png differ diff --git a/lasvecka-node/public/favicon.ico b/lasvecka-node/public/favicon.ico new file mode 100644 index 0000000..60dea7c Binary files /dev/null and b/lasvecka-node/public/favicon.ico differ diff --git a/lasvecka-node/public/faviconbkg.png b/lasvecka-node/public/faviconbkg.png new file mode 100644 index 0000000..6cf30ec Binary files /dev/null and b/lasvecka-node/public/faviconbkg.png differ diff --git a/lasvecka-react/public/robots.txt b/lasvecka-node/public/robots.txt similarity index 100% rename from lasvecka-react/public/robots.txt rename to lasvecka-node/public/robots.txt diff --git a/lasvecka-node/public/site.webmanifest b/lasvecka-node/public/site.webmanifest new file mode 100644 index 0000000..693635a --- /dev/null +++ b/lasvecka-node/public/site.webmanifest @@ -0,0 +1 @@ +{"name":"läsvecka.nu","short_name":"läsvecka.nu","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#1c7bb7","background_color":"#90c0de","display":"standalone"} \ No newline at end of file diff --git a/lasvecka-node/public/sitemap.xml b/lasvecka-node/public/sitemap.xml new file mode 100644 index 0000000..4218419 --- /dev/null +++ b/lasvecka-node/public/sitemap.xml @@ -0,0 +1,14 @@ + + + + + https://lasvecka.nu/ + + + https://läsvecka.nu/ + + \ No newline at end of file diff --git a/lasvecka-python/__pycache__/calc_date.cpython-39.pyc b/lasvecka-python/__pycache__/calc_date.cpython-39.pyc deleted file mode 100644 index a571ccd..0000000 Binary files a/lasvecka-python/__pycache__/calc_date.cpython-39.pyc and /dev/null differ diff --git a/lasvecka-python/app.py b/lasvecka-python/app.py deleted file mode 100644 index 734b6a2..0000000 --- a/lasvecka-python/app.py +++ /dev/null @@ -1,29 +0,0 @@ -from flask import Flask, jsonify -from flask_cors import CORS -from waitress import serve -from calc_date import compute_time -import json - -# configuration -DEBUG = False - -# init app -app = Flask(__name__) -app.config.from_object(__name__) - -# enable CORS -CORS(app, resources={r'/*': {'origins': '*'}}) - -# return the string be used in the frontend as a JSON-object -@app.route('/getData') -def get_studyweek(): - return jsonify(compute_time()) - - -# http://localhost:5000 -if __name__ == '__main__': - # Dev purposes only - # app.run(host="0.0.0.0") - - # For prod - serve(app, listen='0.0.0.0:5000') diff --git a/lasvecka-python/calc_date.py b/lasvecka-python/calc_date.py deleted file mode 100644 index 7e85fc5..0000000 --- a/lasvecka-python/calc_date.py +++ /dev/null @@ -1,66 +0,0 @@ -from datetime import date - -EASTER_START = date.fromisoformat("2024-04-03") -EASTER_END = date.fromisoformat("2024-04-05") -ORD_CONT = date.fromisoformat("2024-04-08") - -# Find the appropiate date & period from data.txt (the output from the webscraper) -def read_date_period(curr_date): - sought_date = "" - diff = -1000 - with open('data.txt', 'r') as data_file: - date_dict = eval(data_file.read()) - for dat, typ in date_dict.items(): - delta_t = date.fromisoformat(dat) - curr_date - if delta_t.days == 0: - return (dat, typ) - elif delta_t.days > diff and delta_t.days < 0: - sought_date = dat - diff = delta_t.days - return(sought_date, date_dict[sought_date]) - - - - -def handle_easter(easter_start_diff, easter_end_diff): - # Checks if it's easter - if easter_start_diff.days >= 0 and easter_end_diff.days <= 0: - return("Självstudier") - # Add offset, will go up to Lv 8 until regular exam period - elif easter_end_diff.days > 0: - weeks, _ = divmod(easter_end_diff.days, 7) - return ("Lv " + str(weeks + 4)) - - - -# Computes and determines the week of the study period, or returns Självstudier/Tentavecka if it's Easter or -# exam period. -def compute_time(): - current_date = date.today() - # Calculates diffs for easter handling - easter_end_check = current_date - ORD_CONT - easter_start_check = current_date - EASTER_START - dat, typ = read_date_period(current_date) - # Is it exam period? Also check for final exam period - if typ == "exam_period": - delta_t = current_date - date.fromisoformat(dat) - if delta_t.days > 7: - return "Självstudier" - else: - return "Tentavecka" - # Is it easter or after easter? Call handle_easter - if easter_end_check.days >= 0 or easter_start_check.days >= 0: - return (handle_easter(easter_start_check, easter_end_check)) - else: - # Regular time handling - delta_t = current_date - date.fromisoformat(dat) - weeks, _ = divmod(delta_t.days, 7) - if weeks > 7: - return ("Självstudier") - else: - # divmod will interpret the first study week as week 0 - return ("LV " + str(weeks + 1)) - - -if __name__ == '__main__': - compute_time() diff --git a/lasvecka-python/data.txt b/lasvecka-python/data.txt deleted file mode 100644 index ed9dcce..0000000 --- a/lasvecka-python/data.txt +++ /dev/null @@ -1 +0,0 @@ -{"2023-08-28": "study_period", "2023-10-21": "exam_period", "2023-10-30": "study_period", "2024-01-08": "exam_period", "2024-01-15": "study_period", "2024-03-09": "exam_period", "2024-03-18": "study_period", "2024-05-25": "exam_period"} \ No newline at end of file diff --git a/lasvecka-python/dev.Dockerfile b/lasvecka-python/dev.Dockerfile deleted file mode 100644 index 0d8e1ee..0000000 --- a/lasvecka-python/dev.Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM python:3-alpine - -COPY . /app - -WORKDIR /app - -RUN pip install -r requirements.text - -ENTRYPOINT ["python"] - -CMD ["app.py"] - -EXPOSE 5000 diff --git a/lasvecka-python/lasveckor_scraper.py b/lasvecka-python/lasveckor_scraper.py deleted file mode 100644 index aa8b198..0000000 --- a/lasvecka-python/lasveckor_scraper.py +++ /dev/null @@ -1,52 +0,0 @@ -import requests -import json -from bs4 import BeautifulSoup - -url = 'https://student.portal.chalmers.se/sv/chalmersstudier/Sidor/Lasarstider.aspx' - -response = requests.get(url) - -soup = BeautifulSoup(response.text, "html.parser") - -text = soup.findAll('span') - -# For debugging purposes -def test_scrape(): - # Test the output of scraper - current_line = 0 - for line in text: - if line.string is not None: - if "Självstudier" in line.string or "påsk" in line.string: - print(text[current_line + 2].string) - current_line = current_line + 1 - - -# Iterate through text to find specific lines which are then used to determine -# the position of sought dates. Dumps the results as a json-formatted object -# in source directory in a txt file -def scrape(): - # Store dates when a period starts - data = {} - current_line = 0 - for line in text: - if line.string is not None: - if "Läsperiod" in line.string: - # print(text[current_line + 2].string) - data[text[current_line + 2].string] = "study_period" - # data.append((text[current_line + 2].string, "study_period")) - if "Tentamensperiod" in line.string: - # print(text[current_line + 2].string) - # data.append((text[current_line + 2].string, "exam_period")) - data[text[current_line + 2].string] = "exam_period" - # if "Omtentamensperiod" in line.string: - # print(text[current_line + 2].string) - # data.append((text[current_line + 2].string, "reexam_period")) - # data[text[current_line + 2].string] = "reexam_period" - current_line = current_line + 1 - with open('data.txt', 'w') as outfile: - outfile.write(json.dumps(data)) - - -if __name__ == '__main__': - # test_scrape() - scrape() diff --git a/lasvecka-python/prod.Dockerfile b/lasvecka-python/prod.Dockerfile deleted file mode 100644 index 0d8e1ee..0000000 --- a/lasvecka-python/prod.Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM python:3-alpine - -COPY . /app - -WORKDIR /app - -RUN pip install -r requirements.text - -ENTRYPOINT ["python"] - -CMD ["app.py"] - -EXPOSE 5000 diff --git a/lasvecka-python/requirements.text b/lasvecka-python/requirements.text deleted file mode 100644 index 9ba036c..0000000 --- a/lasvecka-python/requirements.text +++ /dev/null @@ -1,4 +0,0 @@ -flask -flask_cors -waitress -jsonify diff --git a/lasvecka-react/.dockerignore b/lasvecka-react/.dockerignore deleted file mode 100644 index 04953aa..0000000 --- a/lasvecka-react/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -build -.dockerignore -Dockerfile -Dockerfile.prod diff --git a/lasvecka-react/README.md b/lasvecka-react/README.md deleted file mode 100644 index 9c40dcd..0000000 --- a/lasvecka-react/README.md +++ /dev/null @@ -1,68 +0,0 @@ -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). - -## Available Scripts - -In the project directory, you can run: - -### `yarn start` - -Runs the app in the development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will reload if you make edits.
-You will also see any lint errors in the console. - -### `yarn test` - -Launches the test runner in the interactive watch mode.
-See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. - -### `yarn build` - -Builds the app for production to the `build` folder.
-It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.
-Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `yarn eject` - -**Note: this is a one-way operation. Once you `eject`, you can’t go back!** - -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. - -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). - -### Code Splitting - -This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting - -### Analyzing the Bundle Size - -This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size - -### Making a Progressive Web App - -This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app - -### Advanced Configuration - -This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration - -### Deployment - -This section has moved here: https://facebook.github.io/create-react-app/docs/deployment - -### `yarn build` fails to minify - -This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify diff --git a/lasvecka-react/dev.Dockerfile b/lasvecka-react/dev.Dockerfile deleted file mode 100644 index 49f494d..0000000 --- a/lasvecka-react/dev.Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM node:18 - -WORKDIR /app - -COPY . . - -RUN yarn install -RUN yarn upgrade --latest - -CMD yarn start - -EXPOSE 3000 diff --git a/lasvecka-react/nginx.conf b/lasvecka-react/nginx.conf deleted file mode 100644 index 0268fed..0000000 --- a/lasvecka-react/nginx.conf +++ /dev/null @@ -1,11 +0,0 @@ -server { - - listen 80; - server_name localhost; - - location / { - root /usr/share/nginx/html; - index index.html; - try_files $uri $uri/ /index.html; - } -} diff --git a/lasvecka-react/package.json b/lasvecka-react/package.json deleted file mode 100755 index b5313ac..0000000 --- a/lasvecka-react/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "lasvecka-react", - "version": "0.1.0", - "private": true, - "dependencies": { - "@testing-library/jest-dom": "^4.2.4", - "@testing-library/react": "^9.3.2", - "@testing-library/user-event": "^7.1.2", - "axios": "^0.19.2", - "react": "^16.13.1", - "react-dom": "^16.13.1", - "react-scripts": "3.4.1", - "serve": "^11.3.2", - "yarn": "^1.22.4" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" - }, - "eslintConfig": { - "extends": "react-app" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/lasvecka-react/prod.Dockerfile b/lasvecka-react/prod.Dockerfile deleted file mode 100644 index 74dc39d..0000000 --- a/lasvecka-react/prod.Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM node:18 AS build-step - -RUN mkdir -p /usr/src/lasveckor/frontend -RUN chown -R node:node /usr/src/lasveckor/frontend - -USER root - -WORKDIR /usr/src/lasveckor/frontend - -COPY . . -COPY ["package.json", "./"] - -RUN yarn install -RUN yarn upgrade --latest -RUN yarn global add react-scripts -RUN yarn build - -FROM nginx:alpine -RUN rm /etc/nginx/conf.d/* -COPY nginx.conf /etc/nginx/conf.d/nginx.conf -COPY --from=build-step /usr/src/lasveckor/frontend/build /usr/share/nginx/html diff --git a/lasvecka-react/public/favicon.ico b/lasvecka-react/public/favicon.ico deleted file mode 100644 index 3a236cc..0000000 Binary files a/lasvecka-react/public/favicon.ico and /dev/null differ diff --git a/lasvecka-react/public/index.html b/lasvecka-react/public/index.html deleted file mode 100644 index fe1b86e..0000000 --- a/lasvecka-react/public/index.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - Läsvecka - - - -
- - - diff --git a/lasvecka-react/src/App.css b/lasvecka-react/src/App.css deleted file mode 100644 index 2a31985..0000000 --- a/lasvecka-react/src/App.css +++ /dev/null @@ -1,4 +0,0 @@ -.App { - background-color: #90c0de; - overflow: hidden; -} diff --git a/lasvecka-react/src/App.js b/lasvecka-react/src/App.js deleted file mode 100644 index cb3882e..0000000 --- a/lasvecka-react/src/App.js +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; -import WeekDisplay from "./Components/WeekDisplay"; -import "./App.css"; - -function App() { - console.log("Powered by G.U.D."); - return ( -
- -
- ); -} - -export default App; diff --git a/lasvecka-react/src/App.test.js b/lasvecka-react/src/App.test.js deleted file mode 100644 index 4db7ebc..0000000 --- a/lasvecka-react/src/App.test.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - const { getByText } = render(); - const linkElement = getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/lasvecka-react/src/Components/WeekDisplay.jsx b/lasvecka-react/src/Components/WeekDisplay.jsx deleted file mode 100644 index 11a7be0..0000000 --- a/lasvecka-react/src/Components/WeekDisplay.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import React, { Component } from "react"; -import axios from "axios"; -import '../Style/WeekDisplay.css'; - -class WeekDisplay extends Component { - constructor(props) { - super(props); - - this.state = { - data: "" - }; - } - - // React hook to rerender the page when data is successfully loaded from - // backend - // Use localhost:5000/getData for dev - componentDidMount() { - axios - .get("https://api.lasvecka.nu/getData") - .then(res => { - this.setState({ - data: res.data - }); - }) - .catch(err => { - console.log(err); - }); - } - - /* - Generates the text to be rendered on the webpage, returns "Självstudier" - if data hasn't been loaded from the backend. - */ - genText = () => { - let data = this.state.data - if (data !== 'undefined' && data.length > 0) { - return data; - } else { - return "" - } - - } - - render() { - return ( -
-

{this.genText()}

-
- ); - } -} - -export default WeekDisplay; diff --git a/lasvecka-react/src/Style/WeekDisplay.css b/lasvecka-react/src/Style/WeekDisplay.css deleted file mode 100644 index b653649..0000000 --- a/lasvecka-react/src/Style/WeekDisplay.css +++ /dev/null @@ -1,14 +0,0 @@ -.WeekDisplayText { - position: absolute; - top: 50%; - left: 0; - right: 0; - text-align: center; - font-size: 260px; - font-weight: bold; - font-family: Arial, serif; - line-height: 227px; - margin: -110px 0 0 0; - height: 220px; - color: #1c7bb7; -} \ No newline at end of file diff --git a/lasvecka-react/src/index.css b/lasvecka-react/src/index.css deleted file mode 100644 index c174697..0000000 --- a/lasvecka-react/src/index.css +++ /dev/null @@ -1,20 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - overflow: hidden; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} - -html { - height: 100%; - overflow: hidden; - background-color: #90c0de; -} diff --git a/lasvecka-react/src/index.js b/lasvecka-react/src/index.js deleted file mode 100644 index f5185c1..0000000 --- a/lasvecka-react/src/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import './index.css'; -import App from './App'; -import * as serviceWorker from './serviceWorker'; - -ReactDOM.render( - - - , - document.getElementById('root') -); - -// If you want your app to work offline and load faster, you can change -// unregister() to register() below. Note this comes with some pitfalls. -// Learn more about service workers: https://bit.ly/CRA-PWA -serviceWorker.unregister(); diff --git a/lasvecka-react/src/serviceWorker.js b/lasvecka-react/src/serviceWorker.js deleted file mode 100644 index b04b771..0000000 --- a/lasvecka-react/src/serviceWorker.js +++ /dev/null @@ -1,141 +0,0 @@ -// This optional code is used to register a service worker. -// register() is not called by default. - -// This lets the app load faster on subsequent visits in production, and gives -// it offline capabilities. However, it also means that developers (and users) -// will only see deployed updates on subsequent visits to a page, after all the -// existing tabs open on the page have been closed, since previously cached -// resources are updated in the background. - -// To learn more about the benefits of this model and instructions on how to -// opt-in, read https://bit.ly/CRA-PWA - -const isLocalhost = Boolean( - window.location.hostname === 'localhost' || - // [::1] is the IPv6 localhost address. - window.location.hostname === '[::1]' || - // 127.0.0.0/8 are considered localhost for IPv4. - window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ - ) -); - -export function register(config) { - if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { - // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); - if (publicUrl.origin !== window.location.origin) { - // Our service worker won't work if PUBLIC_URL is on a different origin - // from what our page is served on. This might happen if a CDN is used to - // serve assets; see https://github.com/facebook/create-react-app/issues/2374 - return; - } - - window.addEventListener('load', () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - - if (isLocalhost) { - // This is running on localhost. Let's check if a service worker still exists or not. - checkValidServiceWorker(swUrl, config); - - // Add some additional logging to localhost, pointing developers to the - // service worker/PWA documentation. - navigator.serviceWorker.ready.then(() => { - console.log( - 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://bit.ly/CRA-PWA' - ); - }); - } else { - // Is not localhost. Just register service worker - registerValidSW(swUrl, config); - } - }); - } -} - -function registerValidSW(swUrl, config) { - navigator.serviceWorker - .register(swUrl) - .then(registration => { - registration.onupdatefound = () => { - const installingWorker = registration.installing; - if (installingWorker == null) { - return; - } - installingWorker.onstatechange = () => { - if (installingWorker.state === 'installed') { - if (navigator.serviceWorker.controller) { - // At this point, the updated precached content has been fetched, - // but the previous service worker will still serve the older - // content until all client tabs are closed. - console.log( - 'New content is available and will be used when all ' + - 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' - ); - - // Execute callback - if (config && config.onUpdate) { - config.onUpdate(registration); - } - } else { - // At this point, everything has been precached. - // It's the perfect time to display a - // "Content is cached for offline use." message. - console.log('Content is cached for offline use.'); - - // Execute callback - if (config && config.onSuccess) { - config.onSuccess(registration); - } - } - } - }; - }; - }) - .catch(error => { - console.error('Error during service worker registration:', error); - }); -} - -function checkValidServiceWorker(swUrl, config) { - // Check if the service worker can be found. If it can't reload the page. - fetch(swUrl, { - headers: { 'Service-Worker': 'script' }, - }) - .then(response => { - // Ensure service worker exists, and that we really are getting a JS file. - const contentType = response.headers.get('content-type'); - if ( - response.status === 404 || - (contentType != null && contentType.indexOf('javascript') === -1) - ) { - // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then(registration => { - registration.unregister().then(() => { - window.location.reload(); - }); - }); - } else { - // Service worker found. Proceed as normal. - registerValidSW(swUrl, config); - } - }) - .catch(() => { - console.log( - 'No internet connection found. App is running in offline mode.' - ); - }); -} - -export function unregister() { - if ('serviceWorker' in navigator) { - navigator.serviceWorker.ready - .then(registration => { - registration.unregister(); - }) - .catch(error => { - console.error(error.message); - }); - } -} diff --git a/lasvecka-react/src/setupTests.js b/lasvecka-react/src/setupTests.js deleted file mode 100644 index 74b1a27..0000000 --- a/lasvecka-react/src/setupTests.js +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom/extend-expect'; diff --git a/prod.docker-compose.yml b/prod.docker-compose.yml index fe1e69c..e157d1a 100644 --- a/prod.docker-compose.yml +++ b/prod.docker-compose.yml @@ -1,31 +1,14 @@ -version: '2' +version: '3' services: - backend: - container_name: lasvecka-python - image: gudchs/lasvecka_backend:latest - network_mode: "nginxreverseproxy_default" - volumes: - - LasveckaBackend:/lasvecka-python - environment: - VIRTUAL_HOST: api.lasvecka.nu - VIRTUAL_PORT: 5000 - LETSENCRYPT_HOST: api.lasvecka.nu + app: + container_name: lasvecka-node + iamge: ghcr.io/gudchs/lasvecka:main restart: unless-stopped - - frontend: - container_name: lasvecka-react - image: gudchs/lasvecka_frontend:latest - stdin_open: true - network_mode: "nginxreverseproxy_default" + ports: + - 3000:3000 volumes: - - LasveckaFrontend:/usr/src/lasveckor/frontend - environment: - VIRTUAL_HOST: lasvecka.nu,www.lasvecka.nu,xn--lsvecka-5wa.nu,www.xn--lsvecka-5wa.nu - - LETSENCRYPT_HOST: lasvecka.nu,www.lasvecka.nu,xn--lsvecka-5wa.nu,www.xn--lsvecka-5wa.nu - restart: unless-stopped + - lasvecka:/usr/src/app/data volumes: - LasveckaFrontend: - LasveckaBackend: + lasvecka: diff --git a/release.sh b/release.sh deleted file mode 100644 index db0f031..0000000 --- a/release.sh +++ /dev/null @@ -1,9 +0,0 @@ -# Frontend -docker build --tag lasvecka_frontend:latest -f ./lasvecka-react/prod.Dockerfile ./lasvecka-react -docker tag lasvecka_frontend:latest gudchs/lasvecka_frontend:latest -docker push gudchs/lasvecka_frontend:latest - -# Backend -docker build --tag lasvecka_backend:latest -f ./lasvecka-python/dev.Dockerfile ./lasvecka-python -docker tag lasvecka_backend:latest gudchs/lasvecka_backend:latest -docker push gudchs/lasvecka_backend:latest