diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 489e4aaa7..7e1212b53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,15 +14,15 @@ jobs: runs-on: ubuntu-20.04 container: node:14.16-alpine steps: - - name: checkout + - name: Checkout uses: actions/checkout@v2 - - name: install dependencies + - name: Install dependencies env: HUSKY_SKIP_INSTALL: 1 run: yarn - - name: lint + - name: Lint run: yarn lint - - name: build + - name: Build run: yarn build build_and_push: @@ -70,7 +70,7 @@ jobs: ghcr.io/sct/overseerr:develop ghcr.io/sct/overseerr:${{ github.sha }} cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache-new + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - # Temporary fix # https://github.com/docker/build-push-action/issues/252 # https://github.com/moby/buildkit/issues/1896 diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml new file mode 100644 index 000000000..9f05f86e8 --- /dev/null +++ b/.github/workflows/preview.yml @@ -0,0 +1,44 @@ +name: Overseerr Preview + +on: + push: + tags: + - 'preview-*' + +jobs: + build_and_push: + name: Build & Publish Docker Preview Images + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Get the version + id: get_version + run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/} + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Log in to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Log in to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + file: ./Dockerfile + platforms: linux/amd64 + push: true + build-args: | + COMMIT_TAG=${{ github.sha }} + tags: | + sctx/overseerr:${{ steps.get_version.outputs.VERSION }} + ghcr.io/sct/overseerr:${{ steps.get_version.outputs.VERSION }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 62b2ecb1e..8ff0fbb77 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,16 +11,17 @@ jobs: runs-on: ubuntu-20.04 container: node:14.16-alpine steps: - - name: checkout + - name: Checkout uses: actions/checkout@v2 - - name: install dependencies + - name: Install dependencies env: HUSKY_SKIP_INSTALL: 1 run: yarn - - name: lint + - name: Lint run: yarn lint - - name: build + - name: Build run: yarn build + semantic-release: name: Tag and release latest version needs: test @@ -57,6 +58,7 @@ jobs: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} run: npx semantic-release + build-snap: name: Build Snap Package (${{ matrix.architecture }}) needs: semantic-release @@ -77,7 +79,6 @@ jobs: run: git checkout master - name: Pull latest changes run: git pull - - name: Prepare id: prepare run: | @@ -87,35 +88,31 @@ jobs: else echo ::set-output name=RELEASE::edge fi - - name: Set Up QEMU uses: docker/setup-qemu-action@v1 with: image: tonistiigi/binfmt@sha256:df15403e06a03c2f461c1f7938b171fda34a5849eb63a70e2a2109ed5a778bde - - name: Build Snap Package uses: diddlesnaps/snapcraft-multiarch-action@v1 id: build with: architecture: ${{ matrix.architecture }} - - name: Upload Snap Package uses: actions/upload-artifact@v2 with: name: overseerr-snap-package-${{ matrix.architecture }} path: ${{ steps.build.outputs.snap }} - - name: Review Snap Package uses: diddlesnaps/snapcraft-review-tools-action@v1.2.0 with: snap: ${{ steps.build.outputs.snap }} - - name: Publish Snap Package uses: snapcore/action-publish@v1 with: store_login: ${{ secrets.SNAP_LOGIN }} snap: ${{ steps.build.outputs.snap }} release: ${{ steps.prepare.outputs.RELEASE }} + discord: name: Send Discord Notification needs: semantic-release @@ -124,7 +121,6 @@ jobs: steps: - name: Get Build Job Status uses: technote-space/workflow-conclusion-action@v2.1.5 - - name: Combine Job Status id: status run: | @@ -134,7 +130,6 @@ jobs: else echo ::set-output name=status::$WORKFLOW_CONCLUSION fi - - name: Post Status to Discord uses: sarisia/actions-status-discord@v1 with: diff --git a/.github/workflows/snap.yaml b/.github/workflows/snap.yaml index ea7f92f9e..b0b5a3992 100644 --- a/.github/workflows/snap.yaml +++ b/.github/workflows/snap.yaml @@ -22,15 +22,15 @@ jobs: runs-on: ubuntu-20.04 container: node:14.16-alpine steps: - - name: checkout + - name: Checkout uses: actions/checkout@v2 - - name: install dependencies + - name: Install dependencies env: HUSKY_SKIP_INSTALL: 1 run: yarn - - name: lint + - name: Lint run: yarn lint - - name: build + - name: Build run: yarn build build-snap: diff --git a/Dockerfile b/Dockerfile index 9a5af8ca7..eda37b312 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,28 +1,30 @@ FROM node:14.16-alpine AS BUILD_IMAGE +WORKDIR /app + ARG TARGETPLATFORM ENV TARGETPLATFORM=${TARGETPLATFORM:-linux/amd64} -ARG COMMIT_TAG -ENV COMMIT_TAG=${COMMIT_TAG} - -COPY . /app -WORKDIR /app - RUN \ case "${TARGETPLATFORM}" in \ 'linux/arm64') apk add --no-cache python make g++ ;; \ 'linux/arm/v7') apk add --no-cache python make g++ ;; \ esac -RUN yarn --frozen-lockfile --network-timeout 1000000 && \ - yarn build +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile --network-timeout 1000000 + +COPY . ./ + +ARG COMMIT_TAG +ENV COMMIT_TAG=${COMMIT_TAG} + +RUN yarn build # remove development dependencies RUN yarn install --production --ignore-scripts --prefer-offline -RUN rm -rf src && \ - rm -rf server +RUN rm -rf src server RUN touch config/DOCKER @@ -31,11 +33,12 @@ RUN echo "{\"commitTag\": \"${COMMIT_TAG}\"}" > committag.json FROM node:14.16-alpine +WORKDIR /app + RUN apk add --no-cache tzdata tini # copy from build image -COPY --from=BUILD_IMAGE /app /app -WORKDIR /app +COPY --from=BUILD_IMAGE /app ./ ENTRYPOINT [ "/sbin/tini", "--" ] CMD [ "yarn", "start" ] diff --git a/overseerr-api.yml b/overseerr-api.yml index 08bf1b5ca..637af162c 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -103,8 +103,10 @@ components: properties: apiKey: type: string - example: 'anapikey' readOnly: true + appLanguage: + type: string + example: en applicationTitle: type: string example: Overseerr @@ -126,6 +128,9 @@ components: localLogin: type: boolean example: true + newPlexLogin: + type: boolean + example: true defaultPermissions: type: number example: 32 @@ -1128,6 +1133,15 @@ components: properties: webhookUrl: type: string + WebPushSettings: + type: object + properties: + enabled: + type: boolean + example: false + types: + type: number + example: 2 WebhookSettings: type: object properties: @@ -1142,6 +1156,8 @@ components: properties: webhookUrl: type: string + authHeader: + type: string jsonPayload: type: string TelegramSettings: @@ -1196,6 +1212,22 @@ components: type: string priority: type: number + LunaSeaSettings: + type: object + properties: + enabled: + type: boolean + example: false + types: + type: number + example: 2 + options: + type: object + properties: + webhookUrl: + type: string + profileName: + type: string NotificationEmailSettings: type: object properties: @@ -1223,6 +1255,12 @@ components: secure: type: boolean example: false + ignoreTls: + type: boolean + example: false + requireTls: + type: boolean + example: false authUser: type: string nullable: true @@ -2397,22 +2435,22 @@ paths: responses: '204': description: Test notification attempted - /settings/notifications/telegram: + /settings/notifications/lunasea: get: - summary: Get Telegram notification settings - description: Returns current Telegram notification settings in a JSON object. + summary: Get LunaSea notification settings + description: Returns current LunaSea notification settings in a JSON object. tags: - settings responses: '200': - description: Returned Telegram settings + description: Returned LunaSea settings content: application/json: schema: - $ref: '#/components/schemas/TelegramSettings' + $ref: '#/components/schemas/LunaSeaSettings' post: - summary: Update Telegram notification settings - description: Update Telegram notification settings with the provided values. + summary: Update LunaSea notification settings + description: Updates LunaSea notification settings with the provided values. tags: - settings requestBody: @@ -2420,18 +2458,18 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/TelegramSettings' + $ref: '#/components/schemas/LunaSeaSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: - $ref: '#/components/schemas/TelegramSettings' - /settings/notifications/telegram/test: + $ref: '#/components/schemas/LunaSeaSettings' + /settings/notifications/lunasea/test: post: - summary: Test Telegram settings - description: Sends a test notification to the Telegram agent. + summary: Test LunaSea settings + description: Sends a test notification to the LunaSea agent. tags: - settings requestBody: @@ -2439,7 +2477,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/TelegramSettings' + $ref: '#/components/schemas/LunaSeaSettings' responses: '204': description: Test notification attempted @@ -2581,6 +2619,98 @@ paths: responses: '204': description: Test notification attempted + /settings/notifications/telegram: + get: + summary: Get Telegram notification settings + description: Returns current Telegram notification settings in a JSON object. + tags: + - settings + responses: + '200': + description: Returned Telegram settings + content: + application/json: + schema: + $ref: '#/components/schemas/TelegramSettings' + post: + summary: Update Telegram notification settings + description: Update Telegram notification settings with the provided values. + tags: + - settings + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TelegramSettings' + responses: + '200': + description: 'Values were sucessfully updated' + content: + application/json: + schema: + $ref: '#/components/schemas/TelegramSettings' + /settings/notifications/telegram/test: + post: + summary: Test Telegram settings + description: Sends a test notification to the Telegram agent. + tags: + - settings + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TelegramSettings' + responses: + '204': + description: Test notification attempted + /settings/notifications/webpush: + get: + summary: Get Web Push notification settings + description: Returns current Web Push notification settings in a JSON object. + tags: + - settings + responses: + '200': + description: Returned web push settings + content: + application/json: + schema: + $ref: '#/components/schemas/WebPushSettings' + post: + summary: Update Web Push notification settings + description: Updates Web Push notification settings with the provided values. + tags: + - settings + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WebPushSettings' + responses: + '200': + description: 'Values were sucessfully updated' + content: + application/json: + schema: + $ref: '#/components/schemas/WebPushSettings' + /settings/notifications/webpush/test: + post: + summary: Test Web Push settings + description: Sends a test notification to the Web Push agent. + tags: + - settings + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WebPushSettings' + responses: + '204': + description: Test notification attempted /settings/notifications/webhook: get: summary: Get webhook notification settings @@ -2903,6 +3033,32 @@ paths: type: array items: $ref: '#/components/schemas/User' + /user/registerPushSubscription: + post: + summary: Register a web push /user/registerPushSubscription + description: Registers a web push subscription for the logged-in user + tags: + - users + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + endpoint: + type: string + auth: + type: string + p256dh: + type: string + required: + - endpoint + - auth + - p256dh + responses: + '204': + description: Successfully registered push subscription /user/{userId}: get: summary: Get user by ID diff --git a/package.json b/package.json index 0c7a91b34..564a5e41c 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,11 @@ }, "license": "MIT", "dependencies": { - "@headlessui/react": "^1.0.0", + "@headlessui/react": "^1.1.1", "@heroicons/react": "^1.0.1", "@supercharge/request-ip": "^1.1.2", "@svgr/webpack": "^5.5.0", - "@tanem/react-nprogress": "^3.0.62", + "@tanem/react-nprogress": "^3.0.64", "ace-builds": "^1.4.12", "axios": "^0.21.1", "bcrypt": "^5.0.1", @@ -30,35 +30,34 @@ "connect-typeorm": "^1.1.4", "cookie-parser": "^1.4.5", "copy-to-clipboard": "^3.3.1", - "country-flag-icons": "^1.2.9", + "country-flag-icons": "^1.2.10", "csurf": "^1.11.0", "email-templates": "^8.0.4", "express": "^4.17.1", - "express-openapi-validator": "^4.12.7", + "express-openapi-validator": "^4.12.9", "express-rate-limit": "^5.2.6", "express-session": "^1.17.1", "formik": "^2.2.6", - "gravatar-url": "^3.1.0", + "gravatar-url": "3.1.0", "intl": "^1.2.5", "lodash": "^4.17.21", "next": "10.1.3", "node-cache": "^5.1.2", "node-schedule": "^2.0.0", - "nodemailer": "^6.5.0", - "nookies": "^2.5.2", - "openpgp": "^5.0.0-1", + "nodemailer": "^6.6.0", + "openpgp": "^5.0.0-2", "plex-api": "^5.3.1", "pug": "^3.0.2", "react": "17.0.2", "react-ace": "^9.3.0", "react-animate-height": "^2.0.23", "react-dom": "17.0.2", - "react-intersection-observer": "^8.31.0", - "react-intl": "5.15.8", - "react-markdown": "^6.0.0", + "react-intersection-observer": "^8.31.1", + "react-intl": "5.17.4", + "react-markdown": "^6.0.1", "react-select": "^4.3.0", "react-spring": "^8.0.27", - "react-toast-notifications": "^2.4.3", + "react-toast-notifications": "^2.4.4", "react-transition-group": "^4.4.1", "react-truncate-markup": "^5.1.0", "react-use-clipboard": "1.0.7", @@ -66,17 +65,18 @@ "secure-random-password": "^0.2.2", "sqlite3": "^5.0.2", "swagger-ui-express": "^4.1.6", - "swr": "^0.5.5", + "swr": "^0.5.6", "typeorm": "^0.2.32", "uuid": "^8.3.2", + "web-push": "^3.4.4", "winston": "^3.3.3", - "winston-daily-rotate-file": "^4.5.2", + "winston-daily-rotate-file": "^4.5.3", "xml2js": "^0.4.23", "yamljs": "^0.3.0", "yup": "^0.32.9" }, "devDependencies": { - "@babel/cli": "^7.13.14", + "@babel/cli": "^7.13.16", "@commitlint/cli": "^12.1.1", "@commitlint/config-conventional": "^12.1.1", "@semantic-release/changelog": "^5.0.1", @@ -96,10 +96,10 @@ "@types/express-rate-limit": "^5.1.1", "@types/express-session": "^1.17.3", "@types/lodash": "^4.14.168", - "@types/node": "^14.14.41", + "@types/node": "^15.0.1", "@types/node-schedule": "^1.3.1", "@types/nodemailer": "^6.4.1", - "@types/react": "^17.0.3", + "@types/react": "^17.0.4", "@types/react-dom": "^17.0.3", "@types/react-select": "^4.0.15", "@types/react-toast-notifications": "^2.4.0", @@ -107,6 +107,7 @@ "@types/secure-random-password": "^0.2.0", "@types/swagger-ui-express": "^4.1.2", "@types/uuid": "^8.3.0", + "@types/web-push": "^3.3.0", "@types/xml2js": "^0.4.8", "@types/yamljs": "^0.2.31", "@types/yup": "^0.29.11", @@ -118,9 +119,9 @@ "commitizen": "^4.2.3", "copyfiles": "^2.4.1", "cz-conventional-changelog": "^3.3.0", - "eslint": "^7.24.0", - "eslint-config-prettier": "^8.2.0", - "eslint-plugin-formatjs": "^2.14.6", + "eslint": "^7.25.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-formatjs": "^2.14.10", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-react": "^7.23.2", @@ -129,11 +130,11 @@ "husky": "4.3.8", "lint-staged": "^10.5.4", "nodemon": "^2.0.7", - "postcss": "^8.2.10", + "postcss": "^8.2.13", "prettier": "^2.2.1", "semantic-release": "^17.4.2", "semantic-release-docker-buildx": "^1.0.1", - "tailwindcss": "^2.1.1", + "tailwindcss": "^2.1.2", "ts-node": "^9.1.1", "typescript": "^4.2.4" }, diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png index 692f01a85..f246f9fa2 100644 Binary files a/public/android-chrome-192x192.png and b/public/android-chrome-192x192.png differ diff --git a/public/android-chrome-192x192_maskable.png b/public/android-chrome-192x192_maskable.png new file mode 100644 index 000000000..ecdd73670 Binary files /dev/null and b/public/android-chrome-192x192_maskable.png differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png index 34d1f9e1e..4910ced2d 100644 Binary files a/public/android-chrome-512x512.png and b/public/android-chrome-512x512.png differ diff --git a/public/android-chrome-512x512_maskable.png b/public/android-chrome-512x512_maskable.png new file mode 100644 index 000000000..475cf85e9 Binary files /dev/null and b/public/android-chrome-512x512_maskable.png differ diff --git a/public/clock-icon-192x192.png b/public/clock-icon-192x192.png new file mode 100644 index 000000000..d7e57dd0a Binary files /dev/null and b/public/clock-icon-192x192.png differ diff --git a/public/cog-icon-192x192.png b/public/cog-icon-192x192.png new file mode 100644 index 000000000..99d114059 Binary files /dev/null and b/public/cog-icon-192x192.png differ diff --git a/public/images/radarr_logo.svg b/public/images/radarr_logo.svg deleted file mode 100644 index 231b9f936..000000000 --- a/public/images/radarr_logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/images/sonarr_logo.svg b/public/images/sonarr_logo.svg deleted file mode 100644 index 2175728dd..000000000 --- a/public/images/sonarr_logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/offline.html b/public/offline.html new file mode 100644 index 000000000..01658360f --- /dev/null +++ b/public/offline.html @@ -0,0 +1,69 @@ + + +
+ + + + +
{intl.formatMessage(
@@ -325,55 +330,42 @@ const CollectionDetails: React.FC (
switch (buttonSize) {
case 'sm':
- buttonStyle.push('px-2.5 py-1.5 text-xs');
- break;
- case 'md':
- buttonStyle.push('px-4 py-2 text-sm');
+ buttonStyle.push('px-2.5 py-1.5 text-xs button-sm');
break;
case 'lg':
- buttonStyle.push('px-6 py-3 text-base');
+ buttonStyle.push('px-6 py-3 text-base button-lg');
break;
+ case 'md':
default:
- buttonStyle.push('px-4 py-2 text-sm');
+ buttonStyle.push('px-4 py-2 text-sm button-md');
}
buttonStyle.push(className ?? '');
diff --git a/src/components/Common/ButtonWithDropdown/index.tsx b/src/components/Common/ButtonWithDropdown/index.tsx
index 65a8c7417..944c9d8bb 100644
--- a/src/components/Common/ButtonWithDropdown/index.tsx
+++ b/src/components/Common/ButtonWithDropdown/index.tsx
@@ -19,16 +19,16 @@ const DropdownItem: React.FC