Compare commits

..

5 Commits

Author SHA1 Message Date
semantic-release-bot
cc526ff26d chore(release): 1.0.0-arm-test.1 2021-03-12 09:47:58 +00:00
sct
bffb84d08b fix: try custom buildx semantic-release package 2021-03-12 09:45:25 +00:00
sct
a66872588e ci: load resulting build image into docker 2021-03-12 09:34:42 +00:00
sct
a10921e411 ci: temporarily remove test/snap build for testing 2021-03-12 09:34:42 +00:00
sct
7ca08057a7 ci: add arm-test for release 2021-03-12 09:34:42 +00:00
56 changed files with 1406 additions and 2744 deletions

View File

@@ -12,7 +12,7 @@ jobs:
test:
name: Lint & Test Build
runs-on: ubuntu-20.04
container: node:14.16-alpine
container: node:12.18-alpine
steps:
- name: checkout
uses: actions/checkout@v2

View File

@@ -4,26 +4,27 @@ on:
push:
branches:
- master
- arm-test
jobs:
test:
name: Lint & Test Build
runs-on: ubuntu-20.04
container: node:14.16-alpine
steps:
- name: checkout
uses: actions/checkout@v2
- name: install dependencies
env:
HUSKY_SKIP_INSTALL: 1
run: yarn
- name: lint
run: yarn lint
- name: build
run: yarn build
# test:
# name: Lint & Test Build
# runs-on: ubuntu-20.04
# container: node:12.18-alpine
# steps:
# - name: checkout
# uses: actions/checkout@v2
# - name: install dependencies
# env:
# HUSKY_SKIP_INSTALL: 1
# run: yarn
# - name: lint
# run: yarn lint
# - name: build
# run: yarn build
semantic-release:
name: Tag and release latest version
needs: test
# needs: test
runs-on: ubuntu-20.04
steps:
- name: Checkout
@@ -33,7 +34,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 14
node-version: 12
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
@@ -57,65 +58,65 @@ 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
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
architecture:
- amd64
- arm64
- armhf
steps:
- name: Checkout Code
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Switch to master branch
run: git checkout master
- name: Pull latest changes
run: git pull
# build-snap:
# name: Build Snap Package (${{ matrix.architecture }})
# needs: semantic-release
# runs-on: ubuntu-20.04
# strategy:
# fail-fast: false
# matrix:
# architecture:
# - amd64
# - arm64
# - armhf
# steps:
# - name: Checkout Code
# uses: actions/checkout@v2
# with:
# fetch-depth: 0
# - name: Switch to master branch
# run: git checkout master
# - name: Pull latest changes
# run: git pull
- name: Prepare
id: prepare
run: |
git fetch --prune --tags
if [[ $GITHUB_REF == refs/tags/* || $GITHUB_REF == refs/heads/master ]]; then
echo ::set-output name=RELEASE::stable
else
echo ::set-output name=RELEASE::edge
fi
# - name: Prepare
# id: prepare
# run: |
# git fetch --prune --tags
# if [[ $GITHUB_REF == refs/tags/* || $GITHUB_REF == refs/heads/master ]]; then
# echo ::set-output name=RELEASE::stable
# 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: 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: 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: 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: 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 }}
# - 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

File diff suppressed because it is too large Load Diff

View File

@@ -904,8 +904,6 @@ components:
$ref: '#/components/schemas/Season'
status:
type: string
tagline:
type: string
type:
type: string
voteAverage:
@@ -4739,12 +4737,6 @@ paths:
description: Returns a list of genres in a JSON array.
tags:
- tmdb
parameters:
- in: query
name: language
schema:
type: string
example: en
responses:
'200':
description: Results
@@ -4767,12 +4759,6 @@ paths:
description: Returns a list of genres in a JSON array.
tags:
- tmdb
parameters:
- in: query
name: language
schema:
type: string
example: en
responses:
'200':
description: Results

View File

@@ -1,6 +1,6 @@
{
"name": "overseerr",
"version": "1.21.1",
"version": "1.0.0-arm-test.1",
"private": true,
"scripts": {
"dev": "nodemon -e ts --watch server --watch overseerr-api.yml -e .json,.ts,.yml -x ts-node --files --project server/tsconfig.json server/index.ts",
@@ -20,7 +20,6 @@
"@headlessui/react": "^0.3.1",
"@supercharge/request-ip": "^1.1.2",
"@svgr/webpack": "^5.5.0",
"@tanem/react-nprogress": "^3.0.57",
"ace-builds": "^1.4.12",
"axios": "^0.21.1",
"bcrypt": "^5.0.1",
@@ -43,7 +42,6 @@
"node-schedule": "^2.0.0",
"nodemailer": "^6.5.0",
"nookies": "^2.5.2",
"openpgp": "^5.0.0-1",
"plex-api": "^5.3.1",
"pug": "^3.0.2",
"react": "17.0.1",
@@ -91,9 +89,9 @@
"@types/express": "^4.17.11",
"@types/express-session": "^1.17.3",
"@types/lodash": "^4.14.168",
"@types/node": "^14.14.34",
"@types/node": "^14.14.33",
"@types/node-schedule": "^1.3.1",
"@types/nodemailer": "^6.4.1",
"@types/nodemailer": "^6.4.0",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"@types/react-toast-notifications": "^2.4.0",
@@ -126,8 +124,9 @@
"postcss": "^8.2.8",
"postcss-preset-env": "^6.7.0",
"prettier": "^2.2.1",
"semantic-release": "^17.4.2",
"semantic-release-docker-buildx": "^1.0.1",
"semantic-release": "^17.4.1",
"semantic-release-docker": "^2.2.0",
"semantic-release-docker-buildx": "^0.0.0-development",
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
"ts-node": "^9.1.1",
"typescript": "^4.2.3"
@@ -197,7 +196,11 @@
]
],
"branches": [
"master"
"master",
{
"name": "arm-test",
"prerelease": true
}
],
"npmPublish": false,
"publish": [

View File

@@ -254,7 +254,6 @@ export interface TmdbTvDetails {
}[];
seasons: TmdbTvSeasonResult[];
status: string;
tagline?: string;
type: string;
vote_average: number;
vote_count: number;

View File

@@ -37,7 +37,4 @@ export class UserSettings {
@Column({ nullable: true })
public originalLanguage?: string;
@Column({ nullable: true })
public pgpKey?: string;
}

View File

@@ -10,5 +10,4 @@ export interface UserSettingsNotificationsResponse {
discordId?: string;
telegramChatId?: string;
telegramSendSilently?: boolean;
pgpKey?: string;
}

View File

@@ -1,9 +1,8 @@
import nodemailer from 'nodemailer';
import Email from 'email-templates';
import { getSettings } from '../settings';
import { openpgpEncrypt } from './openpgpEncrypt';
class PreparedEmail extends Email {
public constructor(pgpKey?: string) {
public constructor() {
const settings = getSettings().notifications.agents.email;
const transport = nodemailer.createTransport({
@@ -23,16 +22,6 @@ class PreparedEmail extends Email {
}
: undefined,
});
if (pgpKey) {
transport.use(
'stream',
openpgpEncrypt({
signingKey: settings.options.pgpPrivateKey,
password: settings.options.pgpPassword,
encryptionKeys: [pgpKey],
})
);
}
super({
message: {
from: {

View File

@@ -1,181 +0,0 @@
import * as openpgp from 'openpgp';
import { Transform, TransformCallback } from 'stream';
import crypto from 'crypto';
interface EncryptorOptions {
signingKey?: string;
password?: string;
encryptionKeys: string[];
}
class PGPEncryptor extends Transform {
private _messageChunks: Uint8Array[] = [];
private _messageLength = 0;
private _signingKey?: string;
private _password?: string;
private _encryptionKeys: string[];
constructor(options: EncryptorOptions) {
super();
this._signingKey = options.signingKey;
this._password = options.password;
this._encryptionKeys = options.encryptionKeys;
}
// just save the whole message
_transform = (
chunk: any,
_encoding: BufferEncoding,
callback: TransformCallback
): void => {
this._messageChunks.push(chunk);
this._messageLength += chunk.length;
callback();
};
// Actually do stuff
_flush = async (callback: TransformCallback): Promise<void> => {
// Reconstruct message as buffer
const message = Buffer.concat(this._messageChunks, this._messageLength);
const validPublicKeys = await Promise.all(
this._encryptionKeys.map((armoredKey) => openpgp.readKey({ armoredKey }))
);
let privateKey: openpgp.Key | undefined;
// Just return the message if there is no one to encrypt for
if (!validPublicKeys.length) {
this.push(message);
return callback();
}
// Only sign the message if private key and password exist
if (this._signingKey && this._password) {
privateKey = await openpgp.readKey({
armoredKey: this._signingKey,
});
await privateKey.decrypt(this._password);
}
const emailPartDelimiter = '\r\n\r\n';
const messageParts = message.toString().split(emailPartDelimiter);
/**
* In this loop original headers are split up into two parts,
* one for the email that is sent
* and one for the encrypted content
*/
const header = messageParts.shift() as string;
const emailHeaders: string[][] = [];
const contentHeaders: string[][] = [];
const linesInHeader = header.split('\r\n');
let previousHeader: string[] = [];
for (let i = 0; i < linesInHeader.length; i++) {
const line = linesInHeader[i];
/**
* If it is a multi-line header (current line starts with whitespace)
* or it's the first line in the iteration
* add the current line with previous header and move on
*/
if (/^\s/.test(line) || i === 0) {
previousHeader.push(line);
continue;
}
/**
* This is done to prevent the last header
* from being missed
*/
if (i === linesInHeader.length - 1) {
previousHeader.push(line);
}
/**
* We need to seperate the actual content headers
* so that we can add it as a header for the encrypted content
* So that the content will be displayed properly after decryption
*/
if (
/^(content-type|content-transfer-encoding):/i.test(previousHeader[0])
) {
contentHeaders.push(previousHeader);
} else {
emailHeaders.push(previousHeader);
}
previousHeader = [line];
}
// Generate a new boundary for the email content
const boundary = 'nm_' + crypto.randomBytes(14).toString('hex');
/**
* Concatenate everything into single strings
* and add pgp headers to the email headers
*/
const emailHeadersRaw =
emailHeaders.map((line) => line.join('\r\n')).join('\r\n') +
'\r\n' +
'Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";' +
'\r\n' +
' boundary="' +
boundary +
'"' +
'\r\n' +
'Content-Description: OpenPGP encrypted message' +
'\r\n' +
'Content-Transfer-Encoding: 7bit';
const contentHeadersRaw = contentHeaders
.map((line) => line.join('\r\n'))
.join('\r\n');
const encryptedMessage = await openpgp.encrypt({
message: openpgp.Message.fromText(
contentHeadersRaw +
emailPartDelimiter +
messageParts.join(emailPartDelimiter)
),
publicKeys: validPublicKeys,
privateKeys: privateKey,
});
const body =
'--' +
boundary +
'\r\n' +
'Content-Type: application/pgp-encrypted\r\n' +
'Content-Transfer-Encoding: 7bit\r\n' +
'\r\n' +
'Version: 1\r\n' +
'\r\n' +
'--' +
boundary +
'\r\n' +
'Content-Type: application/octet-stream; name=encrypted.asc\r\n' +
'Content-Disposition: inline; filename=encrypted.asc\r\n' +
'Content-Transfer-Encoding: 7bit\r\n' +
'\r\n' +
encryptedMessage +
'\r\n--' +
boundary +
'--\r\n';
this.push(Buffer.from(emailHeadersRaw + emailPartDelimiter + body));
callback();
};
}
export const openpgpEncrypt = (options: EncryptorOptions) => {
return function (mail: any, callback: () => unknown): void {
if (!options.encryptionKeys.length) {
setImmediate(callback);
}
mail.message.transform(
() =>
new PGPEncryptor({
signingKey: options.signingKey,
password: options.password,
encryptionKeys: options.encryptionKeys,
})
);
setImmediate(callback);
};
};

View File

@@ -156,14 +156,15 @@ class DiscordAgent
break;
}
const url =
settings.main.applicationUrl && payload.media
? `${settings.main.applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}`
: undefined;
if (settings.main.applicationUrl && payload.media) {
fields.push({
name: `Open in ${settings.main.applicationTitle}`,
value: `${settings.main.applicationUrl}/${payload.media?.mediaType}/${payload.media?.tmdbId}`,
});
}
return {
title: payload.subject,
url,
description: payload.message,
color,
timestamp: new Date().toISOString(),

View File

@@ -47,7 +47,7 @@ class EmailAgent
users
.filter((user) => user.hasPermission(Permission.MANAGE_REQUESTS))
.forEach((user) => {
const email = new PreparedEmail(payload.notifyUser.settings?.pgpKey);
const email = new PreparedEmail();
email.send({
template: path.join(
@@ -97,7 +97,7 @@ class EmailAgent
users
.filter((user) => user.hasPermission(Permission.MANAGE_REQUESTS))
.forEach((user) => {
const email = new PreparedEmail(payload.notifyUser.settings?.pgpKey);
const email = new PreparedEmail();
email.send({
template: path.join(
@@ -142,7 +142,7 @@ class EmailAgent
// This is getting main settings for the whole app
const { applicationUrl, applicationTitle } = getSettings().main;
try {
const email = new PreparedEmail(payload.notifyUser.settings?.pgpKey);
const email = new PreparedEmail();
await email.send({
template: path.join(
@@ -234,7 +234,7 @@ class EmailAgent
// This is getting main settings for the whole app
const { applicationUrl, applicationTitle } = getSettings().main;
try {
const email = new PreparedEmail(payload.notifyUser.settings?.pgpKey);
const email = new PreparedEmail();
await email.send({
template: path.join(
@@ -276,7 +276,7 @@ class EmailAgent
// This is getting main settings for the whole app
const { applicationUrl, applicationTitle } = getSettings().main;
try {
const email = new PreparedEmail(payload.notifyUser.settings?.pgpKey);
const email = new PreparedEmail();
await email.send({
template: path.join(
@@ -318,7 +318,7 @@ class EmailAgent
// This is getting main settings for the whole app
const { applicationUrl, applicationTitle } = getSettings().main;
try {
const email = new PreparedEmail(payload.notifyUser.settings?.pgpKey);
const email = new PreparedEmail();
await email.send({
template: path.join(__dirname, '../../../templates/email/test-email'),

View File

@@ -117,8 +117,6 @@ export interface NotificationAgentEmail extends NotificationAgentConfig {
authPass?: string;
allowSelfSigned: boolean;
senderName: string;
pgpPrivateKey?: string;
pgpPassword?: string;
};
}

View File

@@ -1,31 +0,0 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class AddPGPToUserSettings1615333940450 implements MigrationInterface {
name = 'AddPGPToUserSettings1615333940450';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TABLE "temporary_user_settings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "enableNotifications" boolean NOT NULL DEFAULT (1), "discordId" varchar, "userId" integer, "region" varchar, "originalLanguage" varchar, "telegramChatId" varchar, "telegramSendSilently" boolean, "pgpKey" varchar, CONSTRAINT "UQ_986a2b6d3c05eb4091bb8066f78" UNIQUE ("userId"), CONSTRAINT "FK_986a2b6d3c05eb4091bb8066f78" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`
);
await queryRunner.query(
`INSERT INTO "temporary_user_settings"("id", "enableNotifications", "discordId", "userId", "region", "originalLanguage", "telegramChatId", "telegramSendSilently") SELECT "id", "enableNotifications", "discordId", "userId", "region", "originalLanguage", "telegramChatId", "telegramSendSilently" FROM "user_settings"`
);
await queryRunner.query(`DROP TABLE "user_settings"`);
await queryRunner.query(
`ALTER TABLE "temporary_user_settings" RENAME TO "user_settings"`
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "user_settings" RENAME TO "temporary_user_settings"`
);
await queryRunner.query(
`CREATE TABLE "user_settings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "enableNotifications" boolean NOT NULL DEFAULT (1), "discordId" varchar, "userId" integer, "region" varchar, "originalLanguage" varchar, "telegramChatId" varchar, "telegramSendSilently" boolean, CONSTRAINT "UQ_986a2b6d3c05eb4091bb8066f78" UNIQUE ("userId"), CONSTRAINT "FK_986a2b6d3c05eb4091bb8066f78" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`
);
await queryRunner.query(
`INSERT INTO "user_settings"("id", "enableNotifications", "discordId", "userId", "region", "originalLanguage", "telegramChatId", "telegramSendSilently") SELECT "id", "enableNotifications", "discordId", "userId", "region", "originalLanguage", "telegramChatId", "telegramSendSilently" FROM "temporary_user_settings"`
);
await queryRunner.query(`DROP TABLE "temporary_user_settings"`);
}
}

View File

@@ -91,7 +91,6 @@ export interface TvDetails {
spokenLanguages: SpokenLanguage[];
seasons: Season[];
status: string;
tagline?: string;
type: string;
voteAverage: number;
voteCount: number;
@@ -175,7 +174,6 @@ export const mapTvDetails = (
originCountry: show.origin_country,
originalLanguage: show.original_language,
originalName: show.original_name,
tagline: show.tagline,
overview: show.overview,
popularity: show.popularity,
productionCompanies: show.production_companies.map((company) => ({

View File

@@ -95,9 +95,7 @@ router.get<{ id: string }>('/network/:id', async (req, res) => {
router.get('/genres/movie', isAuthenticated(), async (req, res) => {
const tmdb = new TheMovieDb();
const genres = await tmdb.getMovieGenres({
language: req.query.language as string,
});
const genres = await tmdb.getMovieGenres();
return res.status(200).json(genres);
});
@@ -105,9 +103,7 @@ router.get('/genres/movie', isAuthenticated(), async (req, res) => {
router.get('/genres/tv', isAuthenticated(), async (req, res) => {
const tmdb = new TheMovieDb();
const genres = await tmdb.getTvGenres({
language: req.query.language as string,
});
const genres = await tmdb.getTvGenres();
return res.status(200).json(genres);
});

View File

@@ -73,14 +73,6 @@ userSettingsRoutes.post<
return next({ status: 404, message: 'User not found.' });
}
// "Owner" user settings cannot be modified by other users
if (user.id === 1 && req.user?.id !== 1) {
return next({
status: 403,
message: "You do not have permission to modify this user's settings.",
});
}
user.username = req.body.username;
if (!user.settings) {
user.settings = new UserSettings({
@@ -225,7 +217,6 @@ userSettingsRoutes.get<{ id: string }, UserSettingsNotificationsResponse>(
discordId: user.settings?.discordId,
telegramChatId: user.settings?.telegramChatId,
telegramSendSilently: user?.settings?.telegramSendSilently,
pgpKey: user?.settings?.pgpKey,
});
} catch (e) {
next({ status: 500, message: e.message });
@@ -249,14 +240,6 @@ userSettingsRoutes.post<
return next({ status: 404, message: 'User not found.' });
}
// "Owner" user settings cannot be modified by other users
if (user.id === 1 && req.user?.id !== 1) {
return next({
status: 403,
message: "You do not have permission to modify this user's settings.",
});
}
if (!user.settings) {
user.settings = new UserSettings({
user: req.user,
@@ -264,14 +247,12 @@ userSettingsRoutes.post<
discordId: req.body.discordId,
telegramChatId: req.body.telegramChatId,
telegramSendSilently: req.body.telegramSendSilently,
pgpKey: req.body.pgpKey,
});
} else {
user.settings.enableNotifications = req.body.enableNotifications;
user.settings.discordId = req.body.discordId;
user.settings.telegramChatId = req.body.telegramChatId;
user.settings.telegramSendSilently = req.body.telegramSendSilently;
user.settings.pgpKey = req.body.pgpKey;
}
userRepository.save(user);
@@ -281,7 +262,6 @@ userSettingsRoutes.post<
discordId: user.settings.discordId,
telegramChatId: user.settings.telegramChatId,
telegramSendSilently: user.settings.telegramSendSilently,
pgpKey: user.settings.pgpKey,
});
} catch (e) {
next({ status: 500, message: e.message });
@@ -329,8 +309,8 @@ userSettingsRoutes.post<
return next({ status: 404, message: 'User not found.' });
}
// "Owner" user permissions cannot be modified, and users cannot set their own permissions
if (user.id === 1 || req.user?.id === user.id) {
// Only let the owner user modify themselves
if (user.id === 1 && req.user?.id !== 1) {
return next({
status: 403,
message: 'You do not have permission to modify this user',

View File

@@ -19,14 +19,12 @@ import Transition from '../Transition';
import PageTitle from '../Common/PageTitle';
import { useUser, Permission } from '../../hooks/useUser';
import useSettings from '../../hooks/useSettings';
import Link from 'next/link';
import { uniq } from 'lodash';
const messages = defineMessages({
overviewunavailable: 'Overview unavailable.',
overview: 'Overview',
movies: 'Movies',
numberofmovies: '{count} Movies',
numberofmovies: 'Number of Movies: {count}',
requesting: 'Requesting…',
request: 'Request',
requestcollection: 'Request Collection',
@@ -64,10 +62,6 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
}
);
const { data: genres } = useSWR<{ id: number; name: string }[]>(
`/api/v1/genres/movie?language=${locale}`
);
if (!data && !error) {
return <LoadingSpinner />;
}
@@ -111,17 +105,6 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
collectionStatus4k = MediaStatus.PARTIALLY_AVAILABLE;
}
const hasRequestable =
data.parts.filter(
(part) => !part.mediaInfo || part.mediaInfo.status === MediaStatus.UNKNOWN
).length > 0;
const hasRequestable4k =
data.parts.filter(
(part) =>
!part.mediaInfo || part.mediaInfo.status4k === MediaStatus.UNKNOWN
).length > 0;
const requestableParts = data.parts.filter(
(part) =>
!part.mediaInfo ||
@@ -164,43 +147,9 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
}
};
const collectionAttributes: React.ReactNode[] = [];
collectionAttributes.push(
intl.formatMessage(messages.numberofmovies, {
count: data.parts.length,
})
);
if (genres && data.parts.some((part) => part.genreIds.length)) {
collectionAttributes.push(
uniq(
data.parts.reduce(
(genresList: number[], curr) => genresList.concat(curr.genreIds),
[]
)
)
.map((genreId) => (
<Link
href={`/discover/movies/genre/${genreId}`}
key={`genre-${genreId}`}
>
<a className="hover:underline">
{genres.find((g) => g.id === genreId)?.name}
</a>
</Link>
))
.reduce((prev, curr) => (
<>
{prev}, {curr}
</>
))
);
}
return (
<div
className="media-page"
className="px-4 pt-16 -mx-4 -mt-16 bg-center bg-cover"
style={{
height: 493,
backgroundImage: `linear-gradient(180deg, rgba(17, 24, 39, 0.47) 0%, rgba(17, 24, 39, 1) 100%), url(//image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data.backdropPath})`,
@@ -267,20 +216,24 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
</ul>
</Modal>
</Transition>
<div className="media-header">
<img
src={`//image.tmdb.org/t/p/w600_and_h900_bestv2${data.posterPath}`}
alt=""
className="media-poster"
/>
<div className="media-title">
<div className="media-status">
<StatusBadge
status={collectionStatus}
inProgress={data.parts.some(
(part) => (part.mediaInfo?.downloadStatus ?? []).length > 0
)}
/>
<div className="flex flex-col items-center pt-4 lg:flex-row lg:items-end">
<div className="lg:mr-4">
<img
src={`//image.tmdb.org/t/p/w600_and_h900_bestv2${data.posterPath}`}
alt=""
className="w-32 rounded shadow md:rounded-lg md:shadow-2xl md:w-44 lg:w-52"
/>
</div>
<div className="flex flex-col flex-1 mt-4 text-center text-white lg:mr-4 lg:mt-0 lg:text-left">
<div className="mb-2 space-x-2">
<span className="ml-2 lg:ml-0">
<StatusBadge
status={collectionStatus}
inProgress={data.parts.some(
(part) => (part.mediaInfo?.downloadStatus ?? []).length > 0
)}
/>
</span>
{settings.currentSettings.movie4kEnabled &&
hasPermission(
[Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE],
@@ -288,83 +241,43 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
type: 'or',
}
) && (
<StatusBadge
status={collectionStatus4k}
is4k
inProgress={data.parts.some(
(part) =>
(part.mediaInfo?.downloadStatus4k ?? []).length > 0
)}
/>
<span>
<StatusBadge
status={collectionStatus4k}
is4k
inProgress={data.parts.some(
(part) =>
(part.mediaInfo?.downloadStatus4k ?? []).length > 0
)}
/>
</span>
)}
</div>
<h1>{data.name}</h1>
<span className="media-attributes">
{collectionAttributes.length > 0 &&
collectionAttributes
.map((t, k) => <span key={k}>{t}</span>)
.reduce((prev, curr) => (
<>
{prev} | {curr}
</>
))}
<h1 className="text-2xl md:text-4xl">{data.name}</h1>
<span className="mt-1 text-xs lg:text-base lg:mt-0">
{intl.formatMessage(messages.numberofmovies, {
count: data.parts.length,
})}
</span>
</div>
<div className="media-actions">
<div className="relative z-10 flex flex-wrap justify-center flex-shrink-0 mt-4 sm:justify-end sm:flex-nowrap lg:mt-0">
{hasPermission(Permission.REQUEST) &&
(hasRequestable ||
(collectionStatus !== MediaStatus.AVAILABLE ||
(settings.currentSettings.movie4kEnabled &&
hasPermission(
[Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE],
{ type: 'or' }
) &&
hasRequestable4k)) && (
<ButtonWithDropdown
buttonType="primary"
onClick={() => {
setRequestModal(true);
setIs4k(!hasRequestable);
}}
text={
<>
<svg
className="w-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
/>
</svg>
<span>
{intl.formatMessage(
hasRequestable
? messages.requestcollection
: messages.requestcollection4k
)}
</span>
</>
}
>
{settings.currentSettings.movie4kEnabled &&
hasPermission(
[Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE],
{ type: 'or' }
) &&
hasRequestable &&
hasRequestable4k && (
<ButtonWithDropdown.Item
buttonType="primary"
onClick={() => {
setRequestModal(true);
setIs4k(true);
}}
>
collectionStatus4k !== MediaStatus.AVAILABLE)) && (
<div className="mb-3 sm:mb-0">
<ButtonWithDropdown
buttonType="primary"
onClick={() => {
setRequestModal(true);
setIs4k(collectionStatus === MediaStatus.AVAILABLE);
}}
text={
<>
<svg
className="w-4 mr-1"
fill="none"
@@ -380,27 +293,70 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
/>
</svg>
<span>
{intl.formatMessage(messages.requestcollection4k)}
{intl.formatMessage(
collectionStatus === MediaStatus.AVAILABLE
? messages.requestcollection4k
: messages.requestcollection
)}
</span>
</ButtonWithDropdown.Item>
)}
</ButtonWithDropdown>
</>
}
>
{settings.currentSettings.movie4kEnabled &&
hasPermission(
[Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE],
{ type: 'or' }
) &&
collectionStatus !== MediaStatus.AVAILABLE &&
collectionStatus4k !== MediaStatus.AVAILABLE && (
<ButtonWithDropdown.Item
buttonType="primary"
onClick={() => {
setRequestModal(true);
setIs4k(true);
}}
>
<svg
className="w-4 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
/>
</svg>
<span>
{intl.formatMessage(messages.requestcollection4k)}
</span>
</ButtonWithDropdown.Item>
)}
</ButtonWithDropdown>
</div>
)}
</div>
</div>
<div className="media-overview">
<div className="flex-1">
<h2>{intl.formatMessage(messages.overview)}</h2>
<p>
<div className="flex flex-col pt-8 pb-4 text-white md:flex-row">
<div className="flex-1 md:mr-8">
<h2 className="text-xl md:text-2xl">
{intl.formatMessage(messages.overview)}
</h2>
<p className="pt-2 text-sm md:text-base">
{data.overview
? data.overview
: intl.formatMessage(messages.overviewunavailable)}
</p>
</div>
</div>
<div className="slider-header">
<div className="slider-title">
<span>{intl.formatMessage(messages.movies)}</span>
<div className="mt-6 mb-4 md:flex md:items-center md:justify-between">
<div className="flex-1 min-w-0">
<div className="inline-flex items-center text-xl leading-7 text-white sm:text-2xl sm:leading-9 sm:truncate">
<span>{intl.formatMessage(messages.movies)}</span>
</div>
</div>
</div>
<Slider

View File

@@ -45,37 +45,37 @@ function Button<P extends ElementTypes = 'button'>(
ref?: React.Ref<Element<P>>
): JSX.Element {
const buttonStyle = [
'inline-flex items-center justify-center border border-transparent leading-5 font-medium rounded-md focus:outline-none transition ease-in-out duration-150 cursor-pointer disabled:opacity-50',
'inline-flex items-center justify-center border border-transparent leading-5 font-medium rounded-md focus:outline-none transition ease-in-out duration-150 cursor-pointer',
];
switch (buttonType) {
case 'primary':
buttonStyle.push(
'text-white bg-indigo-600 border-indigo-600 hover:bg-indigo-500 hover:border-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-indigo-700 active:border-indigo-700'
'text-white bg-indigo-600 hover:bg-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-indigo-700 disabled:opacity-50'
);
break;
case 'danger':
buttonStyle.push(
'text-white bg-red-600 border-red-600 hover:bg-red-500 hover:border-red-500 focus:border-red-700 focus:ring-red active:bg-red-700 active:border-red-700'
'text-white bg-red-600 hover:bg-red-500 focus:border-red-700 focus:ring-red active:bg-red-700 disabled:opacity-50'
);
break;
case 'warning':
buttonStyle.push(
'text-white bg-yellow-500 border-yellow-500 hover:bg-yellow-400 hover:border-yellow-400 focus:border-yellow-700 focus:ring-yellow active:bg-yellow-700 active:border-yellow-700'
'text-white bg-yellow-500 hover:bg-yellow-400 focus:border-yellow-700 focus:ring-yellow active:bg-yellow-700 disabled:opacity-50'
);
break;
case 'success':
buttonStyle.push(
'text-white bg-green-400 border-green-400 hover:bg-green-300 hover:border-green-300 focus:border-green-700 focus:ring-green active:bg-green-700 active:border-green-700'
'text-white bg-green-400 hover:bg-green-300 focus:border-green-700 focus:ring-green active:bg-green-700 disabled:opacity-50'
);
break;
case 'ghost':
buttonStyle.push(
'text-white bg-transaprent border-gray-600 hover:border-gray-200 focus:border-gray-100 active:border-gray-100'
'text-white bg-transaprent border border-gray-600 hover:border-gray-200 focus:border-gray-100 active:border-gray-100 disabled:opacity-50'
);
break;
default:
buttonStyle.push(
'text-gray-200 bg-gray-500 border-gray-500 hover:text-white hover:bg-gray-400 hover:border-gray-400 group-hover:text-white group-hover:bg-gray-400 group-hover:border-gray-400 focus:border-blue-300 focus:ring-blue active:text-gray-200 active:bg-gray-400 active:border-gray-400'
'leading-5 font-medium rounded-md text-gray-200 bg-gray-500 hover:bg-gray-400 group-hover:bg-gray-400 hover:text-white group-hover:text-white focus:border-blue-300 focus:ring-blue active:text-gray-200 active:bg-gray-400 disabled:opacity-50'
);
}

View File

@@ -59,23 +59,24 @@ const ButtonWithDropdown: React.FC<ButtonWithDropdownProps> = ({
useClickOutside(buttonRef, () => setIsOpen(false));
const styleClasses = {
mainButtonClasses: 'text-white border',
dropdownSideButtonClasses: 'border',
mainButtonClasses: '',
dropdownSideButtonClasses: '',
dropdownClasses: '',
};
switch (buttonType) {
case 'ghost':
styleClasses.mainButtonClasses +=
' bg-transparent border-gray-600 hover:border-gray-200 focus:border-gray-100 active:border-gray-100';
styleClasses.dropdownSideButtonClasses = styleClasses.mainButtonClasses;
styleClasses.mainButtonClasses =
'text-white bg-transparent border border-gray-600 hover:border-gray-200 focus:border-gray-100 active:border-gray-100';
styleClasses.dropdownSideButtonClasses =
'bg-transparent border border-gray-600 hover:border-gray-200 focus:border-gray-100 active:border-gray-100';
styleClasses.dropdownClasses = 'bg-gray-700';
break;
default:
styleClasses.mainButtonClasses +=
' bg-indigo-600 border-indigo-600 hover:bg-indigo-500 hover:border-indigo-500 active:bg-indigo-700 active:border-indigo-700 focus:ring-blue';
styleClasses.dropdownSideButtonClasses +=
' bg-indigo-700 border-indigo-600 hover:bg-indigo-500 active:bg-indigo-700 focus:ring-blue';
styleClasses.mainButtonClasses =
'text-white bg-indigo-600 hover:text-white hover:bg-indigo-500 active:bg-indigo-700 focus:ring-blue';
styleClasses.dropdownSideButtonClasses =
'bg-indigo-700 border border-indigo-600 hover:bg-indigo-500 active:bg-indigo-700 focus:ring-blue';
styleClasses.dropdownClasses = 'bg-indigo-600';
}

View File

@@ -24,11 +24,11 @@ const ExternalLinkBlock: React.FC<ExternalLinkBlockProps> = ({
plexUrl,
}) => {
return (
<div className="flex items-center justify-center w-full space-x-5">
<div className="flex items-center justify-end">
{plexUrl && (
<a
href={plexUrl}
className="w-12 transition duration-300 opacity-50 hover:opacity-100"
className="w-8 mx-2 transition duration-300 opacity-50 hover:opacity-100"
target="_blank"
rel="noreferrer"
>
@@ -38,7 +38,7 @@ const ExternalLinkBlock: React.FC<ExternalLinkBlockProps> = ({
{tmdbId && (
<a
href={`https://www.themoviedb.org/${mediaType}/${tmdbId}`}
className="w-8 transition duration-300 opacity-50 hover:opacity-100"
className="w-8 mx-2 transition duration-300 opacity-50 hover:opacity-100"
target="_blank"
rel="noreferrer"
>
@@ -48,7 +48,7 @@ const ExternalLinkBlock: React.FC<ExternalLinkBlockProps> = ({
{tvdbId && mediaType === MediaType.TV && (
<a
href={`http://www.thetvdb.com/?tab=series&id=${tvdbId}`}
className="transition duration-300 opacity-50 w-9 hover:opacity-100"
className="w-8 mx-2 transition duration-300 opacity-50 hover:opacity-100"
target="_blank"
rel="noreferrer"
>
@@ -58,7 +58,7 @@ const ExternalLinkBlock: React.FC<ExternalLinkBlockProps> = ({
{imdbId && (
<a
href={`https://www.imdb.com/title/${imdbId}`}
className="w-8 transition duration-300 opacity-50 hover:opacity-100"
className="w-8 mx-2 transition duration-300 opacity-50 hover:opacity-100"
target="_blank"
rel="noreferrer"
>
@@ -68,7 +68,7 @@ const ExternalLinkBlock: React.FC<ExternalLinkBlockProps> = ({
{rtUrl && (
<a
href={`${rtUrl}`}
className="transition duration-300 opacity-50 w-14 hover:opacity-100"
className="mx-2 transition duration-300 opacity-50 w-14 hover:opacity-100"
target="_blank"
rel="noreferrer"
>

View File

@@ -1,73 +0,0 @@
import { NProgress } from '@tanem/react-nprogress';
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import { useRouter } from 'next/router';
interface BarProps {
progress: number;
isFinished: boolean;
}
const Bar = ({ progress, isFinished }: BarProps) => {
return (
<div
className={`fixed top-0 left-0 z-50 w-full transition-opacity ease-out duration-400 ${
isFinished ? 'opacity-0' : 'opacity-100'
}`}
>
<div
className="duration-300 bg-indigo-400 transition-width"
style={{
height: '3px',
width: `${progress * 100}%`,
}}
/>
</div>
);
};
const NProgressBar = ({ loading }: { loading: boolean }) => (
<NProgress isAnimating={loading}>
{({ isFinished, progress }) => (
<Bar progress={progress} isFinished={isFinished} />
)}
</NProgress>
);
const MemoizedNProgress = React.memo(NProgressBar);
const LoadingBar = (): React.ReactPortal | null => {
const [mounted, setMounted] = useState(false);
const [loading, setLoading] = useState(false);
const router = useRouter();
useEffect(() => {
setMounted(true);
}, []);
useEffect(() => {
const handleLoading = () => {
setLoading(true);
};
const handleFinishedLoading = () => {
setLoading(false);
};
router.events.on('routeChangeStart', handleLoading);
router.events.on('routeChangeComplete', handleFinishedLoading);
router.events.on('routeChangeError', handleFinishedLoading);
return () => {
router.events.off('routeChangeStart', handleLoading);
router.events.off('routeChangeComplete', handleFinishedLoading);
router.events.off('routeChangeError', handleFinishedLoading);
};
}, [router]);
return mounted
? ReactDOM.createPortal(
<MemoizedNProgress loading={loading} />,
document.body
)
: null;
};
export default LoadingBar;

View File

@@ -1,5 +1,10 @@
import React, { useState, useContext, useMemo } from 'react';
import { defineMessages, FormattedNumber, useIntl } from 'react-intl';
import {
defineMessages,
FormattedNumber,
FormattedDate,
useIntl,
} from 'react-intl';
import type { MovieDetails as MovieDetailsType } from '../../../server/models/Movie';
import useSWR from 'swr';
import { useRouter } from 'next/router';
@@ -200,7 +205,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
return (
<div
className="media-page"
className="px-4 pt-16 -mx-4 -mt-16 bg-center bg-cover"
style={{
height: 493,
backgroundImage: `linear-gradient(180deg, rgba(17, 24, 39, 0.47) 0%, rgba(17, 24, 39, 1) 100%), url(//image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data.backdropPath})`,
@@ -379,23 +384,27 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</div>
)}
</SlideOver>
<div className="media-header">
<img
src={
data.posterPath
? `//image.tmdb.org/t/p/w600_and_h900_bestv2${data.posterPath}`
: '/images/overseerr_poster_not_found.png'
}
alt=""
className="media-poster"
/>
<div className="media-title">
<div className="media-status">
<StatusBadge
status={data.mediaInfo?.status}
inProgress={(data.mediaInfo?.downloadStatus ?? []).length > 0}
plexUrl={data.mediaInfo?.plexUrl}
/>
<div className="flex flex-col items-center pt-4 lg:flex-row lg:items-end">
<div className="lg:mr-4">
<img
src={
data.posterPath
? `//image.tmdb.org/t/p/w600_and_h900_bestv2${data.posterPath}`
: '/images/overseerr_poster_not_found.png'
}
alt=""
className="w-32 rounded shadow md:rounded-lg md:shadow-2xl md:w-44 lg:w-52"
/>
</div>
<div className="flex flex-col flex-1 mt-4 text-center text-white lg:mr-4 lg:mt-0 lg:text-left">
<div className="mb-2 space-x-2">
<span className="ml-2 lg:ml-0">
<StatusBadge
status={data.mediaInfo?.status}
inProgress={(data.mediaInfo?.downloadStatus ?? []).length > 0}
plexUrl={data.mediaInfo?.plexUrl}
/>
</span>
{settings.currentSettings.movie4kEnabled &&
hasPermission(
[Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE],
@@ -403,25 +412,25 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
type: 'or',
}
) && (
<StatusBadge
status={data.mediaInfo?.status4k}
is4k
inProgress={
(data.mediaInfo?.downloadStatus4k ?? []).length > 0
}
plexUrl4k={data.mediaInfo?.plexUrl4k}
/>
<span>
<StatusBadge
status={data.mediaInfo?.status4k}
is4k
inProgress={
(data.mediaInfo?.downloadStatus4k ?? []).length > 0
}
plexUrl4k={data.mediaInfo?.plexUrl4k}
/>
</span>
)}
</div>
<h1>
<h1 className="text-2xl lg:text-4xl">
{data.title}{' '}
{data.releaseDate && (
<span className="media-year">
({data.releaseDate.slice(0, 4)})
</span>
<span className="text-2xl">({data.releaseDate.slice(0, 4)})</span>
)}
</h1>
<span className="media-attributes">
<span className="mt-1 text-xs lg:text-base lg:mt-0">
{movieAttributes.length > 0 &&
movieAttributes
.map((t, k) => <span key={k}>{t}</span>)
@@ -432,23 +441,27 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
))}
</span>
</div>
<div className="media-actions">
<PlayButton links={mediaLinks} />
<RequestButton
mediaType="movie"
media={data.mediaInfo}
tmdbId={data.id}
onUpdate={() => revalidate()}
/>
<div className="relative z-10 flex flex-wrap justify-center flex-shrink-0 mt-4 sm:justify-end sm:flex-nowrap lg:mt-0">
<div className="mb-3 sm:mb-0">
<PlayButton links={mediaLinks} />
</div>
<div className="mb-3 sm:mb-0">
<RequestButton
mediaType="movie"
media={data.mediaInfo}
tmdbId={data.id}
onUpdate={() => revalidate()}
/>
</div>
{hasPermission(Permission.MANAGE_REQUESTS) && (
<Button
buttonType="default"
className="ml-2 first:ml-0"
className="mb-3 ml-2 first:ml-0 sm:mb-0"
onClick={() => setShowManager(true)}
>
<svg
className="w-5"
style={{ height: 18 }}
style={{ height: 20 }}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
@@ -471,21 +484,27 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
)}
</div>
</div>
<div className="media-overview">
<div className="media-overview-left">
<div className="tagline">{data.tagline}</div>
<h2>{intl.formatMessage(messages.overview)}</h2>
<p>
<div className="flex flex-col pt-8 pb-4 text-white md:flex-row">
<div className="flex-1 md:mr-8">
<h2 className="text-xl md:text-2xl">
{intl.formatMessage(messages.overview)}
</h2>
<p className="pt-2 text-sm md:text-base">
{data.overview
? data.overview
: intl.formatMessage(messages.overviewunavailable)}
</p>
<ul className="media-crew">
<ul className="grid grid-cols-2 gap-6 mt-6 sm:grid-cols-3">
{sortedCrew.slice(0, 6).map((person) => (
<li key={`crew-${person.job}-${person.id}`}>
<span>{person.job}</span>
<li
className="flex flex-col col-span-1"
key={`crew-${person.job}-${person.id}`}
>
<span className="font-bold">{person.job}</span>
<Link href={`/person/${person.id}`}>
<a className="crew-name">{person.name}</a>
<a className="text-gray-400 transition duration-300 hover:text-underline hover:text-gray-100">
{person.name}
</a>
</Link>
</li>
))}
@@ -514,7 +533,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</div>
)}
</div>
<div className="media-overview-right">
<div className="w-full mt-8 md:w-80 md:mt-0">
{data.collection && (
<div className="mb-6">
<Link href={`/collection/${data.collection.id}`}>
@@ -536,65 +555,80 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</Link>
</div>
)}
<div className="media-facts">
<div className="bg-gray-900 border border-gray-800 rounded-lg shadow">
{(!!data.voteCount ||
(ratingData?.criticsRating && !!ratingData?.criticsScore) ||
(ratingData?.audienceRating && !!ratingData?.audienceScore)) && (
<div className="media-ratings">
<div className="flex items-center justify-center px-4 py-2 border-b border-gray-800 last:border-b-0">
{ratingData?.criticsRating && !!ratingData?.criticsScore && (
<>
<span className="media-rating">
<span className="text-sm">
{ratingData.criticsRating === 'Rotten' ? (
<RTRotten className="w-6 mr-1" />
) : (
<RTFresh className="w-6 mr-1" />
)}
</span>
<span className="mr-4 text-sm text-gray-400 last:mr-0">
{ratingData.criticsScore}%
</span>
</>
)}
{ratingData?.audienceRating && !!ratingData?.audienceScore && (
<>
<span className="media-rating">
<span className="text-sm">
{ratingData.audienceRating === 'Spilled' ? (
<RTAudRotten className="w-6 mr-1" />
) : (
<RTAudFresh className="w-6 mr-1" />
)}
</span>
<span className="mr-4 text-sm text-gray-400 last:mr-0">
{ratingData.audienceScore}%
</span>
</>
)}
{!!data.voteCount && (
<>
<span className="media-rating">
<span className="text-sm">
<TmdbLogo className="w-6 mr-2" />
</span>
<span className="text-sm text-gray-400">
{data.voteAverage}/10
</span>
</>
)}
</div>
)}
<div className="media-fact">
<span>{intl.formatMessage(messages.status)}</span>
<span className="media-fact-value">{data.status}</span>
</div>
{data.releaseDate && (
<div className="media-fact">
<span>{intl.formatMessage(messages.releasedate)}</span>
<span className="media-fact-value">
{intl.formatDate(data.releaseDate, {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.releasedate)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
<FormattedDate
value={new Date(data.releaseDate)}
year="numeric"
month="long"
day="numeric"
/>
</span>
</div>
)}
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.status)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
{data.status}
</span>
</div>
{data.revenue > 0 && (
<div className="media-fact">
<span>{intl.formatMessage(messages.revenue)}</span>
<span className="media-fact-value">
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.revenue)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
<FormattedNumber
currency="USD"
style="currency"
@@ -604,9 +638,11 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</div>
)}
{data.budget > 0 && (
<div className="media-fact">
<span>{intl.formatMessage(messages.budget)}</span>
<span className="media-fact-value">
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.budget)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
<FormattedNumber
currency="USD"
style="currency"
@@ -616,9 +652,11 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</div>
)}
{data.originalLanguage && (
<div className="media-fact">
<span>{intl.formatMessage(messages.originallanguage)}</span>
<span className="media-fact-value">
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.originallanguage)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
<Link
href={`/discover/movies/language/${data.originalLanguage}`}
>
@@ -636,13 +674,13 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</div>
)}
{data.productionCompanies.length > 0 && (
<div className="media-fact">
<span>
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.studio, {
studioCount: data.productionCompanies.length,
})}
</span>
<span className="media-fact-value">
<span className="flex-1 text-sm text-right text-gray-400">
{data.productionCompanies.map((s) => {
return (
<Link
@@ -656,41 +694,43 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</span>
</div>
)}
<div className="media-fact">
<ExternalLinkBlock
mediaType="movie"
tmdbId={data.id}
tvdbId={data.externalIds.tvdbId}
imdbId={data.externalIds.imdbId}
rtUrl={ratingData?.url}
plexUrl={data.mediaInfo?.plexUrl ?? data.mediaInfo?.plexUrl4k}
/>
</div>
</div>
<div className="mt-4">
<ExternalLinkBlock
mediaType="movie"
tmdbId={data.id}
tvdbId={data.externalIds.tvdbId}
imdbId={data.externalIds.imdbId}
rtUrl={ratingData?.url}
plexUrl={data.mediaInfo?.plexUrl ?? data.mediaInfo?.plexUrl4k}
/>
</div>
</div>
</div>
{data.credits.cast.length > 0 && (
<>
<div className="slider-header">
<Link href="/movie/[movieId]/cast" as={`/movie/${data.id}/cast`}>
<a className="slider-title">
<span>{intl.formatMessage(messages.cast)}</span>
<svg
className="w-6 h-6 ml-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</a>
</Link>
<div className="mt-6 mb-4 md:flex md:items-center md:justify-between">
<div className="flex-1 min-w-0">
<Link href="/movie/[movieId]/cast" as={`/movie/${data.id}/cast`}>
<a className="inline-flex items-center text-xl leading-7 text-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate">
<span>{intl.formatMessage(messages.cast)}</span>
<svg
className="w-6 h-6 ml-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</a>
</Link>
</div>
</div>
<Slider
sliderKey="cast"

View File

@@ -128,7 +128,7 @@ const PermissionOption: React.FC<PermissionOptionProps> = ({
/>
</div>
<div className="ml-3 text-sm leading-6">
<label htmlFor={option.id} className="block font-medium text-white">
<label htmlFor={option.id} className="block font-medium">
<div className="flex flex-col">
<span>{option.name}</span>
<span className="text-gray-500">{option.description}</span>

View File

@@ -15,8 +15,8 @@ import { groupBy } from 'lodash';
import PageTitle from '../Common/PageTitle';
const messages = defineMessages({
appearsin: 'Appearances',
crewmember: 'Crew',
appearsin: 'Appears in',
crewmember: 'Crew Member',
ascharacter: 'as {character}',
nobiography: 'No biography available.',
});
@@ -85,9 +85,11 @@ const PersonDetails: React.FC = () => {
const cast = (sortedCast ?? []).length > 0 && (
<>
<div className="slider-header">
<div className="slider-title">
<span>{intl.formatMessage(messages.appearsin)}</span>
<div className="relative z-10 mt-6 mb-4 md:flex md:items-center md:justify-between">
<div className="flex-1 min-w-0">
<div className="inline-flex items-center text-xl leading-7 text-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate">
<span>{intl.formatMessage(messages.appearsin)}</span>
</div>
</div>
</div>
<ul className="cardList">
@@ -125,9 +127,11 @@ const PersonDetails: React.FC = () => {
const crew = (sortedCrew ?? []).length > 0 && (
<>
<div className="slider-header">
<div className="slider-title">
<span>{intl.formatMessage(messages.crewmember)}</span>
<div className="relative z-10 mt-6 mb-4 md:flex md:items-center md:justify-between">
<div className="flex-1 min-w-0">
<div className="inline-flex items-center text-xl leading-7 text-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate">
<span>{intl.formatMessage(messages.crewmember)}</span>
</div>
</div>
</div>
<ul className="cardList">

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import type { MediaRequest } from '../../../server/entity/MediaRequest';
import { useIntl, defineMessages } from 'react-intl';
import { FormattedDate, useIntl, defineMessages } from 'react-intl';
import Badge from '../Common/Badge';
import { MediaRequestStatus } from '../../../server/constants/media';
import Button from '../Common/Button';
@@ -228,11 +228,7 @@ const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
/>
</svg>
<span>
{intl.formatDate(request.createdAt, {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
<FormattedDate value={request.createdAt} />
</span>
</div>
</div>

View File

@@ -256,11 +256,7 @@ const RequestItem: React.FC<RequestItemProps> = ({
{intl.formatMessage(messages.requested)}
</span>
<span className="text-gray-300">
{intl.formatDate(requestData.createdAt, {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
{intl.formatDate(requestData.createdAt)}
</span>
</div>
<div className="card-field">

View File

@@ -18,11 +18,12 @@ const messages = defineMessages({
qualityprofile: 'Quality Profile',
rootfolder: 'Root Folder',
animenote: '* This series is an anime.',
default: '{name} (Default)',
folder: '{path} ({space})',
default: '(Default)',
loadingprofiles: 'Loading profiles…',
loadingfolders: 'Loading folders…',
requestas: 'Request As',
languageprofile: 'Language Profile',
loading: 'Loading…',
loadinglanguages: 'Loading languages…',
});
export type RequestOverrides = {
@@ -265,7 +266,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
<>
<div className="flex flex-col items-center justify-between md:flex-row">
<div className="flex-grow flex-shrink-0 w-full mb-2 md:w-1/4 md:pr-4 md:mb-0">
<label htmlFor="server">
<label htmlFor="server" className="text-label">
{intl.formatMessage(messages.destinationserver)}
</label>
<select
@@ -278,17 +279,16 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
>
{data.map((server) => (
<option key={`server-list-${server.id}`} value={server.id}>
{server.name}
{server.isDefault && server.is4k === is4k
? intl.formatMessage(messages.default, {
name: server.name,
})
: server.name}
? ` ${intl.formatMessage(messages.default)}`
: ''}
</option>
))}
</select>
</div>
<div className="flex-grow flex-shrink-0 w-full mb-2 md:w-1/4 md:pr-4 md:mb-0">
<label htmlFor="profile">
<label htmlFor="profile" className="text-label">
{intl.formatMessage(messages.qualityprofile)}
</label>
<select
@@ -298,11 +298,10 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
onChange={(e) => setSelectedProfile(Number(e.target.value))}
onBlur={(e) => setSelectedProfile(Number(e.target.value))}
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 text-white transition duration-150 ease-in-out bg-gray-800 border-gray-700 rounded-md form-select focus:outline-none focus:ring-blue focus:border-blue-300 sm:text-sm sm:leading-5"
disabled={isValidating || !serverData}
>
{(isValidating || !serverData) && (
{isValidating && (
<option value="">
{intl.formatMessage(messages.loading)}
{intl.formatMessage(messages.loadingprofiles)}
</option>
)}
{!isValidating &&
@@ -312,17 +311,14 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
key={`profile-list${profile.id}`}
value={profile.id}
>
{profile.name}
{isAnime &&
serverData.server.activeAnimeProfileId === profile.id
? intl.formatMessage(messages.default, {
name: profile.name,
})
? ` ${intl.formatMessage(messages.default)}`
: !isAnime &&
serverData.server.activeProfileId === profile.id
? intl.formatMessage(messages.default, {
name: profile.name,
})
: profile.name}
? ` ${intl.formatMessage(messages.default)}`
: ''}
</option>
))}
</select>
@@ -332,7 +328,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
type === 'tv' ? 'md:pr-4' : ''
}`}
>
<label htmlFor="folder">
<label htmlFor="folder" className="text-label">
{intl.formatMessage(messages.rootfolder)}
</label>
<select
@@ -342,11 +338,10 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
onChange={(e) => setSelectedFolder(e.target.value)}
onBlur={(e) => setSelectedFolder(e.target.value)}
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 text-white transition duration-150 ease-in-out bg-gray-800 border-gray-700 rounded-md form-select focus:outline-none focus:ring-blue focus:border-blue-300 sm:text-sm sm:leading-5"
disabled={isValidating || !serverData}
>
{(isValidating || !serverData) && (
{isValidating && (
<option value="">
{intl.formatMessage(messages.loading)}
{intl.formatMessage(messages.loadingfolders)}
</option>
)}
{!isValidating &&
@@ -356,33 +351,21 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
key={`folder-list${folder.id}`}
value={folder.path}
>
{folder.path} ({formatBytes(folder.freeSpace ?? 0)})
{isAnime &&
serverData.server.activeAnimeDirectory === folder.path
? intl.formatMessage(messages.default, {
name: intl.formatMessage(messages.folder, {
path: folder.path,
space: formatBytes(folder.freeSpace ?? 0),
}),
})
? ` ${intl.formatMessage(messages.default)}`
: !isAnime &&
serverData.server.activeDirectory === folder.path
? intl.formatMessage(messages.default, {
name: intl.formatMessage(messages.folder, {
path: folder.path,
space: formatBytes(folder.freeSpace ?? 0),
}),
})
: intl.formatMessage(messages.folder, {
path: folder.path,
space: formatBytes(folder.freeSpace ?? 0),
})}
? ` ${intl.formatMessage(messages.default)}`
: ''}
</option>
))}
</select>
</div>
{type === 'tv' && (
<div className="flex-grow flex-shrink-0 w-full mb-2 md:w-1/4 md:mb-0">
<label htmlFor="language">
<label htmlFor="language" className="text-label">
{intl.formatMessage(messages.languageprofile)}
</label>
<select
@@ -396,11 +379,10 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
setSelectedLanguage(parseInt(e.target.value))
}
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 text-white transition duration-150 ease-in-out bg-gray-800 border-gray-700 rounded-md form-select focus:outline-none focus:ring-blue focus:border-blue-300 sm:text-sm sm:leading-5"
disabled={isValidating || !serverData}
>
{(isValidating || !serverData) && (
{isValidating && (
<option value="">
{intl.formatMessage(messages.loading)}
{intl.formatMessage(messages.loadinglanguages)}
</option>
)}
{!isValidating &&
@@ -410,19 +392,16 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
key={`folder-list${language.id}`}
value={language.id}
>
{language.name}
{isAnime &&
serverData.server.activeAnimeLanguageProfileId ===
language.id
? intl.formatMessage(messages.default, {
name: language.name,
})
? ` ${intl.formatMessage(messages.default)}`
: !isAnime &&
serverData.server.activeLanguageProfileId ===
language.id
? intl.formatMessage(messages.default, {
name: language.name,
})
: language.name}
? ` ${intl.formatMessage(messages.default)}`
: ''}
</option>
))}
</select>
@@ -433,7 +412,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
)}
{hasPermission([Permission.MANAGE_REQUESTS, Permission.MANAGE_USERS]) &&
selectedUser && (
<div className="first:mt-0 sm:mt-4">
<div className="mt-0 sm:mt-2">
<Listbox
as="div"
value={selectedUser}
@@ -442,7 +421,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
>
{({ open }) => (
<>
<Listbox.Label>
<Listbox.Label className="text-label">
{intl.formatMessage(messages.requestas)}
</Listbox.Label>
<div className="relative">

View File

@@ -9,8 +9,6 @@ import * as Yup from 'yup';
import { useToasts } from 'react-toast-notifications';
import NotificationTypeSelector from '../../NotificationTypeSelector';
import Alert from '../../Common/Alert';
import Badge from '../../Common/Badge';
import globalMessages from '../../../i18n/globalMessages';
const messages = defineMessages({
save: 'Save Changes',
@@ -41,27 +39,8 @@ const messages = defineMessages({
emailNotificationTypesAlertDescriptionPt2:
'<strong>Media Approved</strong>, <strong>Media Declined</strong>, and <strong>Media Available</strong>\
email notifications are sent to the user who submitted the request.',
pgpPrivateKey: '<PgpLink>PGP</PgpLink> Private Key',
pgpPrivateKeyTip:
'Sign encrypted email messages (PGP password is also required)',
pgpPassword: '<PgpLink>PGP</PgpLink> Password',
pgpPasswordTip:
'Sign encrypted email messages (PGP private key is also required)',
});
export function PgpLink(msg: string): JSX.Element {
return (
<a
href="https://www.openpgp.org/"
target="_blank"
rel="noreferrer"
className="text-gray-100 underline transition duration-300 hover:text-white"
>
{msg}
</a>
);
}
const NotificationsEmail: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
@@ -98,8 +77,6 @@ const NotificationsEmail: React.FC = () => {
authPass: data.options.authPass,
allowSelfSigned: data.options.allowSelfSigned,
senderName: data.options.senderName,
pgpPrivateKey: data.options.pgpPrivateKey,
pgpPassword: data.options.pgpPassword,
}}
validationSchema={NotificationsEmailSchema}
onSubmit={async (values) => {
@@ -116,8 +93,6 @@ const NotificationsEmail: React.FC = () => {
authPass: values.authPass,
allowSelfSigned: values.allowSelfSigned,
senderName: values.senderName,
pgpPrivateKey: values.pgpPrivateKey,
pgpPassword: values.pgpPassword,
},
});
addToast(intl.formatMessage(messages.emailsettingssaved), {
@@ -147,8 +122,6 @@ const NotificationsEmail: React.FC = () => {
authUser: values.authUser,
authPass: values.authPass,
senderName: values.senderName,
pgpPrivateKey: values.pgpPrivateKey,
pgpPassword: values.pgpPassword,
},
});
@@ -318,56 +291,6 @@ const NotificationsEmail: React.FC = () => {
</div>
</div>
</div>
<div className="form-row">
<label htmlFor="pgpPrivateKey" className="text-label">
<span className="mr-2">
{intl.formatMessage(messages.pgpPrivateKey, {
PgpLink: PgpLink,
})}
</span>
<Badge badgeType="danger">
{intl.formatMessage(globalMessages.advanced)}
</Badge>
<span className="label-tip">
{intl.formatMessage(messages.pgpPrivateKeyTip)}
</span>
</label>
<div className="form-input">
<div className="form-input-field">
<Field
id="pgpPrivateKey"
name="pgpPrivateKey"
as="textarea"
rows="3"
/>
</div>
</div>
</div>
<div className="form-row">
<label htmlFor="pgpPassword" className="text-label">
<span className="mr-2">
{intl.formatMessage(messages.pgpPassword, {
PgpLink: PgpLink,
})}
</span>
<Badge badgeType="danger">
{intl.formatMessage(globalMessages.advanced)}
</Badge>
<span className="label-tip">
{intl.formatMessage(messages.pgpPasswordTip)}
</span>
</label>
<div className="form-input">
<div className="form-input-field">
<Field
id="pgpPassword"
name="pgpPassword"
type="password"
autoComplete="off"
/>
</div>
</div>
</div>
<div
role="group"
aria-labelledby="group-label"

View File

@@ -41,13 +41,13 @@ const NotificationsPushover: React.FC = () => {
accessToken: Yup.string()
.required(intl.formatMessage(messages.validationAccessTokenRequired))
.matches(
/^[a-z\d]{30}$/i,
/^a[A-Za-z0-9]{29}$/,
intl.formatMessage(messages.validationAccessTokenRequired)
),
userToken: Yup.string()
.required(intl.formatMessage(messages.validationUserTokenRequired))
.matches(
/^[a-z\d]{30}$/i,
/^[ug][A-Za-z0-9]{29}$/,
intl.formatMessage(messages.validationUserTokenRequired)
),
});

View File

@@ -18,7 +18,7 @@ const messages = defineMessages({
botAPI: 'Bot Authentication Token',
chatId: 'Chat ID',
validationBotAPIRequired: 'You must provide a bot authentication token',
validationChatIdRequired: 'You must provide a valid chat ID',
validationChatIdRequired: 'You must provide a chat ID',
telegramsettingssaved: 'Telegram notification settings saved successfully!',
telegramsettingsfailed: 'Telegram notification settings failed to save.',
testsent: 'Test notification sent!',

View File

@@ -279,7 +279,7 @@ const SettingsServices: React.FC = () => {
<p>{intl.formatMessage(messages.nodefaultdescription)}</p>
</Alert>
)}
<ul className="grid max-w-6xl grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3">
<ul className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{radarrData.map((radarr) => (
<ServerInstance
key={`radarr-config-${radarr.id}`}
@@ -350,7 +350,7 @@ const SettingsServices: React.FC = () => {
<p>{intl.formatMessage(messages.nodefaultdescription)}</p>
</Alert>
)}
<ul className="grid max-w-6xl grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3">
<ul className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{sonarrData.map((sonarr) => (
<ServerInstance
key={`sonarr-config-${sonarr.id}`}

View File

@@ -1,5 +1,5 @@
import React, { useState, useContext, useMemo } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { FormattedDate, defineMessages, useIntl } from 'react-intl';
import useSWR from 'swr';
import { useRouter } from 'next/router';
import Button from '../Common/Button';
@@ -60,7 +60,7 @@ const messages = defineMessages({
If this item exists in your Plex library, the media information will be recreated during the next scan.',
approve: 'Approve',
decline: 'Decline',
showtype: 'Series Type',
showtype: 'Show Type',
anime: 'Anime',
network: '{networkCount, plural, one {Network} other {Networks}}',
viewfullcrew: 'View Full Crew',
@@ -74,8 +74,6 @@ const messages = defineMessages({
mark4kavailable: 'Mark 4K as Available',
allseasonsmarkedavailable: '* All seasons will be marked as available.',
seasons: '{seasonCount, plural, one {# Season} other {# Seasons}}',
episodeRuntime: 'Episode Runtime',
episodeRuntimeMinutes: '{runtime} minutes',
});
interface TvDetailsProps {
@@ -225,7 +223,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
return (
<div
className="media-page"
className="px-4 pt-16 -mx-4 -mt-16 bg-center bg-cover"
style={{
height: 493,
backgroundImage: `linear-gradient(180deg, rgba(17, 24, 39, 0.47) 0%, rgba(17, 24, 39, 1) 100%), url(//image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data.backdropPath})`,
@@ -417,46 +415,52 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
</div>
)}
</SlideOver>
<div className="media-header">
<img
src={
data.posterPath
? `//image.tmdb.org/t/p/w600_and_h900_bestv2${data.posterPath}`
: '/images/overseerr_poster_not_found.png'
}
alt=""
className="media-poster"
/>
<div className="media-title">
<div className="media-status">
<StatusBadge
status={data.mediaInfo?.status}
inProgress={(data.mediaInfo?.downloadStatus ?? []).length > 0}
plexUrl={data.mediaInfo?.plexUrl}
/>
<div className="flex flex-col items-center pt-4 lg:flex-row lg:items-end">
<div className="lg:mr-4">
<img
src={
data.posterPath
? `//image.tmdb.org/t/p/w600_and_h900_bestv2${data.posterPath}`
: '/images/overseerr_poster_not_found.png'
}
alt=""
className="w-32 rounded shadow md:rounded-lg md:shadow-2xl md:w-44 lg:w-52"
/>
</div>
<div className="flex flex-col flex-1 mt-4 text-center text-white lg:mr-4 lg:mt-0 lg:text-left">
<div className="mb-2 space-x-2">
<span className="ml-2 lg:ml-0">
<StatusBadge
status={data.mediaInfo?.status}
inProgress={(data.mediaInfo?.downloadStatus ?? []).length > 0}
plexUrl={data.mediaInfo?.plexUrl}
/>
</span>
{settings.currentSettings.series4kEnabled &&
hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_TV], {
type: 'or',
}) && (
<StatusBadge
status={data.mediaInfo?.status4k}
is4k
inProgress={
(data.mediaInfo?.downloadStatus4k ?? []).length > 0
}
plexUrl4k={data.mediaInfo?.plexUrl4k}
/>
<span>
<StatusBadge
status={data.mediaInfo?.status4k}
is4k
inProgress={
(data.mediaInfo?.downloadStatus4k ?? []).length > 0
}
plexUrl4k={data.mediaInfo?.plexUrl4k}
/>
</span>
)}
</div>
<h1>
<h1 className="text-2xl lg:text-4xl">
{data.name}{' '}
{data.firstAirDate && (
<span className="media-year">
<span className="text-2xl">
({data.firstAirDate.slice(0, 4)})
</span>
)}
</h1>
<span className="media-attributes">
<span className="mt-1 text-xs lg:text-base lg:mt-0">
{seriesAttributes.length > 0 &&
seriesAttributes
.map((t, k) => <span key={k}>{t}</span>)
@@ -467,24 +471,29 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
))}
</span>
</div>
<div className="media-actions">
<PlayButton links={mediaLinks} />
<RequestButton
mediaType="tv"
onUpdate={() => revalidate()}
tmdbId={data?.id}
media={data?.mediaInfo}
isShowComplete={isComplete}
is4kShowComplete={is4kComplete}
/>
<div className="relative z-10 flex flex-wrap justify-center flex-shrink-0 mt-4 sm:justify-end sm:flex-nowrap lg:mt-0">
<div className="mb-3 sm:mb-0">
<PlayButton links={mediaLinks} />
</div>
<div className="mb-3 sm:mb-0">
<RequestButton
mediaType="tv"
onUpdate={() => revalidate()}
tmdbId={data?.id}
media={data?.mediaInfo}
isShowComplete={isComplete}
is4kShowComplete={is4kComplete}
/>
</div>
{hasPermission(Permission.MANAGE_REQUESTS) && (
<Button
buttonType="default"
className="ml-2 first:ml-0"
className="mb-3 ml-2 first:ml-0 sm:mb-0"
onClick={() => setShowManager(true)}
>
<svg
className="w-5"
style={{ height: 20 }}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
@@ -507,16 +516,17 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
)}
</div>
</div>
<div className="media-overview">
<div className="media-overview-left">
<div className="tagline">{data.tagline}</div>
<h2>{intl.formatMessage(messages.overview)}</h2>
<p>
<div className="flex flex-col pt-8 pb-4 text-white md:flex-row">
<div className="flex-1 md:mr-8">
<h2 className="text-xl md:text-2xl">
{intl.formatMessage(messages.overview)}
</h2>
<p className="pt-2 text-sm md:text-base">
{data.overview
? data.overview
: intl.formatMessage(messages.overviewunavailable)}
</p>
<ul className="media-crew">
<ul className="grid grid-cols-2 gap-6 mt-6 sm:grid-cols-3">
{(data.createdBy.length > 0
? [
...data.createdBy.map(
@@ -532,10 +542,15 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
)
.slice(0, 6)
.map((person) => (
<li key={`crew-${person.job}-${person.id}`}>
<span>{person.job}</span>
<li
className="flex flex-col col-span-1"
key={`crew-${person.job}-${person.id}`}
>
<span className="font-bold">{person.job}</span>
<Link href={`/person/${person.id}`}>
<a className="crew-name">{person.name}</a>
<a className="text-gray-400 transition duration-300 hover:text-underline hover:text-gray-100">
{person.name}
</a>
</Link>
</li>
))}
@@ -564,92 +579,108 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
</div>
)}
</div>
<div className="media-overview-right">
<div className="media-facts">
<div className="w-full mt-8 md:w-80 md:mt-0">
<div className="bg-gray-900 border border-gray-800 rounded-lg shadow">
{(!!data.voteCount ||
(ratingData?.criticsRating && !!ratingData?.criticsScore) ||
(ratingData?.audienceRating && !!ratingData?.audienceScore)) && (
<div className="media-ratings">
<div className="flex items-center justify-center px-4 py-2 border-b border-gray-800 last:border-b-0">
{ratingData?.criticsRating && !!ratingData?.criticsScore && (
<span className="media-rating">
{ratingData.criticsRating === 'Rotten' ? (
<RTRotten className="w-6 mr-1" />
) : (
<RTFresh className="w-6 mr-1" />
)}
{ratingData.criticsScore}%
</span>
<>
<span className="text-sm">
{ratingData.criticsRating === 'Rotten' ? (
<RTRotten className="w-6 mr-1" />
) : (
<RTFresh className="w-6 mr-1" />
)}
</span>
<span className="mr-4 text-sm text-gray-400 last:mr-0">
{ratingData.criticsScore}%
</span>
</>
)}
{ratingData?.audienceRating && !!ratingData?.audienceScore && (
<span className="media-rating">
{ratingData.audienceRating === 'Spilled' ? (
<RTAudRotten className="w-6 mr-1" />
) : (
<RTAudFresh className="w-6 mr-1" />
)}
{ratingData.audienceScore}%
</span>
<>
<span className="text-sm">
{ratingData.audienceRating === 'Spilled' ? (
<RTAudRotten className="w-6 mr-1" />
) : (
<RTAudFresh className="w-6 mr-1" />
)}
</span>
<span className="mr-4 text-sm text-gray-400 last:mr-0">
{ratingData.audienceScore}%
</span>
</>
)}
{!!data.voteCount && (
<span className="media-rating">
<TmdbLogo className="w-6 mr-2" />
{data.voteAverage}/10
</span>
<>
<span className="text-sm">
<TmdbLogo className="w-6 mr-2" />
</span>
<span className="text-sm text-gray-400">
{data.voteAverage}/10
</span>
</>
)}
</div>
)}
{data.keywords.some(
(keyword) => keyword.id === ANIME_KEYWORD_ID
) && (
<div className="media-fact">
<span>{intl.formatMessage(messages.showtype)}</span>
<span className="media-fact-value">
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.showtype)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
{intl.formatMessage(messages.anime)}
</span>
</div>
)}
<div className="media-fact">
<span>{intl.formatMessage(messages.status)}</span>
<span className="media-fact-value">{data.status}</span>
</div>
{data.firstAirDate && (
<div className="media-fact">
<span>{intl.formatMessage(messages.firstAirDate)}</span>
<span className="media-fact-value">
{intl.formatDate(data.firstAirDate, {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.firstAirDate)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
<FormattedDate
value={new Date(data.firstAirDate)}
year="numeric"
month="long"
day="numeric"
/>
</span>
</div>
)}
{data.nextEpisodeToAir && (
<div className="media-fact">
<span>{intl.formatMessage(messages.nextAirDate)}</span>
<span className="media-fact-value">
{intl.formatDate(data.nextEpisodeToAir.airDate, {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</span>
</div>
)}
{data.episodeRunTime.length > 0 && (
<div className="media-fact">
<span>{intl.formatMessage(messages.episodeRuntime)}</span>
<span className="media-fact-value">
{intl.formatMessage(messages.episodeRuntimeMinutes, {
runtime: data.episodeRunTime[0],
})}
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.nextAirDate)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
<FormattedDate
value={new Date(data.nextEpisodeToAir?.airDate)}
year="numeric"
month="long"
day="numeric"
/>
</span>
</div>
)}
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.status)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
{data.status}
</span>
</div>
{data.originalLanguage && (
<div className="media-fact">
<span>{intl.formatMessage(messages.originallanguage)}</span>
<span className="media-fact-value">
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.originallanguage)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
<Link href={`/discover/tv/language/${data.originalLanguage}`}>
<a className="hover:underline">
{intl.formatDisplayName(data.originalLanguage, {
@@ -665,13 +696,13 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
</div>
)}
{data.networks.length > 0 && (
<div className="media-fact">
<span>
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
<span className="text-sm">
{intl.formatMessage(messages.network, {
networkCount: data.networks.length,
})}
</span>
<span className="media-fact-value">
<span className="flex-1 text-sm text-right text-gray-400">
{data.networks
.map((n) => (
<Link
@@ -689,41 +720,43 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
</span>
</div>
)}
<div className="media-fact">
<ExternalLinkBlock
mediaType="tv"
tmdbId={data.id}
tvdbId={data.externalIds.tvdbId}
imdbId={data.externalIds.imdbId}
rtUrl={ratingData?.url}
plexUrl={data.mediaInfo?.plexUrl ?? data.mediaInfo?.plexUrl4k}
/>
</div>
</div>
<div className="mt-4">
<ExternalLinkBlock
mediaType="tv"
tmdbId={data.id}
tvdbId={data.externalIds.tvdbId}
imdbId={data.externalIds.imdbId}
rtUrl={ratingData?.url}
plexUrl={data.mediaInfo?.plexUrl ?? data.mediaInfo?.plexUrl4k}
/>
</div>
</div>
</div>
{data.credits.cast.length > 0 && (
<>
<div className="slider-header">
<Link href="/tv/[tvId]/cast" as={`/tv/${data.id}/cast`}>
<a className="slider-title">
<span>{intl.formatMessage(messages.cast)}</span>
<svg
className="w-6 h-6 ml-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</a>
</Link>
<div className="mt-6 mb-4 md:flex md:items-center md:justify-between">
<div className="flex-1 min-w-0">
<Link href="/tv/[tvId]/cast" as={`/tv/${data.id}/cast`}>
<a className="inline-flex items-center text-xl leading-7 text-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate">
<span>{intl.formatMessage(messages.cast)}</span>
<svg
className="w-6 h-6 ml-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</a>
</Link>
</div>
</div>
<Slider
sliderKey="cast"

View File

@@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
import PermissionEdit from '../PermissionEdit';
import Modal from '../Common/Modal';
import { User, useUser } from '../../hooks/useUser';
import { defineMessages, useIntl } from 'react-intl';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import axios from 'axios';
import { useToasts } from 'react-toast-notifications';
@@ -19,7 +19,8 @@ const messages = defineMessages({
save: 'Save Changes',
saving: 'Saving…',
userfail: 'Something went wrong while saving the user.',
edituser: 'Edit User Permissions',
permissions: 'Permissions',
edituser: 'Edit User',
});
const BulkEditModal: React.FC<BulkEditProps> = ({
@@ -92,12 +93,27 @@ const BulkEditModal: React.FC<BulkEditProps> = ({
okText={intl.formatMessage(messages.save)}
onCancel={onCancel}
>
<div className="mb-6">
<PermissionEdit
actingUser={currentUser}
currentPermission={currentPermission}
onUpdate={(newPermission) => setCurrentPermission(newPermission)}
/>
<div className="mt-6 mb-6">
<div role="group" aria-labelledby="group-label">
<div className="form-row">
<div>
<div id="group-label" className="group-label">
<FormattedMessage {...messages.permissions} />
</div>
</div>
<div className="form-input">
<div className="max-w-lg">
<PermissionEdit
actingUser={currentUser}
currentPermission={currentPermission}
onUpdate={(newPermission) =>
setCurrentPermission(newPermission)
}
/>
</div>
</div>
</div>
</div>
</div>
</Modal>
);

View File

@@ -2,7 +2,7 @@ import React, { useState } from 'react';
import useSWR from 'swr';
import LoadingSpinner from '../Common/LoadingSpinner';
import Badge from '../Common/Badge';
import { defineMessages, useIntl } from 'react-intl';
import { FormattedDate, defineMessages, useIntl } from 'react-intl';
import Button from '../Common/Button';
import { hasPermission } from '../../../server/lib/permissions';
import { Permission, User, UserType, useUser } from '../../hooks/useUser';
@@ -551,23 +551,14 @@ const UserList: React.FC = () => {
: intl.formatMessage(messages.user)}
</Table.TD>
<Table.TD>
{intl.formatDate(user.createdAt, {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
<FormattedDate value={user.createdAt} />
</Table.TD>
<Table.TD>
{intl.formatDate(user.updatedAt, {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
<FormattedDate value={user.updatedAt} />
</Table.TD>
<Table.TD alignText="right">
<Button
buttonType="warning"
disabled={user.id === 1 && currentUser?.id !== 1}
className="mr-2"
onClick={() =>
router.push(
@@ -580,11 +571,7 @@ const UserList: React.FC = () => {
</Button>
<Button
buttonType="danger"
disabled={
user.id === 1 ||
(currentUser?.id !== 1 &&
hasPermission(Permission.ADMIN, user.permissions))
}
disabled={hasPermission(Permission.ADMIN, user.permissions)}
onClick={() => setDeleteModal({ isOpen: true, user })}
>
{intl.formatMessage(messages.delete)}

View File

@@ -27,11 +27,7 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
const subtextItems: React.ReactNode[] = [
intl.formatMessage(messages.joindate, {
joindate: intl.formatDate(user.createdAt, {
year: 'numeric',
month: 'long',
day: 'numeric',
}),
joindate: intl.formatDate(user.createdAt),
}),
intl.formatMessage(messages.requests, {
requestCount: user.requestCount,
@@ -43,7 +39,7 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
}
return (
<div className="relative z-40 mt-6 mb-12 lg:flex lg:items-end lg:justify-between lg:space-x-5">
<div className="relative z-40 mt-6 mb-12 md:flex md:items-end md:justify-between md:space-x-5">
<div className="flex items-end space-x-5 justify-items-end">
<div className="flex-shrink-0">
<div className="relative">
@@ -84,9 +80,9 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
</p>
</div>
</div>
<div className="flex flex-col-reverse mt-6 space-y-4 space-y-reverse justify-stretch lg:flex-row lg:justify-end lg:space-x-reverse lg:space-y-0 lg:space-x-3">
<div className="flex flex-col-reverse mt-6 space-y-4 space-y-reverse justify-stretch sm:flex-row-reverse sm:justify-end sm:space-x-reverse sm:space-y-0 sm:space-x-3 md:mt-0 md:flex-row md:space-x-3">
{(loggedInUser?.id === user.id ||
(user.id !== 1 && hasPermission(Permission.MANAGE_USERS))) &&
hasPermission(Permission.MANAGE_USERS)) &&
!isSettingsPage ? (
<Link
href={
@@ -113,30 +109,28 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
</Button>
</Link>
) : (
isSettingsPage && (
<Link
href={
loggedInUser?.id === user.id ? `/profile` : `/users/${user.id}`
}
passHref
>
<Button as="a">
<svg
className="w-5 h-5 mr-1"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
clipRule="evenodd"
/>
</svg>
{intl.formatMessage(messages.profile)}
</Button>
</Link>
)
<Link
href={
loggedInUser?.id === user.id ? `/profile` : `/users/${user.id}`
}
passHref
>
<Button as="a">
<svg
className="w-5 h-5 mr-1"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
clipRule="evenodd"
/>
</svg>
{intl.formatMessage(messages.profile)}
</Button>
</Link>
)}
</div>
</div>

View File

@@ -11,9 +11,6 @@ import Button from '../../../Common/Button';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import { UserSettingsNotificationsResponse } from '../../../../../server/interfaces/api/userSettingsInterfaces';
import * as Yup from 'yup';
import Badge from '../../../Common/Badge';
import globalMessages from '../../../../i18n/globalMessages';
import { PgpLink } from '../../../Settings/Notifications/NotificationsEmail';
const messages = defineMessages({
notificationsettings: 'Notification Settings',
@@ -35,8 +32,6 @@ const messages = defineMessages({
localuser: 'Local User',
toastSettingsSuccess: 'Settings successfully saved!',
toastSettingsFailure: 'Something went wrong while saving settings.',
pgpKey: '<PgpLink>PGP</PgpLink> Public Key',
pgpKeyTip: 'Encrypt email messages',
});
const UserNotificationSettings: React.FC = () => {
@@ -81,7 +76,6 @@ const UserNotificationSettings: React.FC = () => {
discordId: data?.discordId,
telegramChatId: data?.telegramChatId,
telegramSendSilently: data?.telegramSendSilently,
pgpKey: data?.pgpKey,
}}
validationSchema={UserNotificationSettingsSchema}
enableReinitialize
@@ -94,7 +88,6 @@ const UserNotificationSettings: React.FC = () => {
discordId: values.discordId,
telegramChatId: values.telegramChatId,
telegramSendSilently: values.telegramSendSilently,
pgpKey: values.pgpKey,
}
);
@@ -130,29 +123,6 @@ const UserNotificationSettings: React.FC = () => {
/>
</div>
</div>
<div className="form-row">
<label htmlFor="pgpKey" className="text-label">
<span className="mr-2">
{intl.formatMessage(messages.pgpKey, {
PgpLink: PgpLink,
})}
</span>
<Badge badgeType="danger">
{intl.formatMessage(globalMessages.advanced)}
</Badge>
<span className="label-tip">
{intl.formatMessage(messages.pgpKeyTip)}
</span>
</label>
<div className="form-input">
<div className="form-input-field">
<Field id="pgpKey" name="pgpKey" as="textarea" rows="3" />
</div>
{errors.pgpKey && touched.pgpKey && (
<div className="error">{errors.pgpKey}</div>
)}
</div>
</div>
<div className="form-row">
<label htmlFor="discordId" className="text-label">
<span>{intl.formatMessage(messages.discordId)}</span>

View File

@@ -10,7 +10,6 @@ import Error from '../../../../pages/_error';
import Button from '../../../Common/Button';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import PermissionEdit from '../../../PermissionEdit';
import Alert from '../../../Common/Alert';
const messages = defineMessages({
displayName: 'Display Name',
@@ -21,8 +20,6 @@ const messages = defineMessages({
toastSettingsSuccess: 'Settings successfully saved!',
toastSettingsFailure: 'Something went wrong while saving settings.',
permissions: 'Permissions',
unauthorized: 'Unauthorized',
unauthorizedDescription: 'You cannot modify your own permissions.',
});
const UserPermissions: React.FC = () => {
@@ -43,21 +40,6 @@ const UserPermissions: React.FC = () => {
return <Error statusCode={500} />;
}
if (currentUser?.id !== 1 && currentUser?.id === user?.id) {
return (
<>
<div className="mb-6">
<h3 className="heading">
{intl.formatMessage(messages.permissions)}
</h3>
</div>
<Alert title={intl.formatMessage(messages.unauthorized)} type="error">
{intl.formatMessage(messages.unauthorizedDescription)}
</Alert>
</>
);
}
return (
<>
<div className="mb-6">
@@ -92,15 +74,28 @@ const UserPermissions: React.FC = () => {
{({ isSubmitting, setFieldValue, values }) => {
return (
<Form className="section">
<div className="max-w-3xl">
<PermissionEdit
actingUser={currentUser}
currentUser={user}
currentPermission={values.currentPermissions ?? 0}
onUpdate={(newPermission) =>
setFieldValue('currentPermissions', newPermission)
}
/>
<div
role="group"
aria-labelledby="group-label"
className="form-group"
>
<div className="form-row">
<span id="group-label" className="group-label">
{intl.formatMessage(messages.permissions)}
</span>
<div className="form-input">
<div className="max-w-lg">
<PermissionEdit
actingUser={currentUser}
currentUser={user}
currentPermission={values.currentPermissions ?? 0}
onUpdate={(newPermission) =>
setFieldValue('currentPermissions', newPermission)
}
/>
</div>
</div>
</div>
</div>
<div className="actions">
<div className="flex justify-end">

View File

@@ -9,7 +9,6 @@ import LoadingSpinner from '../../Common/LoadingSpinner';
import PageTitle from '../../Common/PageTitle';
import ProfileHeader from '../ProfileHeader';
import useSettings from '../../../hooks/useSettings';
import Alert from '../../Common/Alert';
const messages = defineMessages({
settings: 'User Settings',
@@ -17,9 +16,6 @@ const messages = defineMessages({
menuChangePass: 'Password',
menuNotifications: 'Notifications',
menuPermissions: 'Permissions',
unauthorized: 'Unauthorized',
unauthorizedDescription:
"You do not have permission to modify this user's settings.",
});
interface SettingsRoute {
@@ -28,7 +24,6 @@ interface SettingsRoute {
regex: RegExp;
requiredPermission?: Permission | Permission[];
permissionType?: { type: 'and' | 'or' };
hidden?: boolean;
}
const UserSettings: React.FC = ({ children }) => {
@@ -56,15 +51,6 @@ const UserSettings: React.FC = ({ children }) => {
text: intl.formatMessage(messages.menuChangePass),
route: '/settings/password',
regex: /\/settings\/password/,
hidden:
(!settings.currentSettings.localLogin &&
!hasPermission(
Permission.MANAGE_SETTINGS,
currentUser?.permissions ?? 0
)) ||
(currentUser?.id !== 1 &&
currentUser?.id !== user?.id &&
hasPermission(Permission.ADMIN, user?.permissions ?? 0)),
},
{
text: intl.formatMessage(messages.menuNotifications),
@@ -76,7 +62,6 @@ const UserSettings: React.FC = ({ children }) => {
route: '/settings/permissions',
regex: /\/settings\/permissions/,
requiredPermission: Permission.MANAGE_USERS,
hidden: currentUser?.id !== 1 && currentUser?.id === user.id,
},
];
@@ -91,6 +76,20 @@ const UserSettings: React.FC = ({ children }) => {
regex: RegExp;
isMobile?: boolean;
}> = ({ children, route, regex, isMobile = false }) => {
if (
route === '/settings/password' &&
((!settings.currentSettings.localLogin &&
!hasPermission(
Permission.MANAGE_SETTINGS,
currentUser?.permissions ?? 0
)) ||
(currentUser?.id !== 1 &&
currentUser?.id !== user?.id &&
hasPermission(Permission.ADMIN, user?.permissions ?? 0)))
) {
return null;
}
const finalRoute = router.asPath.includes('/profile')
? `/profile${route}`
: `/users/${user.id}${route}`;
@@ -112,20 +111,6 @@ const UserSettings: React.FC = ({ children }) => {
);
};
if (currentUser?.id !== 1 && user.id === 1) {
return (
<>
<PageTitle title={intl.formatMessage(messages.settings)} />
<ProfileHeader user={user} isSettingsPage />
<div className="mt-6">
<Alert title={intl.formatMessage(messages.unauthorized)} type="error">
{intl.formatMessage(messages.unauthorizedDescription)}
</Alert>
</div>
</>
);
}
const currentRoute = settingsRoutes.find(
(route) => !!router.pathname.match(route.regex)
)?.route;
@@ -151,16 +136,14 @@ const UserSettings: React.FC = ({ children }) => {
aria-label="Selected tab"
>
{settingsRoutes
.filter(
(route) =>
!route.hidden &&
(route.requiredPermission
? hasPermission(
route.requiredPermission,
currentUser?.permissions ?? 0,
route.permissionType
)
: true)
.filter((route) =>
route.requiredPermission
? hasPermission(
route.requiredPermission,
currentUser?.permissions ?? 0,
route.permissionType
)
: true
)
.map((route, index) => (
<SettingsLink
@@ -178,16 +161,14 @@ const UserSettings: React.FC = ({ children }) => {
<div className="border-b border-gray-600">
<nav className="flex -mb-px">
{settingsRoutes
.filter(
(route) =>
!route.hidden &&
(route.requiredPermission
? hasPermission(
route.requiredPermission,
currentUser?.permissions ?? 0,
route.permissionType
)
: true)
.filter((route) =>
route.requiredPermission
? hasPermission(
route.requiredPermission,
currentUser?.permissions ?? 0,
route.permissionType
)
: true
)
.map((route, index) => (
<SettingsLink

View File

@@ -16,7 +16,6 @@ import { defineMessages, useIntl } from 'react-intl';
const messages = defineMessages({
recentrequests: 'Recent Requests',
norequests: 'No Requests',
});
type MediaTitle = MovieDetails | TvDetails;
@@ -96,7 +95,7 @@ const UserProfile: React.FC = () => {
/>
))}
placeholder={<RequestCard.Placeholder />}
emptyMessage={intl.formatMessage(messages.norequests)}
emptyMessage={'No Requests'}
/>
</div>
</>

View File

@@ -51,13 +51,13 @@
"components.PlexLoginButton.loading": "Wird geladen …",
"components.PlexLoginButton.loggingin": "Wird angemeldet …",
"components.PlexLoginButton.loginwithplex": "Anmelden",
"components.RequestBlock.seasons": "{seasonCount, plural, one {Staffel} other {Staffeln}}",
"components.RequestBlock.seasons": "Staffeln",
"components.RequestCard.all": "Alle",
"components.RequestCard.requestedby": "Angefragt von {username}",
"components.RequestCard.seasons": "{seasonCount, plural, one {Staffel} other {Staffeln}}",
"components.RequestCard.seasons": "Staffeln",
"components.RequestList.RequestItem.notavailable": "entf.",
"components.RequestList.RequestItem.requestedby": "Angefragt von {username}",
"components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Staffel} other {Staffeln}}",
"components.RequestList.RequestItem.seasons": "Staffeln",
"components.RequestList.mediaInfo": "Medieninfos",
"components.RequestList.modifiedBy": "Zuletzt geändert von",
"components.RequestList.next": "Nächste",
@@ -67,7 +67,7 @@
"components.RequestList.showingresults": "Zeigt <strong>{from}</strong> bis <strong> {to} </strong> von <strong> {total} </strong> Ergebnissen",
"components.RequestList.status": "Status",
"components.RequestModal.cancel": "Anfrage abbrechen",
"components.RequestModal.cancelling": "Abbrechen …",
"components.RequestModal.cancelling": "Abbrechen…",
"components.RequestModal.cancelrequest": "Dadurch wird deine Anfrage entfernt. Bist du sicher, dass du weitermachen willst?",
"components.RequestModal.close": "Schließen",
"components.RequestModal.extras": "Extras",
@@ -531,7 +531,7 @@
"components.RequestModal.AdvancedRequester.loadingprofiles": "Lade Profile …",
"components.RequestModal.AdvancedRequester.loadingfolders": "Lade Ordner …",
"components.RequestModal.AdvancedRequester.destinationserver": "Zielserver",
"components.RequestModal.AdvancedRequester.default": "{name} (Standard)",
"components.RequestModal.AdvancedRequester.default": "(Standard)",
"components.RequestModal.AdvancedRequester.animenote": "* Diese Serie ist ein Anime.",
"components.RequestModal.AdvancedRequester.advancedoptions": "Erweiterte Einstellungen",
"components.RequestBlock.server": "Zielserver",
@@ -846,7 +846,7 @@
"components.Settings.SettingsJobsCache.plex-full-sync": "Plex komplette Bibliothek Synchronisierung",
"components.Settings.SettingsJobsCache.download-sync-reset": "Download Synchronisierung Zurücksetzung",
"components.Settings.SettingsJobsCache.download-sync": "Download Synchronisierung",
"i18n.loading": "Lade …",
"i18n.loading": "Lade…",
"components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "Du musst eine gültige Telegram Chat-ID angeben",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "<TelegramBotLink>Starte einen Chat</TelegramBotLink>, füge <GetIdBotLink>@get_id_bot</GetIdBotLink> hinzu, und führe den Befehl <code>/my_id</code> aus",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTip": "Füge <GetIdBotLink>@get_id_bot</GetIdBotLink> zum Chat hinzu",
@@ -858,12 +858,12 @@
"components.Settings.SettingsJobsCache.sonarr-sync": "Sonarr Synchronisierung",
"components.Settings.SettingsJobsCache.radarr-sync": "Radarr Synchronisierung",
"components.Settings.Notifications.botUsername": "Bot Benutzername",
"components.Discover.DiscoverTvGenre.genreSeries": "{genre}-Serien",
"components.Discover.DiscoverStudio.studioMovies": "{studio}-Filme",
"components.Discover.DiscoverNetwork.networkSeries": "{network}-Serien",
"components.Discover.DiscoverMovieGenre.genreMovies": "{genre}-Filme",
"components.Discover.DiscoverTvGenre.genreSeries": "{genre} Serien",
"components.Discover.DiscoverStudio.studioMovies": "{studio} Filme",
"components.Discover.DiscoverNetwork.networkSeries": "{network} Serien",
"components.Discover.DiscoverMovieGenre.genreMovies": "{genre} Filme",
"components.Setup.scanbackground": "Das Scannen läuft im Hintergrund. Du kannst in der Zwischenzeit das Setup fortsetzen.",
"components.Settings.scanning": "Scannen …",
"components.Settings.scanning": "Scannen…",
"components.Settings.scan": "Scan der Plex Bibliothek",
"components.Settings.SettingsJobsCache.sonarr-scan": "Sonarr Scan",
"components.Settings.SettingsJobsCache.radarr-scan": "Radarr Scan",
@@ -879,19 +879,5 @@
"components.RequestList.RequestItem.all": "Alle",
"components.RequestCard.status": "Status",
"components.Discover.StudioSlider.studios": "Filmstudio",
"components.Discover.NetworkSlider.networks": "Streaming-Anbieter",
"components.Discover.DiscoverTvLanguage.languageSeries": "Serien auf {language}",
"components.Discover.DiscoverMovieLanguage.languageMovies": "Filme auf {language}",
"components.UserProfile.ProfileHeader.requests": "{requestCount} {requestCount, plural, one {Anfrage} other {Anfragen}}",
"components.Settings.SettingsUsers.localLogin": "Lokale Benutzeranmeldung aktivieren",
"components.Settings.SettingsUsers.defaultPermissions": "Standardbenutzerberechtigungen",
"components.UserProfile.ProfileHeader.userid": "Benutzer-ID: {userid}",
"components.UserProfile.ProfileHeader.joindate": "Mitglied seit dem {joindate}",
"components.Settings.menuUsers": "Benutzer",
"components.Settings.SettingsUsers.userSettingsDescription": "Globale und Standardbenutzereinstellungen konfigurieren.",
"components.Settings.SettingsUsers.userSettings": "Benutzer",
"components.Settings.SettingsUsers.toastSettingsSuccess": "Einstellungen erfolgreich gespeichert!",
"components.Settings.SettingsUsers.toastSettingsFailure": "Beim Speichern der Einstellungen ist ein Fehler aufgetreten.",
"components.Settings.SettingsUsers.saving": "Speichern …",
"components.Settings.SettingsUsers.save": "Änderungen speichern"
"components.Discover.NetworkSlider.networks": "Streaming Anbieter"
}

View File

@@ -2,7 +2,7 @@
"components.AppDataWarning.dockerVolumeMissing": "Docker Volume Mount Missing",
"components.AppDataWarning.dockerVolumeMissingDescription": "The <code>{appDataPath}</code> volume mount was not configured properly. All data will be cleared when the container is stopped or restarted.",
"components.CollectionDetails.movies": "Movies",
"components.CollectionDetails.numberofmovies": "{count} Movies",
"components.CollectionDetails.numberofmovies": "Number of Movies: {count}",
"components.CollectionDetails.overview": "Overview",
"components.CollectionDetails.overviewunavailable": "Overview unavailable.",
"components.CollectionDetails.request": "Request",
@@ -141,9 +141,9 @@
"components.PermissionEdit.viewrequestsDescription": "Grants permission to view other users' requests.",
"components.PermissionEdit.vote": "Vote",
"components.PermissionEdit.voteDescription": "Grants permission to vote on requests (voting not yet implemented).",
"components.PersonDetails.appearsin": "Appearances",
"components.PersonDetails.appearsin": "Appears in",
"components.PersonDetails.ascharacter": "as {character}",
"components.PersonDetails.crewmember": "Crew",
"components.PersonDetails.crewmember": "Crew Member",
"components.PersonDetails.nobiography": "No biography available.",
"components.PlexLoginButton.loading": "Loading…",
"components.PlexLoginButton.signingin": "Signing in…",
@@ -197,11 +197,12 @@
"components.RequestList.sortModified": "Last Modified",
"components.RequestModal.AdvancedRequester.advancedoptions": "Advanced Options",
"components.RequestModal.AdvancedRequester.animenote": "* This series is an anime.",
"components.RequestModal.AdvancedRequester.default": "{name} (Default)",
"components.RequestModal.AdvancedRequester.default": "(Default)",
"components.RequestModal.AdvancedRequester.destinationserver": "Destination Server",
"components.RequestModal.AdvancedRequester.folder": "{path} ({space})",
"components.RequestModal.AdvancedRequester.languageprofile": "Language Profile",
"components.RequestModal.AdvancedRequester.loading": "Loading…",
"components.RequestModal.AdvancedRequester.loadingfolders": "Loading folders…",
"components.RequestModal.AdvancedRequester.loadinglanguages": "Loading languages…",
"components.RequestModal.AdvancedRequester.loadingprofiles": "Loading profiles…",
"components.RequestModal.AdvancedRequester.qualityprofile": "Quality Profile",
"components.RequestModal.AdvancedRequester.requestas": "Request As",
"components.RequestModal.AdvancedRequester.rootfolder": "Root Folder",
@@ -327,10 +328,6 @@
"components.Settings.Notifications.emailsettingssaved": "Email notification settings saved successfully!",
"components.Settings.Notifications.enableSsl": "Enable SSL",
"components.Settings.Notifications.notificationtypes": "Notification Types",
"components.Settings.Notifications.pgpPassword": "<PgpLink>PGP</PgpLink> Password",
"components.Settings.Notifications.pgpPasswordTip": "Sign encrypted email messages (PGP private key is also required)",
"components.Settings.Notifications.pgpPrivateKey": "<PgpLink>PGP</PgpLink> Private Key",
"components.Settings.Notifications.pgpPrivateKeyTip": "Sign encrypted email messages (PGP password is also required)",
"components.Settings.Notifications.save": "Save Changes",
"components.Settings.Notifications.saving": "Saving…",
"components.Settings.Notifications.sendSilently": "Send Silently",
@@ -346,7 +343,7 @@
"components.Settings.Notifications.test": "Test",
"components.Settings.Notifications.testsent": "Test notification sent!",
"components.Settings.Notifications.validationBotAPIRequired": "You must provide a bot authentication token",
"components.Settings.Notifications.validationChatIdRequired": "You must provide a valid chat ID",
"components.Settings.Notifications.validationChatIdRequired": "You must provide a chat ID",
"components.Settings.Notifications.validationEmail": "You must provide a valid email address",
"components.Settings.Notifications.validationSmtpHostRequired": "You must provide an SMTP host",
"components.Settings.Notifications.validationSmtpPortRequired": "You must provide an SMTP port",
@@ -632,8 +629,6 @@
"components.TvDetails.cast": "Cast",
"components.TvDetails.decline": "Decline",
"components.TvDetails.downloadstatus": "Download Status",
"components.TvDetails.episodeRuntime": "Episode Runtime",
"components.TvDetails.episodeRuntimeMinutes": "{runtime} minutes",
"components.TvDetails.firstAirDate": "First Air Date",
"components.TvDetails.manageModalClearMedia": "Clear All Media Data",
"components.TvDetails.manageModalClearMediaWarning": "* This will irreversibly remove all data for this TV series, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.",
@@ -655,7 +650,7 @@
"components.TvDetails.recommendations": "Recommendations",
"components.TvDetails.recommendationssubtext": "If you liked {title}, you might also like…",
"components.TvDetails.seasons": "{seasonCount, plural, one {# Season} other {# Seasons}}",
"components.TvDetails.showtype": "Series Type",
"components.TvDetails.showtype": "Show Type",
"components.TvDetails.similar": "Similar Series",
"components.TvDetails.similarsubtext": "Other series similar to {title}",
"components.TvDetails.status": "Status",
@@ -676,7 +671,7 @@
"components.UserList.deleteconfirm": "Are you sure you want to delete this user? All existing request data from this user will be removed.",
"components.UserList.deleteuser": "Delete User",
"components.UserList.edit": "Edit",
"components.UserList.edituser": "Edit User Permissions",
"components.UserList.edituser": "Edit User",
"components.UserList.email": "Email Address",
"components.UserList.importedfromplex": "{userCount, plural, =0 {No new users} one {# new user} other {# new users}} imported from Plex",
"components.UserList.importfromplex": "Import Users from Plex",
@@ -688,6 +683,7 @@
"components.UserList.password": "Password",
"components.UserList.passwordinfo": "Password Information",
"components.UserList.passwordinfodescription": "Email notifications need to be configured and enabled in order to automatically generate passwords.",
"components.UserList.permissions": "Permissions",
"components.UserList.plexuser": "Plex User",
"components.UserList.previous": "Previous",
"components.UserList.resultsperpage": "Display {pageSize} results per page",
@@ -740,8 +736,6 @@
"components.UserProfile.UserSettings.UserNotificationSettings.enableNotifications": "Enable Notifications",
"components.UserProfile.UserSettings.UserNotificationSettings.localuser": "Local User",
"components.UserProfile.UserSettings.UserNotificationSettings.notificationsettings": "Notification Settings",
"components.UserProfile.UserSettings.UserNotificationSettings.pgpKey": "<PgpLink>PGP</PgpLink> Public Key",
"components.UserProfile.UserSettings.UserNotificationSettings.pgpKeyTip": "Encrypt email messages",
"components.UserProfile.UserSettings.UserNotificationSettings.plexuser": "Plex User",
"components.UserProfile.UserSettings.UserNotificationSettings.save": "Save Changes",
"components.UserProfile.UserSettings.UserNotificationSettings.saving": "Saving…",
@@ -779,16 +773,11 @@
"components.UserProfile.UserSettings.UserPermissions.saving": "Saving…",
"components.UserProfile.UserSettings.UserPermissions.toastSettingsFailure": "Something went wrong while saving settings.",
"components.UserProfile.UserSettings.UserPermissions.toastSettingsSuccess": "Settings successfully saved!",
"components.UserProfile.UserSettings.UserPermissions.unauthorized": "Unauthorized",
"components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "You cannot modify your own permissions.",
"components.UserProfile.UserSettings.menuChangePass": "Password",
"components.UserProfile.UserSettings.menuGeneralSettings": "General Settings",
"components.UserProfile.UserSettings.menuNotifications": "Notifications",
"components.UserProfile.UserSettings.menuPermissions": "Permissions",
"components.UserProfile.UserSettings.settings": "User Settings",
"components.UserProfile.UserSettings.unauthorized": "Unauthorized",
"components.UserProfile.UserSettings.unauthorizedDescription": "You do not have permission to modify this user's settings.",
"components.UserProfile.norequests": "No Requests",
"components.UserProfile.recentrequests": "Recent Requests",
"i18n.advanced": "Advanced",
"i18n.approve": "Approve",

View File

@@ -183,7 +183,7 @@
"components.Settings.SonarrModal.toastRadarrTestSuccess": "¡Conexión con Sonarr establecida!",
"components.Settings.menuLogs": "Registro",
"pages.somethingWentWrong": "{statusCode} Algo salió mal",
"pages.serviceUnavailable": "{statusCode}: Servicio no disponible",
"pages.serviceUnavailable": "{statusCode}: Servicio no Disponible",
"pages.returnHome": "Volver al Inicio",
"pages.pageNotFound": "404  Página no encontrada",
"pages.oops": "Ups",
@@ -413,7 +413,7 @@
"components.StatusChacker.newversionavailable": "Nueva versión disponible",
"components.StatusChacker.newversionDescription": "Hay una actualización disponible. Haga clic en el botón de abajo para volver a cargar la aplicación.",
"components.Settings.SettingsAbout.documentation": "Documentación",
"components.Settings.Notifications.validationChatIdRequired": "Debe proporcionar una ID de chat",
"components.Settings.Notifications.validationChatIdRequired": "Debe proporcionar una ID de chat.",
"components.Settings.Notifications.validationBotAPIRequired": "Debe proporcionar una clave de API de bot.",
"components.Settings.Notifications.telegramsettingssaved": "¡Se han guardado los ajustes de notificación de Telegram!",
"components.Settings.Notifications.telegramsettingsfailed": "La configuración de notificaciones de Telegram no se pudo guardar.",
@@ -428,7 +428,7 @@
"components.NotificationTypeSelector.mediafailedDescription": "Envía una notificación cuando los medios no se agregan a los servicios (Radarr / Sonarr). Para ciertos agentes, esto solo enviará la notificación a los administradores o usuarios con el permiso \"Administrar solicitudes\".",
"components.NotificationTypeSelector.mediafailed": "Contenido Fallido",
"components.NotificationTypeSelector.mediaavailableDescription": "Envía una notificación cuando los medios están disponibles.",
"components.NotificationTypeSelector.mediaavailable": "Contenido Disponible",
"components.NotificationTypeSelector.mediaavailable": "Contenido disponible",
"components.NotificationTypeSelector.mediaapprovedDescription": "Envía una notificación cuando los medios son aprobados.",
"components.NotificationTypeSelector.mediaapproved": "Contenido Aprobado",
"i18n.request": "Solicitar",
@@ -507,7 +507,7 @@
"components.RequestModal.AdvancedRequester.loadingprofiles": "Cargando perfiles…",
"components.RequestModal.AdvancedRequester.loadingfolders": "Cargando carpetas…",
"components.RequestModal.AdvancedRequester.destinationserver": "Servidor de destino",
"components.RequestModal.AdvancedRequester.default": "{name} (Predeterminado)",
"components.RequestModal.AdvancedRequester.default": "(Predeterminado)",
"components.RequestModal.AdvancedRequester.animenote": "* Esta serie es un anime.",
"components.RequestModal.AdvancedRequester.advancedoptions": "Opciones avanzadas",
"components.RequestButton.viewrequest4k": "Ver Petición 4K",
@@ -554,16 +554,5 @@
"components.PermissionEdit.request": "Solicitar",
"components.PermissionEdit.admin": "Administrador",
"components.Discover.discover": "Descubrir",
"components.Common.ListView.noresults": "Sin resultados.",
"components.Settings.settings": "Ajustes",
"components.Layout.UserDropdown.settings": "Ajustes",
"components.Layout.UserDropdown.myprofile": "Perfil",
"components.Discover.DiscoverTvLanguage.languageSeries": "{language} Series",
"components.Discover.DiscoverTvGenre.genreSeries": "{genre} Series",
"components.Discover.DiscoverStudio.studioMovies": "{studio} Películas",
"components.Discover.DiscoverNetwork.networkSeries": "{network} Series",
"components.Discover.DiscoverMovieLanguage.languageMovies": "{language} Películas",
"components.Discover.DiscoverMovieGenre.genreMovies": "{genre} Películas",
"components.CollectionDetails.request4k": "Solicitar 4K",
"i18n.loading": "Cargando…"
"components.Common.ListView.noresults": "Sin resultados."
}

View File

@@ -408,14 +408,14 @@
"components.Settings.Notifications.NotificationsSlack.save": "Enregistrer les changements",
"components.Settings.Notifications.NotificationsSlack.agentenabled": "Activer l'agent",
"components.RequestList.RequestItem.failedretry": "Une erreur s'est produite lors du renvoi de la demande d'ajout.",
"components.Settings.Notifications.validationChatIdRequired": "Vous devez fournir un identifiant de discussion valide",
"components.Settings.Notifications.validationChatIdRequired": "Vous devez fournir un identifiant de discussion",
"components.Settings.Notifications.botAPI": "Jeton d'authentification du bot",
"components.Settings.Notifications.validationBotAPIRequired": "Vous devez fournir la clé d'authentification du bot",
"components.Settings.Notifications.telegramsettingssaved": "Paramètres de notification Telegram enregistrés avec succès !",
"components.Settings.Notifications.telegramsettingsfailed": "Les paramètres de notification Telegram n'ont pas pu être enregistrés.",
"components.Settings.Notifications.senderName": "Nom de l'expéditeur",
"components.Settings.Notifications.chatId": "ID discussion",
"components.Settings.Notifications.settinguptelegramDescription": "Pour configurer les notifications Telegram, vous aurez besoin de <CreateBotLink>créer un bot</CreateBotLink> et obtenir la clé API du bot. De plus, vous aurez besoin de l'identifiant de conversion pour la conversation à laquelle vous souhaitez envoyer des notifications. Vous pouvez le trouver en ajoutant <GetIdBotLink>@get_id_bot</GetIdBotLink> à la conversation -de groupe- et en exécutant la commande <code>/my_id</code>.",
"components.Settings.Notifications.settinguptelegramDescription": "Pour configurer les notifications Telegram, vous aurez besoin de <CreateBotLink>créer un bot</CreateBotLink> et obtenir la clé API du bot. De plus, vous aurez besoin de l'identifiant de conversion pour la conversation à laquelle vous souhaitez envoyer des notifications. Vous pouvez le récupérer en ajoutant <GetIdBotLink>@get_id_bot</GetIdBotLink> à la conversation -de groupe-.",
"components.Settings.Notifications.settinguptelegram": "Configuration des notifications Telegram",
"components.StatusChacker.reloadOverseerr": "Recharger Overseerr",
"components.StatusChacker.newversionavailable": "Une nouvelle version est disponible",
@@ -425,11 +425,11 @@
"components.Settings.Notifications.NotificationsSlack.notificationtypes": "Types de notification",
"components.NotificationTypeSelector.mediarequestedDescription": "Envoie une notification quand un média est demandé et nécessite une validation.",
"components.NotificationTypeSelector.mediarequested": "Média demandé",
"components.NotificationTypeSelector.mediafailedDescription": "Envoie une notification lorsqu'un média demandé n'a pas pu être ajouté sur Radarr /Sonarr.",
"components.NotificationTypeSelector.mediafailedDescription": "Envoie une notification quand l'ajout d'un média sur Radarr /Sonarr a échoué.",
"components.NotificationTypeSelector.mediafailed": "Échec dajout du média",
"components.NotificationTypeSelector.mediaavailableDescription": "Envoie une notification quand le média demandé devient disponible.",
"components.NotificationTypeSelector.mediaavailableDescription": "Envoie une notification quand le média devient disponible.",
"components.NotificationTypeSelector.mediaavailable": "Média disponible",
"components.NotificationTypeSelector.mediaapprovedDescription": "Envoie une notification quand le média demandé est validé manuellement.",
"components.NotificationTypeSelector.mediaapprovedDescription": "Envoie une notification quand le média est validé. Par défaut, les demandes automatiquement validées ne déclenchent pas l'envoi de notification.",
"components.NotificationTypeSelector.mediaapproved": "Média validé",
"i18n.request": "Demander",
"components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "Vous devez fournir un jeton utilisateur valide",
@@ -531,7 +531,7 @@
"components.RequestModal.AdvancedRequester.loadingprofiles": "Chargement des profils…",
"components.RequestModal.AdvancedRequester.loadingfolders": "Chargement des dossiers…",
"components.RequestModal.AdvancedRequester.destinationserver": "Serveur de destination",
"components.RequestModal.AdvancedRequester.default": "{name} (Défaut)",
"components.RequestModal.AdvancedRequester.default": "(Défaut)",
"components.RequestModal.AdvancedRequester.animenote": "* Cette série est un animé.",
"components.RequestModal.AdvancedRequester.advancedoptions": "Options avancées",
"components.RequestBlock.requestoverrides": "Contournements de demande",
@@ -539,7 +539,7 @@
"components.RequestBlock.rootfolder": "Dossier racine",
"components.RequestBlock.profilechanged": "Profil qualité",
"components.NotificationTypeSelector.mediadeclined": "Média refusé",
"components.NotificationTypeSelector.mediadeclinedDescription": "Envoie une notification lorsqu'un média demandé est refusé.",
"components.NotificationTypeSelector.mediadeclinedDescription": "Envoie une notification lorsqu'une demande est refusée.",
"i18n.experimental": "Expérimentale",
"components.Settings.hideAvailable": "Masquer les médias disponibles",
"components.RequestModal.requesterror": "Il y a eu un problème lors de la demande d'ajout.",
@@ -740,7 +740,7 @@
"components.UserProfile.UserSettings.UserNotificationSettings.discordId": "Identifiant Discord",
"components.UserProfile.UserSettings.UserNotificationSettings.localuser": "Utilisateur local",
"components.UserProfile.UserSettings.UserNotificationSettings.saving": "Enregistrement…",
"components.UserProfile.UserSettings.UserNotificationSettings.save": "Enregistrer les changements",
"components.UserProfile.UserSettings.UserNotificationSettings.save": "Enregsitrer les changements",
"components.UserProfile.UserSettings.UserNotificationSettings.plexuser": "Utilisateur Plex",
"components.UserProfile.UserSettings.UserNotificationSettings.notificationsettings": "Paramètres de notification",
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordset": "Aucun mot de passe défini",
@@ -800,7 +800,7 @@
"components.UserProfile.UserSettings.UserGeneralSettings.localuser": "Utilisateur local",
"components.UserProfile.UserSettings.UserGeneralSettings.generalsettings": "Paramètres généraux",
"components.UserProfile.UserSettings.UserGeneralSettings.displayName": "Nom affiché",
"components.UserProfile.ProfileHeader.settings": "Modifier les paramètres",
"components.UserProfile.ProfileHeader.settings": "Éditer les paramètres",
"components.UserProfile.ProfileHeader.profile": "Afficher le profil",
"components.UserList.userfail": "Un problème est survenu pendant l'enregistrement des paramètres de l'utilisateur.",
"components.UserList.showingresults": "Affiche de <strong>{from}</strong> à <strong>{to}</strong> sur <strong>{total}</strong> résultats",
@@ -809,7 +809,7 @@
"components.UserList.resultsperpage": "Affiche {pageSize} résultats par page",
"components.UserList.previous": "Précédent",
"components.UserList.permissions": "Permissions",
"components.UserList.edituser": "Modifier l'utilisateur",
"components.UserList.edituser": "Éditer l'utilisateur",
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "Paramètres de notification Pushbullet enregistrés avec succès !",
"components.CollectionDetails.requestswillbecreated4k": "Des demandes en 4K seront créés pour les titres suivants :",
"components.UserList.next": "Suivant",
@@ -824,7 +824,7 @@
"components.Discover.upcomingtv": "Séries à venir",
"components.Settings.originallanguage": "Langue à découvrir",
"components.RegionSelector.regionDefault": "Toutes les régions",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "Les notifications par e-mail « <strong>Média demandé</strong> », « <strong>Média validé automatiquement</strong> » et « <strong>Échec dajout du média</strong> » sont envoyées à tous les utilisateurs bénéficiant de la permission « <strong>Gérer les demandes</strong> ».",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "Les notifications « Média demandé » et « Échec dajout du média » seront exclusivement envoyées aux utilisateurs bénéficiant de l'autorisation « Gérer les demandes ».",
"components.Settings.Notifications.emailNotificationTypesAlert": "Destinataires des notifications par e-mail",
"components.Settings.webhook": "Webhook",
"components.Settings.email": "E-mail",
@@ -860,12 +860,12 @@
"components.TvDetails.seasons": "{seasonCount, plural, one {# Saison} other {# Saisons}}",
"components.UserProfile.UserSettings.UserNotificationSettings.sendSilentlyDescription": "Envoyer des notifications sans son",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "<TelegramBotLink>Démarre une discussion</TelegramBotLink>, ajoute <GetIdBotLink>@get_id_bot</GetIdBotLink>, et utilise la commande <code>/my_id</code>",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTip": "Ajoute <GetIdBotLink>@get_id_bot</GetIdBotLink> à la discussion",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatId": "ID de discussion Telegram",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTip": "Ajoute <GetIdBotLink>@get_id_bot</GetIdBotLink> au chat",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatId": "ID de chat Telegram",
"components.UserProfile.UserSettings.UserNotificationSettings.sendSilently": "Envoie les messages Telegram silencieusement",
"components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "Vous devez fournir un identifiant de discussion Telegram valide",
"components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "Vous devez fournir un ID de chat Telegram valide",
"components.Settings.Notifications.botUsername": "Pseudonyme du Bot",
"components.Discover.NetworkSlider.networks": "Réseaux",
"components.Discover.NetworkSlider.networks": "Networks",
"components.RequestList.RequestItem.modified": "Modifiée",
"components.RequestList.RequestItem.status": "Statut",
"components.RequestList.RequestItem.requested": "Demandé",
@@ -873,7 +873,7 @@
"components.RequestList.RequestItem.all": "Toutes",
"components.RequestCard.status": "Statut",
"components.Discover.StudioSlider.studios": "Studios",
"components.Discover.DiscoverTvLanguage.languageSeries": "Séries en {language}",
"components.Discover.DiscoverTvLanguage.languageSeries": "Séries {language}",
"components.Discover.DiscoverMovieLanguage.languageMovies": "Films {language}",
"components.Setup.scanbackground": "Le scan s'effectue en arrière-plan. Vous pouvez donc continuer le processus de configuration pendant ce temps.",
"components.Settings.scanning": "Scan en cours…",
@@ -884,24 +884,5 @@
"components.Settings.SettingsJobsCache.plex-full-scan": "Scan complet des bibliothèques Plex",
"components.Settings.Notifications.validationUrl": "Vous devez fournir un URL valide",
"components.Settings.Notifications.botAvatarUrl": "L'URL de l'avatar de votre Bot",
"components.RequestList.RequestItem.areyousure": "Êtes-vous sûr ?",
"components.Settings.SettingsUsers.userSettingsDescription": "Configurer les paramètres généraux et par défaut de l'utilisateur.",
"components.Settings.SettingsUsers.toastSettingsFailure": "Un problème est survenu pendant la sauvegarde des paramètres.",
"components.Settings.SettingsUsers.localLogin": "Activer la connexion des utilisateurs locaux",
"components.Settings.SettingsUsers.defaultPermissions": "Permissions par défaut de l'utilisateur",
"components.UserProfile.ProfileHeader.userid": "ID utilisateur : {userid}",
"components.UserProfile.ProfileHeader.requests": "{requestCount} {requestCount, plural, one {Demande} other {Demandes}}",
"components.UserProfile.ProfileHeader.joindate": "Membre depuis le {joindate}",
"components.Settings.menuUsers": "Utilisateurs",
"components.Settings.SettingsUsers.userSettings": "Utilisateurs",
"components.Settings.SettingsUsers.toastSettingsSuccess": "Les paramètres ont été sauvegardés avec succès !",
"components.Settings.SettingsUsers.saving": "Sauvegarde en cours…",
"components.Settings.SettingsUsers.save": "Sauvegarder les modifications",
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "Les notifications par e-mail <strong>Média validé</strong>, <strong>Média refusé</strong> et <strong>Média disponible</strong> sont envoyées à l'utilisateur ayant fait la demande.",
"components.NotificationTypeSelector.mediaAutoApproved": "Média validé automatiquement",
"components.NotificationTypeSelector.mediaAutoApprovedDescription": "Envoie une notification quand la demande d'un média est validé automatiquement.",
"components.UserProfile.UserSettings.unauthorizedDescription": "Vous n'êtes pas autorisé à modifier les paramètres de cet utilisateur.",
"components.UserProfile.UserSettings.unauthorized": "Non autorisé",
"components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Vous ne pouvez pas modifier vos propres permissions.",
"components.UserProfile.UserSettings.UserPermissions.unauthorized": "Non autorisé"
"components.RequestList.RequestItem.areyousure": "Êtes-vous sûr ?"
}

View File

@@ -1,5 +1,5 @@
{
"components.RequestModal.AdvancedRequester.default": "{name} (Alapértelmezett)",
"components.RequestModal.AdvancedRequester.default": "(Alapértelmezett)",
"components.RequestModal.AdvancedRequester.animenote": "* Ez a sorozat egy anime.",
"components.RequestModal.AdvancedRequester.advancedoptions": "További beállítások",
"components.RequestList.status": "Állapot",

View File

@@ -8,8 +8,8 @@
"components.Discover.discovermovies": "Film popolari",
"components.UserEdit.email": "Indirizzo e-mail",
"components.Settings.Notifications.validationFromRequired": "È necessario fornire un indirizzo mittente di posta elettronica.",
"components.Settings.Notifications.emailsettingssaved": "Impostazioni delle notifiche via posta elettronica salvate con successo!",
"components.Settings.Notifications.emailsettingsfailed": "Impossibile salvare le impostazioni delle notifiche via posta elettronica.",
"components.Settings.Notifications.emailsettingssaved": "Impostazioni delle notifiche email salvate con successo!",
"components.Settings.Notifications.emailsettingsfailed": "Impossibile salvare le impostazioni delle notifiche email.",
"components.Settings.Notifications.emailsender": "Indirizzo del mittente",
"components.Settings.SonarrModal.testing": "Test in corso…",
"components.Settings.RadarrModal.testing": "Test in corso…",
@@ -413,7 +413,7 @@
"components.Settings.Notifications.telegramsettingssaved": "Impostazioni di Telegram salvate con successo!",
"components.Settings.Notifications.telegramsettingsfailed": "Impossibile salvare le impostazioni di Telegram.",
"components.Settings.Notifications.senderName": "Nome del mittente",
"components.Settings.Notifications.settinguptelegramDescription": "Per configurare le notifiche di Telegram, dovrai <CreateBotLink>creare un bot</CreateBotLink> e ottenerne la chiave API. Inoltre, avrai bisogno dell'ID della chat a cui volete inviare le notifiche. Puoi trovarlo aggiungendo <GetIdBotLink>@get_id_bot</GetIdBotLink> alla chat ed inserendo il comando <code>/my_id</code>.",
"components.Settings.Notifications.settinguptelegramDescription": "Per configurare le notifiche di Telegram, dovrai <CreateBotLink>creare un bot</CreateBotLink> e ottenere la chiave API del bot. Inoltre, avrai bisogno dell'ID della chat a cui vuoi inviare le notifiche. Puoi ottenerlo aggiungendo <GetIdBotLink>@get_id_bot</GetIdBotLink> alla chat.",
"components.Settings.Notifications.settinguptelegram": "Configurazione delle notifiche di Telegram",
"components.Settings.Notifications.chatId": "ID chat",
"components.Settings.Notifications.botAPI": "Token di autenticazione bot",
@@ -427,8 +427,8 @@
"components.NotificationTypeSelector.mediarequested": "Media Richiesto",
"components.NotificationTypeSelector.mediafailedDescription": "Invia una notifica quando il media non viene aggiunto a Radarr o Sonarr.",
"components.NotificationTypeSelector.mediafailed": "Aggiunta media non riuscita",
"components.NotificationTypeSelector.mediaavailableDescription": "Invia una notifica quando il media richiesto diventa disponibile.",
"components.NotificationTypeSelector.mediaapprovedDescription": "Invia una notifica quando i media richiesti sono approvati manualmente.",
"components.NotificationTypeSelector.mediaavailableDescription": "Invia una notifica quando il media diventa disponibile.",
"components.NotificationTypeSelector.mediaapprovedDescription": "Invia una notifica quando il media viene approvato. Per impostazione predefinita, le richieste approvate automaticamente non attiveranno le notifiche.",
"components.NotificationTypeSelector.mediaapproved": "Media approvato",
"components.NotificationTypeSelector.mediaavailable": "Media disponibile",
"i18n.request": "Richiedi",
@@ -472,7 +472,7 @@
"components.UserList.usercreatedfailed": "Qualcosa è andato storto nel creare l'utente.",
"components.UserList.validationpasswordminchars": "La password è troppo corta; deve avere un minimo di 8 caratteri",
"components.UserList.validationemailrequired": "Devi inserire un indirizzo e-mail valido.",
"components.UserList.passwordinfodescription": "Le notifiche via posta elettronica devono essere configurate e abilitate per generare automaticamente le password.",
"components.UserList.passwordinfodescription": "Le notifiche e-mail devono essere configurate e abilitate per generare automaticamente le password.",
"components.UserList.email": "Indirizzo e-mail",
"components.RequestButton.viewrequest4k": "Visualizza la richiesta 4K",
"components.RequestButton.viewrequest": "Visualizza la richiesta",
@@ -537,7 +537,7 @@
"components.RequestModal.AdvancedRequester.loadingprofiles": "Caricamento dei profili…",
"components.RequestModal.AdvancedRequester.loadingfolders": "Caricamento cartelle…",
"components.RequestModal.AdvancedRequester.destinationserver": "Server di destinazione",
"components.RequestModal.AdvancedRequester.default": "{name} (Standard)",
"components.RequestModal.AdvancedRequester.default": "(Standard)",
"components.RequestModal.AdvancedRequester.animenote": "* Questa serie è un anime.",
"components.RequestModal.AdvancedRequester.advancedoptions": "Opzioni avanzate",
"components.RequestButton.declinerequests": "Rifiuta {requestCount} {requestCount, plural, one {richiesta} other {richieste}}",
@@ -653,7 +653,7 @@
"components.ResetPassword.forgotpassword": "Reimposta la password",
"components.ResetPassword.emailresetlink": "Inviami un collegamento di recupero via e-mail",
"components.ResetPassword.email": "Indirizzo e-mail",
"components.ResetPassword.confirmpassword": "Conferma la password",
"components.ResetPassword.confirmpassword": "Conferma la Password",
"components.RequestModal.requesterror": "Qualcosa è andato storto durante l'invio della richiesta.",
"components.RequestModal.notvdbiddescription": "Aggiungi l'ID TVDB a TMDb e riprova più tardi, o seleziona la corrispondenza corretta qui sotto:",
"components.RequestModal.notvdbid": "Nessun ID TVDB è stato trovato per questa voce su TMDb.",
@@ -734,7 +734,7 @@
"components.PermissionEdit.autoapprove4kDescription": "Concede l'approvazione automatica per tutte le richieste 4K fatte da questo utente.",
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordsetDescription": "Questo account utente attualmente non dispone di una password specifica per {applicationTitle}. Configura una password di seguito per consentire a questo account di accedere come «utente locale».",
"components.Layout.UserDropdown.myprofile": "Profilo",
"components.UserProfile.UserSettings.UserNotificationSettings.save": "Salva le modifiche",
"components.UserProfile.UserSettings.UserNotificationSettings.save": "Salva Modifiche",
"components.UserProfile.UserSettings.UserNotificationSettings.plexuser": "Utente Plex",
"components.UserProfile.UserSettings.UserNotificationSettings.notificationsettings": "Impostazioni Notifiche",
"components.UserProfile.UserSettings.UserNotificationSettings.localuser": "Utente Locale",
@@ -745,12 +745,12 @@
"components.Settings.Notifications.NotificationsPushbullet.saving": "Salvataggio…",
"components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsFailure": "Qualcosa è andato storto nel salvare le impostazioni.",
"components.UserProfile.UserSettings.UserGeneralSettings.saving": "Salvataggio…",
"components.UserProfile.UserSettings.UserGeneralSettings.save": "Salva le modifiche",
"components.UserProfile.UserSettings.UserGeneralSettings.save": "Salva Modifiche",
"components.UserProfile.UserSettings.UserGeneralSettings.plexuser": "Utente Plex",
"components.UserProfile.UserSettings.UserGeneralSettings.localuser": "Utente locale",
"components.UserProfile.UserSettings.UserGeneralSettings.generalsettings": "Impostazioni generali",
"components.UserProfile.UserSettings.UserGeneralSettings.displayName": "Nome da mostrare",
"components.UserProfile.ProfileHeader.settings": "Modifica le impostazioni",
"components.UserProfile.ProfileHeader.settings": "Modifica impostazioni",
"components.UserProfile.ProfileHeader.profile": "Visualizza profilo",
"components.UserList.userfail": "Qualcosa è andato storto nel creare l'utente.",
"components.UserList.showingResults": "Risultati da <strong>{from}</strong> a <strong>{to}</strong> di <strong>{total}</strong>",
@@ -760,7 +760,7 @@
"components.UserList.previous": "Indietro",
"components.UserList.permissions": "Permessi",
"components.UserList.next": "Avanti",
"components.UserList.edituser": "Modifica l'utente",
"components.UserList.edituser": "Modifica utente",
"components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "È necessario fornire un token di accesso",
"components.Settings.Notifications.NotificationsPushbullet.testSent": "Notifica di prova inviata!",
"components.Settings.Notifications.NotificationsPushbullet.test": "Test",
@@ -783,7 +783,7 @@
"components.UserProfile.UserSettings.UserPermissions.toastSettingsSuccess": "Impostazioni salvate correttamente!",
"components.UserProfile.UserSettings.UserPermissions.toastSettingsFailure": "Qualcosa è andato storto nel salvare le impostazioni.",
"components.UserProfile.UserSettings.UserPermissions.saving": "Salvataggio…",
"components.UserProfile.UserSettings.UserPermissions.save": "Salva le modifiche",
"components.UserProfile.UserSettings.UserPermissions.save": "Salva modifiche",
"components.UserProfile.UserSettings.UserPermissions.plexuser": "Utente Plex",
"components.UserProfile.UserSettings.UserPermissions.permissions": "Autorizzazioni",
"components.UserProfile.UserSettings.UserPermissions.localuser": "Utente locale",
@@ -796,12 +796,12 @@
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsSuccess": "Password cambiata!",
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailure": "Qualcosa è andato storto nel salvare la password. La password corrente è corretta?",
"components.UserProfile.UserSettings.UserPasswordChange.saving": "Salvataggio…",
"components.UserProfile.UserSettings.UserPasswordChange.save": "Salva le modifiche",
"components.UserProfile.UserSettings.UserPasswordChange.save": "Salva Modifiche",
"components.UserProfile.UserSettings.UserPasswordChange.password": "Password",
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordset": "Nessuna password impostata",
"components.UserProfile.UserSettings.UserPasswordChange.newpassword": "Nuova password",
"components.UserProfile.UserSettings.UserPasswordChange.currentpassword": "Password attuale",
"components.UserProfile.UserSettings.UserPasswordChange.confirmpassword": "Conferma la password",
"components.UserProfile.UserSettings.UserPasswordChange.newpassword": "Nuova Password",
"components.UserProfile.UserSettings.UserPasswordChange.currentpassword": "Password Attuale",
"components.UserProfile.UserSettings.UserPasswordChange.confirmpassword": "Conferma Password",
"components.UserProfile.UserSettings.UserNotificationSettings.validationDiscordId": "È necessario fornire un ID utente di Discord",
"components.UserProfile.UserSettings.UserNotificationSettings.toastSettingsSuccess": "Impostazioni salvate correttamente!",
"components.UserProfile.UserSettings.UserNotificationSettings.toastSettingsFailure": "Qualcosa è andato storto nel salvare le impostazioni.",
@@ -825,7 +825,7 @@
"components.Discover.upcomingtv": "Serie in uscita",
"components.UserProfile.UserSettings.UserGeneralSettings.originalLanguageDefault": "Tutte le lingue",
"components.Settings.originalLanguageDefault": "Tutte le lingue",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "Le notifiche email <strong>Media richiesti</strong>, <strong>Media approvati automaticamente</strong>, e <strong>Media falliti</strong> sono inviate a tutti gli utenti con l'autorizzazione <strong>Gestisci richieste</strong>.",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "Le notifiche «Media richiesto» e «Aggiunta media non riuscita» saranno inviate solo agli utenti con il permesso «Gestisci richieste».",
"components.UserProfile.UserSettings.UserGeneralSettings.languageServerDefault": "Predefinito ({language})",
"components.RegionSelector.regionServerDefault": "Predefinito ({region})",
"components.UserProfile.UserSettings.UserPasswordChange.nopermissionDescription": "Non hai il permesso di modificare la password di questo utente.",
@@ -842,7 +842,7 @@
"components.Discover.DiscoverMovieGenre.genreMovies": "Film di {genre}",
"components.Settings.SettingsJobsCache.download-sync-reset": "Reimposta sincronizzazione di scaricamento",
"i18n.loading": "Caricamento…",
"components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "Devi fornire un ID valido per la discussione di Telegram",
"components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "Devi fornire un ID valido per la chat di Telegram",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "<TelegramBotLink>Inizia una chat</TelegramBotLink>, aggiungi <GetIdBotLink>@get_id_bot</GetIdBotLink>, ed esegui il comando <code>/my_id</code>",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTip": "Aggiungi <GetIdBotLink>@get_id_bot</GetIdBotLink> alla chat",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatId": "ID chat di Telegram",
@@ -872,21 +872,6 @@
"components.RequestCard.status": "Stato",
"components.Discover.StudioSlider.studios": "Studi",
"components.Discover.NetworkSlider.networks": "Reti",
"components.Discover.DiscoverTvLanguage.languageSeries": "Serie in {language}",
"components.Discover.DiscoverMovieLanguage.languageMovies": "Film in {language}",
"components.UserProfile.ProfileHeader.requests": "{requestCount} {requestCount, plural, one {Richiesta} other {Richieste}}",
"components.UserProfile.ProfileHeader.userid": "ID utente: {userid}",
"components.UserProfile.ProfileHeader.joindate": "Iscritto/a dal {joindate}",
"components.Settings.menuUsers": "Utenti",
"components.Settings.SettingsUsers.userSettingsDescription": "Configura le impostazioni utente globali e predefinite.",
"components.Settings.SettingsUsers.userSettings": "Utenti",
"components.Settings.SettingsUsers.toastSettingsSuccess": "Impostazioni salvate con successo!",
"components.Settings.SettingsUsers.toastSettingsFailure": "Qualcosa è andato storto durante il salvataggio delle impostazioni.",
"components.Settings.SettingsUsers.saving": "Salvataggio…",
"components.Settings.SettingsUsers.save": "Salva le modifiche",
"components.Settings.SettingsUsers.localLogin": "Abilita l'accesso utente locale",
"components.Settings.SettingsUsers.defaultPermissions": "Autorizzazioni utente predefinite",
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "Le notifiche email <strong>Media approvato</strong>, <strong>Media rifiutato</strong>, e <strong>Media disponibile</strong> sono inviate all'utente che ha effettuato la richiesta.",
"components.NotificationTypeSelector.mediaAutoApprovedDescription": "Invia una notifica quando i media richiesti vengono approvati automaticamente.",
"components.NotificationTypeSelector.mediaAutoApproved": "Media approvati automaticamente"
"components.Discover.DiscoverTvLanguage.languageSeries": "Serie {language}",
"components.Discover.DiscoverMovieLanguage.languageMovies": "Film {language}"
}

View File

@@ -339,15 +339,15 @@
"components.Settings.SettingsAbout.Releases.currentversion": "Huidige versie",
"components.Settings.Notifications.testsent": "Testmelding verzonden!",
"components.Settings.Notifications.test": "Test",
"components.MovieDetails.studio": "{studioCount, plural, one {Studio} other {Studio's}}",
"components.MovieDetails.studio": "{studioCount, plural, one {studio} other {studio's}}",
"components.CollectionDetails.requesting": "Bezig met aanvragen…",
"components.CollectionDetails.overviewunavailable": "Overzicht niet beschikbaar.",
"components.CollectionDetails.overview": "Overzicht",
"components.CollectionDetails.numberofmovies": "Aantal films: {count}",
"components.CollectionDetails.movies": "Films",
"components.NotificationTypeSelector.mediafailed": "Media mislukt",
"components.NotificationTypeSelector.mediaapprovedDescription": "Stuurt een melding wanneer aangevraagde media handmatig is goedgekeurd.",
"components.NotificationTypeSelector.mediaavailableDescription": "Melding sturen wanneer aangevraagde media beschikbaar is.",
"components.NotificationTypeSelector.mediaapprovedDescription": "Een melding sturen wanneer media goedgekeurd is. Standaard worden geen meldingen verstuurd voor automatisch goedgekeurde verzoeken.",
"components.NotificationTypeSelector.mediaavailableDescription": "Melding sturen wanneer media beschikbaar is.",
"components.NotificationTypeSelector.mediaapproved": "Media goedgekeurd",
"components.MovieDetails.view": "Bekijken",
"components.CollectionDetails.request": "Aanvragen",
@@ -390,7 +390,7 @@
"components.Settings.SettingsAbout.Releases.viewchangelog": "Changelog bekijken",
"components.Settings.SettingsAbout.Releases.runningDevelopMessage": "De wijzigingen in je versie zijn hieronder niet beschikbaar. Bekijk de <GithubLink>GitHub repository</GithubLink> voor de laatste updates.",
"components.Settings.SettingsAbout.Releases.runningDevelop": "Je gebruikt een ontwikkelversie van Overseerr!",
"components.Settings.Notifications.validationChatIdRequired": "Je moet een geldige chat-ID opgeven",
"components.Settings.Notifications.validationChatIdRequired": "Je moet een chat-ID opgeven",
"components.Settings.Notifications.validationBotAPIRequired": "Je moet een bot-verificatietoken opgeven",
"components.Settings.Notifications.telegramsettingssaved": "Instellingen Telegrammeldingen met succes opgeslagen!",
"components.Settings.Notifications.telegramsettingsfailed": "De instellingen voor Telegrammeldingen konden niet opgeslagen worden.",
@@ -422,14 +422,14 @@
"components.UserList.importedfromplex": "{userCount, plural, =0 {Geen nieuwe gebruikers} one {# nieuwe gebruiker} other {# nieuwe gebruikers}} geïmporteerd vanuit Plex",
"components.Settings.SettingsAbout.Releases.versionChangelog": "Changelog",
"components.Settings.SettingsAbout.Releases.releases": "Versies",
"components.Settings.Notifications.settinguptelegramDescription": "Om Telegrammeldingen in te stellen, moet je <CreateBotLink>een bot aanmaken</CreateBotLink> en de API-sleutel van de bot gebruiken. Je hebt ook de Chat ID nodig van de chat waarin je meldingen wilt sturen. Dit kun je vinden door <GetIdBotLink>@get_id_bot</GetIdBotLink> aan de chat toe te voegen en het commando <code>/my_id</code> uit te voeren.",
"components.Settings.Notifications.settinguptelegramDescription": "Om Telegrammeldingen in te stellen, moet je <CreateBotLink>een bot aanmaken</CreateBotLink> en de API-sleutel van de bot gebruiken. Je hebt ook de Chat ID nodig van de chat waarin je meldingen wilt sturen. Dit kun je doen door <GetIdBotLink>@get_id_bot</GetIdBotLink> aan de chat toe te voegen.",
"components.Settings.Notifications.settinguptelegram": "Telegrammeldingen instellen",
"components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Instellingen voor Slack-meldingen met succes opgeslagen!",
"components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Instellingen voor Slack-meldingen konden niet opgeslagen worden.",
"components.Settings.Notifications.NotificationsSlack.settingupslackDescription": "Om Slack-meldingen in te stellen moet je een <WebhookLink>Incoming Webhook</WebhookLink> integratie gebruiken en de webhook-URL hieronder ingeven.",
"components.Settings.Notifications.NotificationsSlack.settingupslack": "Slack-meldingen instellen",
"components.NotificationTypeSelector.mediarequestedDescription": "Een melding sturen wanneer media is aangevraagd en goedkeuring vereist.",
"components.NotificationTypeSelector.mediafailedDescription": "Een melding sturen wanneer aangevraagde media niet toegevoegd kan worden aan Radarr of Sonarr.",
"components.NotificationTypeSelector.mediafailedDescription": "Een melding sturen wanneer media niet toegevoegd kan worden aan Radarr of Sonarr.",
"components.TvDetails.TvCrew.fullseriescrew": "Volledige crew van de serie",
"components.Settings.Notifications.NotificationsPushover.saving": "Bezig met opslaan…",
"components.Settings.Notifications.NotificationsPushover.save": "Wijzigingen opslaan",
@@ -530,7 +530,7 @@
"components.RequestModal.AdvancedRequester.loadingprofiles": "Profielen laden…",
"components.RequestModal.AdvancedRequester.loadingfolders": "Mappen laden…",
"components.RequestModal.AdvancedRequester.destinationserver": "Doelserver",
"components.RequestModal.AdvancedRequester.default": "{name} (Standaard)",
"components.RequestModal.AdvancedRequester.default": "(Standaard)",
"components.RequestModal.AdvancedRequester.animenote": "* Deze serie is anime.",
"components.RequestModal.AdvancedRequester.advancedoptions": "Geavanceerde opties",
"components.RequestBlock.server": "Doelserver",
@@ -825,7 +825,7 @@
"components.Settings.region": "Regio van Ontdekken",
"components.Settings.originallanguageTip": "Inhoud filteren op oorspronkelijke taal (alleen van toepassing op de categorieën \"Populair\" en \"Verwacht\")",
"components.Settings.originallanguage": "Taal van Ontdekken",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "E-mailmeldingen <strong>Media aangevraagd</strong>, <strong>Media automatisch goedgekeurd</strong> en <strong>Media mislukt</strong> worden verzonden naar alle gebruikers met de machtiging <strong>Verzoeken beheren</strong>.",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "Voor de meldingtypes \"Media aangevraagd\" en \"Media mislukt\" worden alleen meldingen verstuurd naar gebruikers met de machtiging \"Verzoeken beheren\".",
"components.Settings.email": "E-mail",
"components.Settings.Notifications.emailNotificationTypesAlert": "Ontvangers van e-mailmeldingen",
"components.RegionSelector.regionDefault": "Alle regios",
@@ -886,24 +886,5 @@
"components.Discover.StudioSlider.studios": "Studio's",
"components.Discover.NetworkSlider.networks": "Netwerken",
"components.Discover.DiscoverTvLanguage.languageSeries": "Series in het {language}",
"components.Discover.DiscoverMovieLanguage.languageMovies": "Films in het {language}",
"components.UserProfile.ProfileHeader.userid": "Gebruikers-ID: {userid}",
"components.UserProfile.ProfileHeader.requests": "{requestCount} {requestCount, plural, one {verzoek} other {verzoeken}}",
"components.UserProfile.ProfileHeader.joindate": "Lid geworden op {joindate}",
"components.Settings.menuUsers": "Gebruikers",
"components.Settings.SettingsUsers.userSettingsDescription": "Algemene en standaard gebruikersinstellingen configureren.",
"components.Settings.SettingsUsers.userSettings": "Gebruikers",
"components.Settings.SettingsUsers.toastSettingsSuccess": "Instellingen succesvol opgeslagen!",
"components.Settings.SettingsUsers.toastSettingsFailure": "Er ging iets mis bij het opslaan van de instellingen.",
"components.Settings.SettingsUsers.saving": "Bezig met opslaan…",
"components.Settings.SettingsUsers.save": "Wijzigingen opslaan",
"components.Settings.SettingsUsers.localLogin": "Aanmelden voor lokale gebruikers inschakelen",
"components.Settings.SettingsUsers.defaultPermissions": "Standaard gebruikersrechten",
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "E-mailmeldingen <strong>Media goedgekeurd</strong>, <strong>Media geweigerd</strong> and <strong>Media beschikbaar</strong> worden verstuurd naar de gebruiker die het verzoek heeft ingediend.",
"components.NotificationTypeSelector.mediaAutoApprovedDescription": "Stuurt een melding wanneer aangevraagde media automatisch wordt goedgekeurd.",
"components.NotificationTypeSelector.mediaAutoApproved": "Media automatisch goedgekeurd",
"components.UserProfile.UserSettings.unauthorizedDescription": "Je hebt geen toestemming om de instellingen van deze gebruiker te wijzigen.",
"components.UserProfile.UserSettings.unauthorized": "Onbevoegd",
"components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Je kan je eigen machtigingen niet wijzigen.",
"components.UserProfile.UserSettings.UserPermissions.unauthorized": "Onbevoegd"
"components.Discover.DiscoverMovieLanguage.languageMovies": "Films in het {language}"
}

View File

@@ -366,7 +366,7 @@
"components.RequestModal.requestseasons": "Solicitar {seasonCount} {seasonCount, plural, one {Temporada} other {Temporadas}}",
"components.TvDetails.viewfullcrew": "Ver Toda Equipe Técnica",
"components.TvDetails.TvCrew.fullseriescrew": "Equipe Técnica Completa da Série",
"components.PersonDetails.crewmember": "Membros",
"components.PersonDetails.crewmember": "Membro da Equipe Técnica",
"components.MovieDetails.viewfullcrew": "Ver Equipe Técnica Completa",
"components.MovieDetails.MovieCrew.fullcrew": "Equipe Técnica Completa",
"components.UserList.importfromplexerror": "Algo deu errado ao importar usuários do Plex.",
@@ -387,7 +387,7 @@
"components.CollectionDetails.request": "Solicitar",
"components.CollectionDetails.overviewunavailable": "Sinopse indisponível.",
"components.CollectionDetails.overview": "Sinopse",
"components.CollectionDetails.numberofmovies": "Filmes: {count}",
"components.CollectionDetails.numberofmovies": "Número de Filmes: {count}",
"components.CollectionDetails.movies": "Filmes",
"i18n.requested": "Solicitado",
"i18n.retry": "Tentar Novamente",
@@ -398,13 +398,13 @@
"components.UserEdit.autoapproveMovies": "Aprovar Filmes Automaticamente",
"components.TvDetails.watchtrailer": "Assisitir Trailer",
"components.TvDetails.firstAirDate": "Primeira Exibição",
"components.Settings.Notifications.validationChatIdRequired": "Você deve prover um ID de Chat válido",
"components.Settings.Notifications.validationChatIdRequired": "Você deve prover um ID de Chat",
"components.Settings.Notifications.validationBotAPIRequired": "Você deve prover uma chave de autenticação do Bot",
"components.Settings.Notifications.senderName": "Nome do Remetente",
"components.Settings.Notifications.telegramsettingssaved": "Configurações de notificação via Telegram salvas com sucesso!",
"components.Settings.Notifications.telegramsettingsfailed": "Falha ao salvar configurações de notificação via Telegram.",
"components.Settings.Notifications.ssldisabletip": "SSL deve ser desabilitado em conexões TLS padrão (porta 587)",
"components.Settings.Notifications.settinguptelegramDescription": "Para configurar notificações via Telegram, você precisará <CreateBotLink>criar um bot</CreateBotLink> e obter a chave de API do mesmo. Além disso, você irá precisar do ID de Chat de onde você deseja que o bot envie as notificações. Você pode obter o ID de Chat adicionando <GetIdBotLink>@get_id_bot</GetIdBotLink> ao chat ou grupo ao qual você deseja obter o ID e executar o comando <code>/my_id</code>.",
"components.Settings.Notifications.settinguptelegramDescription": "Para configurar notificações via Telegram, você precisará <CreateBotLink>criar um bot</CreateBotLink> e obter a chave de API do mesmo. Além disso, você irá precisar do ID de Chat de onde você deseja que o bot envie as notificações. Você pode obter o ID de Chat adicionando <GetIdBotLink>@get_id_bot</GetIdBotLink> ao chat ou grupo ao qual você deseja obter o ID.",
"components.Settings.Notifications.settinguptelegram": "Configurando Notificações Via Telegram",
"components.Settings.Notifications.chatId": "ID de Chat",
"components.Settings.Notifications.botAPI": "Token de Autenticação do Bot",
@@ -427,10 +427,10 @@
"components.NotificationTypeSelector.mediaavailable": "Mídia Disponível",
"components.NotificationTypeSelector.mediaapproved": "Mídia Aprovada",
"components.NotificationTypeSelector.mediarequested": "Mídia Solicitada",
"components.NotificationTypeSelector.mediafailedDescription": "Envia uma notificação quando houver falha ao adicionar título solicitado aos serviços Radarr ou Sonarr.",
"components.NotificationTypeSelector.mediafailedDescription": "Envia uma notificação quando houver falha ao adicionar título aos serviços Radarr ou Sonarr.",
"components.NotificationTypeSelector.mediafailed": "Solicitação Falhou",
"components.NotificationTypeSelector.mediaavailableDescription": "Envia uma notificação quando o título solicitado estiver disponível.",
"components.NotificationTypeSelector.mediaapprovedDescription": "Envia uma notificação quando uma solicitação de mídia é aprovada manualmente.",
"components.NotificationTypeSelector.mediaapprovedDescription": "Envia uma notificação quando uma solicitação é aprovada. Por padrão, não serão enviadas notificações de solicitações aprovadas automaticamente.",
"i18n.request": "Solicitar",
"components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "Você deve prover uma chave válida de acesso do usúario",
"components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "Você deve prover uma chave válida de acesso",
@@ -532,7 +532,7 @@
"components.Login.loggingin": "Autenticando…",
"components.Login.goback": "Voltar",
"components.Login.email": "Endereço de E-mail",
"components.NotificationTypeSelector.mediadeclinedDescription": "Envia uma notificação quando uma solicitação de mídia é recusada.",
"components.NotificationTypeSelector.mediadeclinedDescription": "Envia uma notificação quando uma solicitação é recusada.",
"components.NotificationTypeSelector.mediadeclined": "Mídia Recusada",
"components.MediaSlider.ShowMoreCard.seemore": "Ver Mais",
"components.RequestModal.requestedited": "Solicitação modificada.",
@@ -544,7 +544,7 @@
"components.RequestModal.AdvancedRequester.loadingprofiles": "Carregando perfis…",
"components.RequestModal.AdvancedRequester.loadingfolders": "Carregando pastas…",
"components.RequestModal.AdvancedRequester.destinationserver": "Servidor de Destino",
"components.RequestModal.AdvancedRequester.default": "{name} (Padrão)",
"components.RequestModal.AdvancedRequester.default": "(Padrão)",
"components.RequestModal.AdvancedRequester.animenote": "* Esta série é um anime.",
"components.RequestModal.AdvancedRequester.advancedoptions": "Opções Avançadas",
"components.RequestBlock.server": "Servidor de Destino",
@@ -809,7 +809,7 @@
"components.UserProfile.UserSettings.UserPasswordChange.validationNewPasswordLength": "A senha é muito curta; Ela deve ter no mínimo 8 caractéres",
"components.UserList.save": "Salvar Mudanças",
"components.UserList.permissions": "Permissões",
"components.UserList.edituser": "Editar Permissões de Usuário",
"components.UserList.edituser": "Editar Usuário",
"components.Settings.Notifications.NotificationsPushbullet.testSent": "Notificação de teste enviada!",
"components.Settings.Notifications.NotificationsPushbullet.test": "Testar",
"components.Settings.Notifications.NotificationsPushbullet.saving": "Salvando…",
@@ -841,7 +841,7 @@
"components.Discover.upcomingtv": "Séries Em Breve",
"components.UserProfile.UserSettings.UserGeneralSettings.regionTip": "Filtra conteúdo por região (se aplica apenas às categorias \"Popular\" e \"Em Breve\")",
"components.Settings.regionTip": "Filtra conteúdo por região (se aplica apenas às categorias \"Popular\" e \"Em Breve\")",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "Notificações de <strong>Mídia Solicitada</strong>, <strong>Mídia Aprovada Automaticamente</strong>, e <strong>Solicitação Falhou</strong>, serão enviadas para todos usuários com permissão de <strong>Gerenciar Solicitações</strong>.",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "Para notificações do tipo \"Mídia Solicitada\" e \"Solicitação Falhou\", as notificações serão enviadas apenas para usuários com permissão de \"Gerenciar Solicitações\".",
"components.UserProfile.UserSettings.UserGeneralSettings.originallanguageTip": "Filtra conteúdo pela língua original (se aplica apenas às categorias \"Popular\" e \"Em Breve\")",
"components.UserProfile.UserSettings.UserGeneralSettings.originalLanguageDefault": "Todos Idiomas",
"components.Settings.originallanguageTip": "Filtra conteúdo pela língua original (se aplica apenas às categorias \"Popular\" e \"Em Breve\")",
@@ -896,34 +896,5 @@
"components.Settings.SettingsJobsCache.sonarr-scan": "Escaneamento do Sonarr",
"components.Settings.SettingsJobsCache.radarr-scan": "Escanemento do Radarr",
"components.Settings.SettingsJobsCache.plex-recently-added-scan": "Recentemente Adicionado ao Plex",
"components.Settings.SettingsJobsCache.plex-full-scan": "Escaneamento de Todas Bibliotecas do Plex",
"components.UserProfile.norequests": "Nenhuma Solicitação",
"components.UserProfile.UserSettings.unauthorizedDescription": "Você não tem permissão para modificar as configurações desse usuários.",
"components.UserProfile.UserSettings.unauthorized": "Não Autorizado",
"components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Você não pode modificar suas próprias permissões.",
"components.UserProfile.UserSettings.UserPermissions.unauthorized": "Não Autorizado",
"components.UserProfile.UserSettings.UserNotificationSettings.pgpKeyTip": "Criptografa mensagens de e-mail",
"components.UserProfile.UserSettings.UserNotificationSettings.pgpKey": "Chave <PgpLink>PGP</PgpLink> Pública",
"components.UserProfile.ProfileHeader.userid": "ID de Usuário: {userid}",
"components.UserProfile.ProfileHeader.requests": "{requestCount} {requestCount, plural, one {Solicitação} other {Solicitações}}",
"components.UserProfile.ProfileHeader.joindate": "Entrou em {joindate}",
"components.Settings.menuUsers": "Usuários",
"components.Settings.SettingsUsers.userSettingsDescription": "Define configurações globais e padrões de usuário.",
"components.Settings.SettingsUsers.userSettings": "Usuários",
"components.Settings.SettingsUsers.toastSettingsSuccess": "Configurações salvas com sucesso!",
"components.Settings.SettingsUsers.toastSettingsFailure": "Algo deu errado ao salvar configurações.",
"components.Settings.SettingsUsers.saving": "Salvando…",
"components.Settings.SettingsUsers.save": "Salvar Mudanças",
"components.Settings.SettingsUsers.localLogin": "Habilitar Autenticação Local",
"components.Settings.SettingsUsers.defaultPermissions": "Permissões Padrão de Usúario",
"components.Settings.Notifications.pgpPrivateKeyTip": "Assina mensagens encriptadas de e-mail (Senha PGP necessária)",
"components.Settings.Notifications.pgpPrivateKey": "Chave <PgpLink>PGP</PgpLink> privada",
"components.Settings.Notifications.pgpPasswordTip": "Assina mensagens encriptadas de e-mail (Chave privada PGP necessária)",
"components.Settings.Notifications.pgpPassword": "Senha <PgpLink>PGP</PgpLink>",
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "Notificações de <strong>Mídia Aprovada</strong>, <strong>Mídia Recusada</strong>, e <strong>Mídia Disponível</strong> serão enviadas ao usuário que fez a solicitação.",
"components.NotificationTypeSelector.mediaAutoApprovedDescription": "Envia uma notificação quando a mídia solicitada é aprovada automaticamente.",
"components.NotificationTypeSelector.mediaAutoApproved": "Mídia Aprovada Automaticamente",
"components.TvDetails.episodeRuntimeMinutes": "{runtime} minutos",
"components.RequestModal.AdvancedRequester.loading": "Carregando…",
"components.RequestModal.AdvancedRequester.folder": "{path} ({space})"
"components.Settings.SettingsJobsCache.plex-full-scan": "Escaneamento de Todas Bibliotecas do Plex"
}

View File

@@ -35,14 +35,14 @@
"components.Settings.Notifications.validationSmtpPortRequired": "Você deve fornecer a porta SMTP",
"components.Settings.Notifications.validationSmtpHostRequired": "Você deve fornecer um servidor SMTP",
"components.Settings.Notifications.validationFromRequired": "Você deve fornecer um endereço do remetente",
"components.Settings.Notifications.validationChatIdRequired": "Você deve fornecer um ID de chat válido",
"components.Settings.Notifications.validationChatIdRequired": "Você deve fornecer um ID de chat",
"components.Settings.Notifications.validationBotAPIRequired": "Você deve fornecer um token de autenticação de bot",
"components.Settings.Notifications.telegramsettingssaved": "Configurações de notificação Telegram salvas com sucesso!",
"components.Settings.Notifications.telegramsettingsfailed": "Falhou o salvar das configurações de notificação Telegram.",
"components.Settings.Notifications.ssldisabletip": "SSL deve ser desabilitado em conexões TLS padrões (porta 587)",
"components.Settings.Notifications.smtpPort": "Porta SMTP",
"components.Settings.Notifications.smtpHost": "Servidor SMTP",
"components.Settings.Notifications.settinguptelegramDescription": "Para configurar notificações Telegram, você precisará <CreateBotLink>criar um bot</CreateBotLink> e obter a chave API do bot. Além disso, você precisará do ID do chat para o qual você deseja enviar notificações. Você pode encontrar isso adicionando <GetIdBotLink>@get_id_bot</GetIdBotLink> ao chat e inserindo o comando <code>/my_id</code>.",
"components.Settings.Notifications.settinguptelegramDescription": "Para configurar notificações Telegram, você precisará <CreateBotLink>criar um bot</CreateBotLink> e obter a chave API do bot. Além disso, você precisará do ID do chat para o qual você deseja enviar notificações. Você pode obter isso adicionando <GetIdBotLink>@get_id_bot</GetIdBotLink> ao chat.",
"components.Settings.Notifications.settinguptelegram": "Configurando notificações Telegram",
"components.Settings.Notifications.senderName": "Nome do Remetente",
"components.Settings.Notifications.enableSsl": "Activar SSL",
@@ -151,7 +151,7 @@
"components.RequestModal.AdvancedRequester.loadingprofiles": "Carregando perfis…",
"components.RequestModal.AdvancedRequester.loadingfolders": "Carregando pastas…",
"components.RequestModal.AdvancedRequester.destinationserver": "Servidor Destino",
"components.RequestModal.AdvancedRequester.default": "{name} (Padrão)",
"components.RequestModal.AdvancedRequester.default": "(Padrão)",
"components.RequestModal.AdvancedRequester.animenote": "* Esta série é um anime.",
"components.RequestModal.AdvancedRequester.advancedoptions": "Opções Avançadas",
"components.RequestList.status": "Estado",
@@ -169,11 +169,11 @@
"components.RequestList.filterPending": "Pendentes",
"components.RequestList.filterApproved": "Aprovadas",
"components.RequestList.filterAll": "Todas",
"components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Temporada} other {Temporadas}}",
"components.RequestList.RequestItem.seasons": "Temporadas",
"components.RequestList.RequestItem.requestedby": "Solicitado por {username}",
"components.RequestList.RequestItem.notavailable": "N/A",
"components.RequestList.RequestItem.failedretry": "Algo errou retentando a fazer a solicitação.",
"components.RequestCard.seasons": "{seasonCount, plural, one {Temporada} other {Temporadas}}",
"components.RequestCard.seasons": "Temporadas",
"components.RequestCard.requestedby": "Solicitado por {username}",
"components.RequestCard.all": "Todas",
"components.RequestButton.viewrequest4k": "Ver Solicitação 4K",
@@ -191,7 +191,7 @@
"components.RequestButton.approverequest": "Aprovar Solicitação",
"components.RequestButton.approve4krequests": "Aprovar {requestCount} {requestCount, plural, one {Solicitação} other {Solicitações}} 4K",
"components.RequestBlock.server": "Servidor Destino",
"components.RequestBlock.seasons": "{seasonCount, plural, one {Temporada} other {Temporadas}}",
"components.RequestBlock.seasons": "Temporadas",
"components.RequestBlock.rootfolder": "Pasta Raíz",
"components.RequestBlock.requestoverrides": "Mudanças na Solicitação",
"components.RequestBlock.profilechanged": "Perfil de Qualidade",
@@ -202,15 +202,15 @@
"components.PersonDetails.crewmember": "Membro da Equipa Técnica",
"components.PersonDetails.ascharacter": "como {character}",
"components.PersonDetails.appearsin": "Aparece em",
"components.NotificationTypeSelector.mediafailedDescription": "Envia uma notificação quando mídia solicitada não é adicionada ao Radarr ou Sonarr.",
"components.NotificationTypeSelector.mediafailedDescription": "Envia uma notificação quando a mídia não é adicionada ao Radarr ou Sonarr.",
"components.NotificationTypeSelector.mediarequestedDescription": "Envia uma notificação quando a mídia é solicitada e requer aprovação.",
"components.NotificationTypeSelector.mediarequested": "Mídia Solicitada",
"components.NotificationTypeSelector.mediafailed": "Mídia Falhou",
"components.NotificationTypeSelector.mediadeclinedDescription": "Envia uma notificação quando uma solicitação de mídia é rejeitada.",
"components.NotificationTypeSelector.mediadeclinedDescription": "Envia uma notificação quando uma solicitação é rejeitada.",
"components.NotificationTypeSelector.mediadeclined": "Mídia Rejeitada",
"components.NotificationTypeSelector.mediaavailableDescription": "Envia uma notificação quando a mídia solicitada estiver disponível.",
"components.NotificationTypeSelector.mediaavailableDescription": "Envia uma notificação quando a mídia estiver disponível.",
"components.NotificationTypeSelector.mediaavailable": "Mídia Disponível",
"components.NotificationTypeSelector.mediaapprovedDescription": "Envia uma notificação quando a mídia solicitada é aprovada manualmente.",
"components.NotificationTypeSelector.mediaapprovedDescription": "Envia uma notificação quando mídia é aprovada. Por padrão, as solicitações aprovadas automaticamente não acionam notificações.",
"components.NotificationTypeSelector.mediaapproved": "Mídia Aprovada",
"components.MovieDetails.watchtrailer": "Ver Trailer",
"components.MovieDetails.viewfullcrew": "Ver Equipa Técnica Completa",
@@ -821,8 +821,8 @@
"components.RegionSelector.regionDefault": "Todas as Regiões",
"components.Settings.webhook": "Webhook",
"components.Settings.email": "E-Mail",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "As notificações por e-mail de <strong>Mídia Solicitada</strong>, <strong>Mídia Aprovada Automaticamente</strong> e <strong>Mídia Falhou</strong> são enviadas a todos os utilizadores com a permissão <strong>Gerir Solicitações</strong> .",
"components.Settings.Notifications.emailNotificationTypesAlert": "Destinatários de Notificação de E-mail",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "Para os tipos de notificação \"Mídia Solicitada\" e \"Mídia Falhou\", as notificações serão enviadas apenas para utilizadores com a permissão \"Gerir Solicitações\".",
"components.Settings.Notifications.emailNotificationTypesAlert": "Destinatários de E-Mail de Notificação",
"components.UserProfile.UserSettings.UserGeneralSettings.originalLanguageDefault": "Todas as Idiomas",
"components.Settings.originalLanguageDefault": "Todas as Idiomas",
"components.UserProfile.UserSettings.UserGeneralSettings.languageServerDefault": "Padrão ({language})",
@@ -873,26 +873,5 @@
"components.Discover.StudioSlider.studios": "Estúdios",
"components.Discover.NetworkSlider.networks": "Redes",
"components.Settings.Notifications.botAvatarUrl": "URL do Avatar do Bot",
"components.Settings.Notifications.validationUrl": "Você deve fornecer uma URL valida",
"components.Discover.DiscoverTvLanguage.languageSeries": "Séries em {language}",
"components.Discover.DiscoverMovieLanguage.languageMovies": "Filmes em {language}",
"components.UserProfile.ProfileHeader.userid": "ID de Utilizador: {userid}",
"components.UserProfile.ProfileHeader.requests": "{requestCount} {requestCount, plural, one {Solicitação} other {Solicitações}}",
"components.UserProfile.ProfileHeader.joindate": "Entrou no {joindate}",
"components.Settings.menuUsers": "Utilizadores",
"components.Settings.SettingsUsers.userSettingsDescription": "Definir as configurações de utilizador global e padrão.",
"components.Settings.SettingsUsers.userSettings": "Utilizadores",
"components.Settings.SettingsUsers.toastSettingsSuccess": "Configurações salvas com sucesso!",
"components.Settings.SettingsUsers.toastSettingsFailure": "Algo errou salvando as configurações.",
"components.Settings.SettingsUsers.saving": "Salvando…",
"components.Settings.SettingsUsers.save": "Salvar Mudanças",
"components.Settings.SettingsUsers.localLogin": "Ativar Login de Utilizador Local",
"components.Settings.SettingsUsers.defaultPermissions": "Permissões de Utilizador Padrão",
"components.UserProfile.UserSettings.unauthorizedDescription": "Você não tem permissão para modificar as configurações deste utilizador.",
"components.UserProfile.UserSettings.unauthorized": "Desautorizado",
"components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Você não pode modificar suas próprias permissões.",
"components.UserProfile.UserSettings.UserPermissions.unauthorized": "Desautorizado",
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "Notificações por e-mail de <strong>Mídia Aprovada</strong>, <strong>Mídia Rejeitada</strong> e <strong>Mídia Disponível</strong> são enviadas ao utilizador que enviou a solicitação.",
"components.NotificationTypeSelector.mediaAutoApprovedDescription": "Envia uma notificação quando a mídia solicitada é aprovada automaticamente.",
"components.NotificationTypeSelector.mediaAutoApproved": "Mídia Aprovada Automaticamente"
"components.Settings.Notifications.validationUrl": "Você deve fornecer uma URL valida"
}

View File

@@ -392,7 +392,7 @@
"components.RequestModal.AdvancedRequester.loadingprofiles": "Загрузка профилей…",
"components.RequestModal.AdvancedRequester.loadinglanguages": "Загрузка языков…",
"components.RequestModal.AdvancedRequester.loadingfolders": "Загрузка папок…",
"components.RequestModal.AdvancedRequester.default": "{name} (По умолчанию)",
"components.RequestModal.AdvancedRequester.default": "(По умолчанию)",
"components.RequestModal.AdvancedRequester.advancedoptions": "Дополнительные параметры",
"components.RequestList.sortModified": "Последнее изменение",
"components.RequestList.sortAdded": "Дата запроса",

View File

@@ -6,7 +6,7 @@
"components.Setup.configureplex": "Konfigurera Plex",
"components.Settings.validationPortRequired": "Du måste ange en port",
"components.Settings.validationHostnameRequired": "Du måste ange hostname/IP",
"components.Settings.toastSettingsSuccess": "Inställningar sparade!",
"components.Settings.toastSettingsSuccess": "Inställningar sparade.",
"components.Settings.toastSettingsFailure": "Något gick fel när inställningarna skulle sparas.",
"components.Settings.toastApiKeySuccess": "Ny API-nyckel skapad!",
"components.Settings.toastApiKeyFailure": "Något gick fel vid skapandet av ny API-nyckel.",
@@ -15,14 +15,14 @@
"components.Settings.startscan": "Starta scanning",
"components.Settings.ssl": "SSL",
"components.Settings.sonarrsettings": "Sonarrinställningar",
"components.Settings.sonarrSettingsDescription": "Konfigurera din Sonarr-anslutning nedan. Du kan ha flera Sonarr-konfigurationer, men bara två kan vara aktiva som standard när som helst (en för standard HD och en för 4K). Administratörer kan åsidosätta servern som används för nya förfrågningar.",
"components.Settings.sonarrSettingsDescription": "Konfigurera anslutningen till Sonarr nedan. Du kan ha multipla Sonarr-servrar men enbart två aktiva som standard (en för standard HD-material och en för 4K-material). Administratörer kan åsidosätta vilken server som används för nya förfrågningar.",
"components.Settings.servernamePlaceholder": "Plex Servernamn",
"components.Settings.servername": "Servernamn",
"components.Settings.saving": "Sparar…",
"components.Settings.save": "Spara ändringar",
"components.Settings.runnow": "Kör Nu",
"components.Settings.radarrsettings": "Radarrinställningar",
"components.Settings.radarrSettingsDescription": "Konfigurera din Radarr-anslutning nedan. Du kan ha flera Radarr-konfigurationer, men bara två kan vara aktiva som standard (en för standard HD och en för 4K). Administratörer kan åsidosätta servern som används för nya förfrågningar.",
"components.Settings.radarrSettingsDescription": "Konfigurera anslutningen till Radarr nedan. Du kan ha multipla Radarr-servrar men enbart två aktiva som standard (en för standard HD-material och en för 4K-material). Administratörer kan åsidosätta vilken server som används för nya förfrågningar.",
"components.Settings.port": "Port",
"components.Settings.plexsettingsDescription": "Konfigurera inställningarna för din Plex-server. Overseerr scannar din Plex-server för att se vilka media som är tillgängliga.",
"components.Settings.plexsettings": "Plexinställningar",
@@ -162,7 +162,7 @@
"components.Settings.Notifications.discordsettingssaved": "Notiferingsinställningar för Discord sparade!",
"components.Settings.Notifications.authUser": "SMTP Användarnamn",
"components.Settings.Notifications.authPass": "SMTP Lösenord",
"components.Settings.Notifications.agentenabled": "Aktivera agenten",
"components.Settings.Notifications.agentenabled": "Aktiverad",
"components.Search.searchresults": "Sökresultat",
"components.RequestModal.status": "Status",
"components.RequestModal.selectseason": "Välj säsong(er)",
@@ -191,13 +191,13 @@
"components.RequestList.next": "Nästa",
"components.RequestList.modifiedBy": "Senast Ändrad Av",
"components.RequestList.mediaInfo": "Media Information",
"components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Säsong} other {Säsonger}}",
"components.RequestList.RequestItem.seasons": "Säsonger",
"components.RequestList.RequestItem.requestedby": "Begärd av {username}",
"components.RequestList.RequestItem.notavailable": "N/A",
"components.RequestCard.seasons": "{seasonCount, plural, one {Säsong} other {Säsonger}}",
"components.RequestCard.seasons": "Säsonger",
"components.RequestCard.requestedby": "Begärd av {username}",
"components.RequestCard.all": "Alla",
"components.RequestBlock.seasons": "{seasonCount, plural, one {Säsong} other {Säsonger}}",
"components.RequestBlock.seasons": "Säsonger",
"components.PlexLoginButton.loginwithplex": "Logga in med Plex",
"components.PlexLoginButton.loggingin": "Loggar in…",
"components.PlexLoginButton.loading": "Laddar…",
@@ -207,7 +207,7 @@
"components.MovieDetails.viewrequest": "Visa förfrågan",
"components.MovieDetails.userrating": "Användarbetyg",
"components.MovieDetails.unavailable": "Otillgänglig",
"components.MovieDetails.studio": "{studioCount, plural, one {Studio} other {Studior}}",
"components.MovieDetails.studio": "Studio",
"components.MovieDetails.status": "Status",
"components.MovieDetails.similarsubtext": "Andra filmer som liknar {title}",
"components.MovieDetails.similar": "Liknande Titlar",
@@ -224,7 +224,7 @@
"components.MovieDetails.manageModalTitle": "Hantera Film",
"components.MovieDetails.manageModalRequests": "Förfrågningar",
"components.MovieDetails.manageModalNoRequests": "Inga förfrågningar",
"components.MovieDetails.manageModalClearMediaWarning": "Denna handling kan ej ångras och kommer att radera all data för denna film, inklusive alla förfrågningar. Om det här objektet finns i ditt Plex-bibliotek kommer media information att återskapas vid nästa inläsning.",
"components.MovieDetails.manageModalClearMediaWarning": "Denna handling kan ej ångras och kommer att radera all data för denna film, inklusive alla förfrågningar. Om det här objektet finns i ditt Plex-bibliotek kommer media information att återskapas vid nästa synkronisering.",
"components.MovieDetails.manageModalClearMedia": "Rensa All Media Data",
"components.MovieDetails.decline": "Avböj",
"components.MovieDetails.cast": "Roller",
@@ -336,11 +336,11 @@
"components.TvDetails.overviewunavailable": "Beskrivning otillgänglig.",
"components.TvDetails.overview": "Beskrivning",
"components.TvDetails.originallanguage": "Ursprungligt Språk",
"components.TvDetails.network": "{networkCount, plural, one {Nätverk} other {Nätverk}}",
"components.TvDetails.network": "Nätverk",
"components.TvDetails.manageModalTitle": "Hantera TV-serier",
"components.TvDetails.manageModalRequests": "Förfrågningar",
"components.TvDetails.manageModalNoRequests": "Inga förfrågningar",
"components.TvDetails.manageModalClearMediaWarning": "* Denna handling går inte att ångra och raderar all media data för denna TV Serien, inklusive förfrågningar. Om objektet finns i ditt Plexbibliotek kommer mediainformationen att återskapas vid nästa skanning.",
"components.TvDetails.manageModalClearMediaWarning": "* Denna handling går inte att ångra och raderar all media data för denna TV Serien, inklusive förfrågningar. Om objektet finns i ditt Plexbibliotek kommer mediainformationen att återskapas vid nästa synkronisering.",
"components.TvDetails.manageModalClearMedia": "Rensa All Media Data",
"components.TvDetails.declinerequests": "Avböj {requestCount} {requestCount, plural, one {Request} other {Requests}}",
"components.TvDetails.decline": "Avböj",
@@ -410,51 +410,51 @@
"components.StatusBadge.status4k": "4K {status}",
"components.Settings.defaultPermissions": "Standard Användarbehörigheter",
"components.Settings.SettingsAbout.documentation": "Dokumentation",
"components.Settings.Notifications.validationChatIdRequired": "Du måste ange ett giltigt chatt-ID",
"components.Settings.Notifications.validationBotAPIRequired": "Du måste ange en bot-autentiseringstoken",
"components.Settings.Notifications.validationChatIdRequired": "Du måste ange ett Chatt-ID",
"components.Settings.Notifications.validationBotAPIRequired": "Du måste ange en Bot API-nyckel",
"components.Settings.Notifications.telegramsettingssaved": "Notiferingsinställningar för Telegram sparade!",
"components.Settings.Notifications.telegramsettingsfailed": "Notifieringsinställningar för Telegram misslyckades att sparas.",
"components.Settings.Notifications.ssldisabletip": "SSL bör inaktiveras på standard TLS-anslutningar (Port 587)",
"components.Settings.Notifications.settinguptelegramDescription": "För att konfigurera Telegram-aviseringar måste du <CreateBotLink> skapa en bot </CreateBotLink> och hämta bot-API-nyckeln. Dessutom behöver du chatt-ID för chatten som du vill skicka meddelanden till. Du hittar detta genom att lägga till <GetIdBotLink> @get_id_bot </GetIdBotLink> i chatten och utfärda kommandot <code> /my_id </code>.",
"components.Settings.Notifications.settinguptelegramDescription": "För att konfigurera Telegram, måste du <CreateBotLink> skapa en bot </CreateBotLink> och hämta bot API-nyckeln. Dessutom behöver du chatt-id för chatten du vill att botten ska skicka meddelanden till. Du kan göra detta genom att lägga till <GetIdBotLink> @get_id_bot </GetIdBotLink> i chatten eller gruppchatten.",
"components.Settings.Notifications.settinguptelegram": "Konfigurera Telegram-notifikationer",
"components.Settings.Notifications.senderName": "Avsändarens namn",
"components.Settings.Notifications.notificationtypes": "Notifikationstyper",
"components.Settings.Notifications.chatId": "Chatt-ID",
"components.Settings.Notifications.botAPI": "Bot-autentiseringstoken",
"components.Settings.Notifications.botAPI": "Bot API",
"components.Settings.Notifications.NotificationsWebhook.webhooksettingssaved": "Notiferingsinställningar för webhook sparade!",
"components.Settings.Notifications.NotificationsWebhook.webhooksettingsfailed": "Notifieringsinställningar för webhook misslyckades att sparas.",
"components.Settings.Notifications.NotificationsWebhook.webhookUrlPlaceholder": "Fjärr-webhook URL",
"components.Settings.Notifications.NotificationsWebhook.webhookUrl": "Webhook-URL",
"components.Settings.Notifications.NotificationsWebhook.validationWebhookUrlRequired": "Du måste ange en webhook URL",
"components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "Du måste ange en giltig JSON Payload",
"components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "Du måste ange en JSON Payload",
"components.Settings.Notifications.NotificationsWebhook.testsent": "Testmeddelande skickat!",
"components.Settings.Notifications.NotificationsWebhook.test": "Test",
"components.Settings.Notifications.NotificationsWebhook.templatevariablehelp": "Lathund för variabler",
"components.Settings.Notifications.NotificationsWebhook.saving": "Sparar…",
"components.Settings.Notifications.NotificationsWebhook.save": "Spara Ändringar",
"components.Settings.Notifications.NotificationsWebhook.resetPayloadSuccess": "JSON har återställts!",
"components.Settings.Notifications.NotificationsWebhook.resetPayloadSuccess": "JSON återställd till standard.",
"components.Settings.Notifications.NotificationsWebhook.resetPayload": "Återställ till Standard",
"components.Settings.Notifications.NotificationsWebhook.notificationtypes": "Notifikationstyper",
"components.Settings.Notifications.NotificationsWebhook.customJson": "Ladda JSON",
"components.Settings.Notifications.NotificationsWebhook.customJson": "Anpassad JSON",
"components.Settings.Notifications.NotificationsWebhook.authheader": "Behörighetsrubrik",
"components.Settings.Notifications.NotificationsWebhook.agentenabled": "Aktiverad",
"components.Settings.Notifications.NotificationsSlack.webhookUrlPlaceholder": "Webhook-URL",
"components.Settings.Notifications.NotificationsSlack.settingupslackDescription": "För att konfigurera Slack-aviseringar måste du skapa en <WebhookLink> Inkommande webbhook </WebhookLink> -integration och ange webbhook-URL nedan.",
"components.Settings.Notifications.NotificationsSlack.settingupslackDescription": "För att använda Slack-aviseringar måste du skapa en <WebhookLink> Inkommande Webhook </WebhookLink> och använda den angivna webbhook-URL:en nedan.",
"components.Settings.Notifications.NotificationsSlack.notificationtypes": "Notifikationstyper",
"components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "Du måste ange en giltig användarnyckel",
"components.Settings.Notifications.NotificationsPushover.settinguppushoverDescription": "För att konfigurera Pushover-aviseringar måste du <RegisterApplicationLink> registrera ett program </RegisterApplicationLink> och ange API-token nedan. (Du kan använda en av våra <IconLink> officiella ikoner på GitHub </IconLink>.) Du behöver också din användarnyckel.",
"components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "Du måste ange en giltig applikationstoken",
"components.Settings.Notifications.NotificationsPushover.userToken": "Användarnyckel",
"components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "Du måste ange en användartoken",
"components.Settings.Notifications.NotificationsPushover.settinguppushoverDescription": "För att konfigurera Pushover måste du <RegisterApplicationLink> registrera en applikation </RegisterApplicationLink> och få en åtkomstnyckel. När du skapar applikationen kan du använda en av ikonerna i den <IconLink> offentliga mappen </IconLink> på github. Du behöver också en Pushover-användartoken som finns på startsidan efter att du loggat in.",
"components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "Du måste ange en åtkomstnyckel",
"components.Settings.Notifications.NotificationsPushover.userToken": "Användartoken",
"components.Settings.Notifications.NotificationsPushover.testsent": "Testmeddelande skickat!",
"components.Settings.Notifications.NotificationsPushover.test": "Test",
"components.Settings.Notifications.NotificationsPushover.settinguppushover": "Konfigurera Pushover-notifikationer",
"components.Settings.Notifications.NotificationsPushover.saving": "Sparar…",
"components.Settings.Notifications.NotificationsPushover.save": "Spara Ändringar",
"components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Inställningar för Pushover-meddelanden sparade!",
"components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Inställningar för pushover-meddelanden sparade!",
"components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Inställningar för pushover-meddelanden kunde inte sparas.",
"components.Settings.Notifications.NotificationsPushover.notificationtypes": "Notifikationstyper",
"components.Settings.Notifications.NotificationsPushover.agentenabled": "Aktiverad",
"components.Settings.Notifications.NotificationsPushover.accessToken": "Applikation / API Token",
"components.Settings.Notifications.NotificationsPushover.accessToken": "Åtkomstnycklar",
"components.RequestModal.request4ktitle": "Begär {titel} i 4K",
"components.RequestModal.request4kfrom": "Det finns för närvarande en väntande 4K-begäran från {username}.",
"components.RequestModal.request4k": "Begär 4K",
@@ -481,13 +481,13 @@
"components.RequestButton.approverequest4k": "Godkänn 4K-begäran",
"components.RequestButton.approverequest": "Godkänn begäran",
"components.RequestButton.approve4krequests": "Godkänn {requestCount} {requestCount, plural, one {Request} other {Requests}}",
"components.NotificationTypeSelector.mediarequestedDescription": "Skickar en notifikation när media är begärd och kräver godkänande.",
"components.NotificationTypeSelector.mediarequestedDescription": "Skickar en notifikation när ny media misslyckas att läggas till i tjänsterna (Radarr/Sonarr). För vissa agenter skickas notifikation endast till administratörer eller användare med behörighet för att \"Hantera förfrågningar\".",
"components.NotificationTypeSelector.mediarequested": "Media Begärd",
"components.NotificationTypeSelector.mediafailedDescription": "Skickar en notifikation när begärd media misslyckas att läggas till i Radarr eller Sonarr.",
"components.NotificationTypeSelector.mediafailedDescription": "Skickar en notifikation när media misslyckas att läggas till i tjänsterna (Radarr/Sonarr). För vissa agenter skickas notifikation endast till administratörer eller användare med behörighet för att \"Hantera förfrågningar\".",
"components.NotificationTypeSelector.mediafailed": "Media Misslyckades",
"components.NotificationTypeSelector.mediaavailableDescription": "Skickar en notifikation när begärd media blir tillgänglig.",
"components.NotificationTypeSelector.mediaavailableDescription": "Skickar en notifikation när media blir tillgänglig.",
"components.NotificationTypeSelector.mediaavailable": "Media Tillgängligt",
"components.NotificationTypeSelector.mediaapprovedDescription": "Skickar en notifikation när media blivit manuellt godkänt.",
"components.NotificationTypeSelector.mediaapprovedDescription": "Skickar en notifikation när media blivit godkänt.",
"components.NotificationTypeSelector.mediaapproved": "Media Godkänt",
"components.MovieDetails.viewfullcrew": "Visa Filmteam",
"components.MovieDetails.view": "Visa",
@@ -499,7 +499,7 @@
"components.UserList.bulkedit": "Mass-redigering",
"components.PermissionEdit.voteDescription": "Ger behörighet att rösta på förfrågningar (röstning är inte implementerad ännu).",
"components.PermissionEdit.vote": "Rösta",
"components.PermissionEdit.usersDescription": "Ger behörighet att hantera Overseerr-användare. Användare med denna behörighet kan inte ändra användare eller bevilja administratörsbehörighet.",
"components.PermissionEdit.usersDescription": "Ger behörighet att hantera Overseerr-användare. Användare med denna behörighet kan inte modifiera användare med Administratörsbehörighet, eller ge det.",
"components.PermissionEdit.users": "Hantera Användare",
"components.PermissionEdit.settingsDescription": "Get behörighet att modifiera alla Overseerr-inställningar. En användare måste ha denna behörighet för att kunna ge den till andra.",
"components.PermissionEdit.settings": "Hantera Inställningar",
@@ -511,9 +511,9 @@
"components.PermissionEdit.request4kDescription": "Ger behörighet att begära 4K filmer och serier.",
"components.PermissionEdit.request4k": "Begära 4K",
"components.PermissionEdit.request": "Begära",
"components.PermissionEdit.managerequestsDescription": "Ger behörighet att hantera Overseerr-förfrågningar. Detta inkluderar att godkänna och neka förfrågningar. Alla förfrågningar som görs av en användare med den här behörigheten kommer att godkännas automatiskt oavsett om de har autogodkännande.",
"components.PermissionEdit.managerequestsDescription": "Ger behörighet att hantera Overseerr förfrågningar. Detta inkluderar att godkänna och neka förfrågningar.",
"components.PermissionEdit.managerequests": "Hantera Förfrågningar",
"components.PermissionEdit.adminDescription": "Fullständig administratörsbehörighet. Överskrider alla andra behörighetskontroller.",
"components.PermissionEdit.adminDescription": "Fullständig administratörsbehörighet. Överskrider alla behörighetskontroller.",
"components.Settings.enablenotifications": "Aktivera Notifikationer",
"components.Settings.autoapprovedrequests": "Aktivera Notifikationer för Automatiska Godkännanden",
"components.Settings.notificationsettingssaved": "Notifikationsinställningarna sparade!",
@@ -542,7 +542,7 @@
"components.RequestModal.AdvancedRequester.loadingprofiles": "Laddar profiler…",
"components.RequestModal.AdvancedRequester.loadingfolders": "Laddar mappar…",
"components.RequestModal.AdvancedRequester.destinationserver": "Destinationsserver",
"components.RequestModal.AdvancedRequester.default": "{name} (Standard)",
"components.RequestModal.AdvancedRequester.default": "(Standard)",
"components.RequestModal.AdvancedRequester.animenote": "* Denna serien är en anime.",
"components.RequestModal.AdvancedRequester.advancedoptions": "Avancerade Val",
"components.RequestBlock.server": "Destinationsserver",
@@ -565,16 +565,16 @@
"components.PersonDetails.crewmember": "Besättningsmedlem",
"components.Login.validationemailrequired": "Du måste ange en giltig e-postadress",
"components.Login.email": "E-postadress",
"components.PermissionEdit.autoapproveSeriesDescription": "Beviljar automatiskt godkännande för icke-4K-serieförfrågningar från den här användaren.",
"components.PermissionEdit.autoapproveSeriesDescription": "Ger automatiskt godkännande av alla begärda serier för denna användaren.",
"components.PermissionEdit.autoapproveSeries": "Auto-Godkänn Serier",
"components.PermissionEdit.autoapproveMoviesDescription": "Beviljar automatiskt godkännande för icke-4K-filmförfrågningar från den här användaren.",
"components.PermissionEdit.autoapproveMoviesDescription": "Ger automatiskt godkännande av alla begärda filmer för denna användaren.",
"components.PermissionEdit.autoapproveMovies": "Auto-Godkänn Filmer",
"components.PermissionEdit.autoapproveDescription": "Beviljar automatiskt godkännande för alla icke-4K-förfrågningar från den här användaren.",
"components.PermissionEdit.autoapproveDescription": "Ger automatiskt godkännande för alla förfrågningar som är gjorda av denna användaren.",
"components.PermissionEdit.autoapprove": "Auto-Godkänn",
"components.PermissionEdit.advancedrequestDescription": "Ger behörighet att använda avancerade inställningar vid en begäran (så som att ändra server, profiler eller sökväg).",
"components.PermissionEdit.advancedrequestDescription": "Ger behörighet att använda avancerade inställningar vid en begäran; så som att ändra server, profiler eller sökväg.",
"components.PermissionEdit.advancedrequest": "Avancerade Förfrågningar",
"components.PermissionEdit.admin": "Admin",
"components.NotificationTypeSelector.mediadeclinedDescription": "Skickar en notifikation när en begärd media är avböjd.",
"components.NotificationTypeSelector.mediadeclinedDescription": "Skickar en notifikation när en begäran är avböjd.",
"components.NotificationTypeSelector.mediadeclined": "Media Avböjd",
"components.MovieDetails.play4konplex": "Spela upp 4K på Plex",
"components.MovieDetails.playonplex": "Spela upp på Plex",
@@ -599,7 +599,7 @@
"components.ResetPassword.validationpasswordminchars": "Lösenordet är för kort; det behöver innehålla minst 8 bokstäver",
"components.ResetPassword.validationpasswordmatch": "Lösenorden måste stämma överrens",
"components.ResetPassword.validationemailrequired": "Du måste ange en giltig e-postadress",
"components.ResetPassword.resetpasswordsuccessmessage": "Lösenordet har återställts, om länken var giltig och associerad med en befintlig användare.",
"components.ResetPassword.resetpasswordsuccessmessage": "Om länken är giltig och är ansluten till en användare så har lösenordet blivit återställt.",
"components.ResetPassword.resetpassword": "Återställ ditt lösenord",
"components.ResetPassword.requestresetlinksuccessmessage": "En lösenordslänk har skickat till e-postadressen ifall den är associerad till en giltig användare.",
"components.ResetPassword.password": "Lösenord",
@@ -671,11 +671,11 @@
"components.TvDetails.opensonarr": "Öppna Serien i Sonarr",
"components.TvDetails.downloadstatus": "Nedladdningsstatus",
"components.TvDetails.areyousure": "Är du säker?",
"components.Settings.SonarrModal.syncEnabled": "Aktivera skanning",
"components.Settings.SonarrModal.syncEnabled": "Aktivera Sync",
"components.Settings.SonarrModal.preventSearch": "Inaktivera Auto-Sök",
"components.Settings.SonarrModal.externalUrlPlaceholder": "Extern URL som pekar till din Sonarr server",
"components.Settings.SonarrModal.externalUrl": "Extern URL",
"components.Settings.RadarrModal.syncEnabled": "Aktivera skanning",
"components.Settings.RadarrModal.syncEnabled": "Aktivera Sync",
"components.Settings.RadarrModal.preventSearch": "Inaktivera Auto-Sök",
"components.Settings.RadarrModal.externalUrlPlaceholder": "Extern URL som pekar till din Radarr server",
"components.Settings.RadarrModal.externalUrl": "Extern URL",
@@ -700,189 +700,5 @@
"components.Settings.serverRemote": "fjärr",
"components.Settings.serverLocal": "lokal",
"components.Settings.serverConnected": "ansluten",
"components.Settings.csrfProtectionTip": "Sätter rättigheterna för API:t till skrivskyddad (kräver HTTPS och Overseerr måste laddas om för att det skall gå i kraft)",
"i18n.loading": "Laddar…",
"components.UserProfile.recentrequests": "Senaste förfrågningar",
"components.UserProfile.UserSettings.settings": "Användarinställningar",
"components.UserProfile.UserSettings.menuPermissions": "Behörigheter",
"components.UserProfile.UserSettings.menuNotifications": "Meddelanden",
"components.UserProfile.UserSettings.menuGeneralSettings": "Allmänna Inställningar",
"components.UserProfile.UserSettings.menuChangePass": "Lösenord",
"components.UserProfile.UserSettings.UserPermissions.toastSettingsSuccess": "Inställningarna har sparats!",
"components.UserProfile.UserSettings.UserPermissions.toastSettingsFailure": "Något gick fel när inställningarna sparades.",
"components.UserProfile.UserSettings.UserPermissions.saving": "Sparar…",
"components.UserProfile.UserSettings.UserPermissions.save": "Spara ändringar",
"components.UserProfile.UserSettings.UserPermissions.plexuser": "Plex-användare",
"components.UserProfile.UserSettings.UserPermissions.permissions": "Behörigheter",
"components.UserProfile.UserSettings.UserPermissions.localuser": "Lokal användare",
"components.UserProfile.UserSettings.UserPermissions.displayName": "Visningsnamn",
"components.UserProfile.UserSettings.UserPasswordChange.validationNewPasswordLength": "Lösenordet är för kort; den ska vara minst 8 tecken lång",
"components.UserProfile.UserSettings.UserPasswordChange.validationNewPassword": "Du måste ange ett nytt lösenord",
"components.UserProfile.UserSettings.UserPasswordChange.validationCurrentPassword": "Du måste ange ditt nuvarande lösenord",
"components.UserProfile.UserSettings.UserPasswordChange.validationConfirmPasswordSame": "Lösenordet måste matcha",
"components.UserProfile.UserSettings.UserPasswordChange.validationConfirmPassword": "Du måste bekräfta ditt nya lösenord",
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsSuccess": "Lösenordet ändrat!",
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailure": "Något gick fel när du ändrade lösenordet. Är ditt nuvarande lösenord korrekt?",
"components.UserProfile.UserSettings.UserPasswordChange.saving": "Sparar…",
"components.UserProfile.UserSettings.UserPasswordChange.save": "Spara ändringar",
"components.UserProfile.UserSettings.UserPasswordChange.password": "Lösenord",
"components.UserProfile.UserSettings.UserPasswordChange.nopermissionDescription": "Du har inte behörighet att ändra användarens lösenord.",
"components.UserProfile.UserSettings.UserPasswordChange.nopermission": "Obehörig",
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordsetDescription": "Detta användarkonto har för närvarande inget lösenord specifikt för {applicationTitle}. Konfigurera ett lösenord nedan så att det här kontot kan logga in som en \"lokal användare\".",
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordset": "Inget lösenord inställt",
"components.UserProfile.UserSettings.UserPasswordChange.newpassword": "Nytt lösenord",
"components.UserProfile.UserSettings.UserPasswordChange.currentpassword": "Nuvarande lösenord",
"components.UserProfile.UserSettings.UserPasswordChange.confirmpassword": "Bekräfta lösenord",
"components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "Du måste ange ett giltigt ID för Telegram-chatt",
"components.UserProfile.UserSettings.UserNotificationSettings.validationDiscordId": "Du måste ange ett giltigt användar-ID för Discord",
"components.UserProfile.UserSettings.UserNotificationSettings.toastSettingsSuccess": "Inställningarna har sparats!",
"components.UserProfile.UserSettings.UserNotificationSettings.toastSettingsFailure": "Något gick fel när inställningarna sparades.",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "<TelegramBotLink>Starta en chatt</TelegramBotLink>, lägg till <GetIdBotLink>@get_id_bot</GetIdBotLink> och använd kommandot <code>/my_id </code>",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTip": "Lägg till <GetIdBotLink>@get_id_bot</GetIdBotLink> i chatten",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatId": "Telegrem chatt-ID",
"components.UserProfile.UserSettings.UserNotificationSettings.sendSilentlyDescription": "Skicka meddelanden utan ljud",
"components.UserProfile.UserSettings.UserNotificationSettings.sendSilently": "Skicka Telegram-meddelanden tyst",
"components.UserProfile.UserSettings.UserNotificationSettings.saving": "Sparar…",
"components.UserProfile.UserSettings.UserNotificationSettings.save": "Spara ändringar",
"components.UserProfile.UserSettings.UserNotificationSettings.plexuser": "Plex-användare",
"components.UserProfile.UserSettings.UserNotificationSettings.notificationsettings": "Aviseringsinställningar",
"components.UserProfile.UserSettings.UserNotificationSettings.localuser": "Lokal använadre",
"components.UserProfile.UserSettings.UserNotificationSettings.enableNotifications": "Aktivera aviseringar",
"components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "<FindDiscordIdLink> ID-nummer </FindDiscordIdLink> för ditt Discord-användarkonto",
"components.UserProfile.UserSettings.UserNotificationSettings.discordId": "Discord-ID",
"components.UserProfile.UserSettings.UserGeneralSettings.user": "Användare",
"components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsSuccess": "Inställningarna har sparats!",
"components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsFailure": "Något gick fel när inställningarna sparades.",
"components.UserProfile.UserSettings.UserGeneralSettings.saving": "Sparar…",
"components.UserProfile.UserSettings.UserGeneralSettings.save": "Spara ändringar",
"components.UserProfile.UserSettings.UserGeneralSettings.role": "Roll",
"components.UserProfile.UserSettings.UserGeneralSettings.regionTip": "Filtrera innehåll efter region (gäller endast kategorierna \"Populär\" och \"Kommande\")",
"components.UserProfile.UserSettings.UserGeneralSettings.region": "Upptäck region",
"components.UserProfile.UserSettings.UserGeneralSettings.plexuser": "Plex-användare",
"components.UserProfile.UserSettings.UserGeneralSettings.owner": "Ägare",
"components.UserProfile.UserSettings.UserGeneralSettings.originallanguageTip": "Filtrera innehåll efter originalspråk (gäller endast kategorierna \"Populär\" och \"Kommande\")",
"components.UserProfile.UserSettings.UserGeneralSettings.originallanguage": "Upptäck språk",
"components.UserProfile.UserSettings.UserGeneralSettings.originalLanguageDefault": "Alla språk",
"components.UserProfile.UserSettings.UserGeneralSettings.localuser": "Lokala användare",
"components.UserProfile.UserSettings.UserGeneralSettings.languageServerDefault": "Standard ({language})",
"components.UserProfile.UserSettings.UserGeneralSettings.generalsettings": "Allmänna Inställningar",
"components.UserProfile.UserSettings.UserGeneralSettings.displayName": "Visningsnamn",
"components.UserProfile.UserSettings.UserGeneralSettings.admin": "Administratör",
"components.UserProfile.UserSettings.UserGeneralSettings.accounttype": "Kontotyp",
"components.UserProfile.ProfileHeader.userid": "Användar-ID: {userid}",
"components.UserProfile.ProfileHeader.settings": "Ändra inställningar",
"components.UserProfile.ProfileHeader.requests": "{requestCount} {requestCount, plural, one {Förfrågan} other {Förfrågningar}}",
"components.UserProfile.ProfileHeader.profile": "Visa profil",
"components.UserProfile.ProfileHeader.joindate": "Medlem sedan {joindate}",
"components.UserList.userfail": "Något gick fel när användaren sparades.",
"components.UserList.sortUpdated": "Senast uppdaterad",
"components.UserList.sortRequests": "Antal förfrågningar",
"components.UserList.sortDisplayName": "Visningsnamn",
"components.UserList.sortCreated": "Skapelsedagen",
"components.UserList.showingresults": "Visar <strong>{from}</strong> till <strong>{to}</strong> av <strong>{total}</strong> resultat",
"components.UserList.saving": "Sparar…",
"components.UserList.save": "Spara ändringar",
"components.UserList.resultsperpage": "Visa {pageSize} resultat per sida",
"components.UserList.previous": "Föregående",
"components.UserList.permissions": "Rättigheter",
"components.UserList.owner": "Ägare",
"components.UserList.next": "Nästa",
"components.UserList.edituser": "Redigera användare",
"components.UserList.accounttype": "Kontotyp",
"components.TvDetails.seasons": "{seasonCount, plural, one {# Säsong} other {# Säsonger}}",
"components.Setup.scanbackground": "Skanning körs i bakgrunden. Du kan fortsätta installationsprocessen under tiden.",
"components.Settings.webhook": "Webhook",
"components.Settings.scanning": "Skannar…",
"components.Settings.scan": "Skanna Plex-bibliotek",
"components.Settings.regionTip": "Filtrera innehåll efter region (gäller endast kategorierna \"Populär\" och \"Kommande\")",
"components.Settings.region": "Upptäck Region",
"components.Settings.originallanguageTip": "Filtrera innehåll efter originalspråk (gäller endast kategorierna \"Populär\" och \"Kommande\")",
"components.Settings.originallanguage": "Upptäck språk",
"components.Settings.originalLanguageDefault": "Alla språk",
"components.Settings.notificationAgentSettingsDescription": "Välj vilka typer av aviseringar som ska skickas och vilka aviseringsagenter som ska användas.",
"components.Settings.menuUsers": "Användare",
"components.Settings.email": "E-post",
"components.Settings.SonarrModal.validationLanguageProfileRequired": "Du måste välja en språkprofil",
"components.Settings.SonarrModal.testFirstLanguageProfiles": "Testa anslutningen för att ladda språkprofiler",
"components.Settings.SonarrModal.selectLanguageProfile": "Välj spåkprofil",
"components.Settings.SonarrModal.loadinglanguageprofiles": "Laddar språkprofiler…",
"components.Settings.SonarrModal.languageprofile": "Spårkprofil",
"components.Settings.SonarrModal.animelanguageprofile": "Anime språkprofil",
"components.Settings.SettingsUsers.userSettingsDescription": "Konfigurera globala och standardinställningar för användare.",
"components.Settings.SettingsUsers.userSettings": "Anvädnare",
"components.Settings.SettingsUsers.toastSettingsSuccess": "Inställningar sparade!",
"components.Settings.SettingsUsers.toastSettingsFailure": "Något gick fel när inställningarna sparades.",
"components.Settings.SettingsUsers.saving": "Sparar…",
"components.Settings.SettingsUsers.save": "Spara ändringar",
"components.Settings.SettingsUsers.localLogin": "Aktivera lokal användarinloggning",
"components.Settings.SettingsUsers.defaultPermissions": "Standard användarrättigheter",
"components.Settings.SettingsJobsCache.unknownJob": "Okänt jobb",
"components.Settings.SettingsJobsCache.sonarr-scan": "Sonarr-skanning",
"components.Settings.SettingsJobsCache.radarr-scan": "Radarr-skanning",
"components.Settings.SettingsJobsCache.plex-recently-added-scan": "Skanning av det senast tillagda i Plex",
"components.Settings.SettingsJobsCache.plex-full-scan": "Full Plex-biblioteksskanning",
"components.Settings.SettingsJobsCache.download-sync-reset": "Hämta synkroniseringsåterställning",
"components.Settings.SettingsJobsCache.download-sync": "Ladda ner synkronisering",
"components.Settings.SettingsAbout.preferredmethod": "Föredraget",
"components.Settings.Notifications.validationUrl": "Du måste ange en giltig URL",
"components.Settings.Notifications.sendSilentlyTip": "Skicka meddelanden utan ljud",
"components.Settings.Notifications.sendSilently": "Skicka tyst",
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "<strong> Medie godkänd</strong>, <strong>Media nekad</strong> och <strong>Media tillgängligt</strong> e-postmeddelanden skickas till användaren som skickade begäran.",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "<strong> E-postmeddelanden </strong>, <strong> Automatiskt godkänd media </strong> och <strong> Media misslyckades </strong> skickas till alla användare med behörigheten <strong> Hantera begäranden </strong>. .",
"components.Settings.Notifications.emailNotificationTypesAlert": "Mottagare av e-postmeddelanden",
"components.Settings.Notifications.botUsername": "Bot-användarnamn",
"components.Settings.Notifications.botAvatarUrl": "Bot Avatar URL",
"components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "Du måste ange en åtkomsttoken",
"components.Settings.Notifications.NotificationsPushbullet.testSent": "Testnotifikation skickad!",
"components.Settings.Notifications.NotificationsPushbullet.test": "Test",
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbulletDescription": "För att konfigurera Pushbullet-aviseringar måste du <CreateAccessTokenLink> skapa en åtkomsttoken </CreateAccessTokenLink> och ange den nedan.",
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbullet": "Ställ in Pushbullet-meddelanden",
"components.Settings.Notifications.NotificationsPushbullet.saving": "Sparar…",
"components.Settings.Notifications.NotificationsPushbullet.save": "Spara ändringar",
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "Meddelandeinställningar för Pushbullet sparades!",
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsFailed": "Meddelandeinställningarna för Pushbullet kunde inte sparas.",
"components.Settings.Notifications.NotificationsPushbullet.notificationTypes": "Notifikationstyper",
"components.Settings.Notifications.NotificationsPushbullet.agentEnabled": "Aktivera agent",
"components.Settings.Notifications.NotificationsPushbullet.accessToken": "Åtkomsttoken",
"components.RequestModal.AdvancedRequester.loadinglanguages": "Laddar språk…",
"components.RequestModal.AdvancedRequester.languageprofile": "Språkprofil",
"components.RequestList.resultsperpage": "Visa {pageSize} resultat per sida",
"components.RequestList.filterProcessing": "Bearbetning",
"components.RequestList.filterAvailable": "Tillgängliga",
"components.RequestList.RequestItem.status": "Status",
"components.RequestList.RequestItem.requested": "Begärda",
"components.RequestList.RequestItem.modifieduserdate": "{date} av{user}",
"components.RequestList.RequestItem.modified": "Modifierad",
"components.RequestList.RequestItem.areyousure": "Är du säker?",
"components.RequestList.RequestItem.all": "Alla",
"components.RequestCard.status": "Status",
"components.RequestBlock.requestoverrides": "Begär åsidosättningar",
"components.RegionSelector.regionServerDefault": "Standard ({region})",
"components.RegionSelector.regionDefault": "Alla Regioner",
"components.PermissionEdit.autoapprove4kSeriesDescription": "Beviljar automatiskt godkännande för 4K-serieförfrågningar från den här användaren.",
"components.PermissionEdit.autoapprove4kSeries": "Godkänn automatiskt 4K-serier",
"components.PermissionEdit.autoapprove4kMoviesDescription": "Ger automatiskt godkännande för 4K-filmförfrågningar från den här användaren.",
"components.PermissionEdit.autoapprove4kMovies": "Godkänn automatiskt 4K-filmer",
"components.PermissionEdit.autoapprove4kDescription": "Ger automatiskt godkännande för alla 4K-förfrågningar från denna användare.",
"components.PermissionEdit.autoapprove4k": "Automatiskt godkännande av 4K",
"components.NotificationTypeSelector.mediaAutoApprovedDescription": "Skickar en notifikation när media blivit automatiskt godkänt.",
"components.NotificationTypeSelector.mediaAutoApproved": "Media Automatiskt Godkänd",
"components.Layout.UserDropdown.settings": "Inställningar",
"components.Layout.UserDropdown.myprofile": "Profil",
"components.Discover.upcomingtv": "Kommande serier",
"components.Discover.StudioSlider.studios": "Studio",
"components.Discover.NetworkSlider.networks": "Nätverk",
"components.Discover.DiscoverTvLanguage.languageSeries": "{language} Serier",
"components.Discover.DiscoverTvGenre.genreSeries": "{genre} Serier",
"components.Discover.DiscoverStudio.studioMovies": "{studio} Filmer",
"components.Discover.DiscoverNetwork.networkSeries": "{network} Serier",
"components.Discover.DiscoverMovieLanguage.languageMovies": "{language} Filmer",
"components.Discover.DiscoverMovieGenre.genreMovies": "{genre} Filmer",
"components.CollectionDetails.requestswillbecreated4k": "Följande titlar kommer begäras i 4K:",
"components.CollectionDetails.requestcollection4k": "Begär Kollektion i 4K",
"components.CollectionDetails.request4k": "Begär 4K",
"components.UserProfile.UserSettings.unauthorizedDescription": "Du har inte behörighet att ändra den här användarens inställningar.",
"components.UserProfile.UserSettings.unauthorized": "Obehörig",
"components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Du kan inte ändra dina egna behörigheter.",
"components.UserProfile.UserSettings.UserPermissions.unauthorized": "Obehörig"
"components.Settings.csrfProtectionTip": "Sätter rättigheterna för API:t till skrivskyddad (kräver HTTPS och Overseerr måste laddas om för att det skall gå i kraft)"
}

View File

@@ -73,9 +73,9 @@
"components.Setup.continue": "繼續",
"components.Setup.configureservices": "配置伺服器",
"components.Setup.configureplex": "配置 Plex 伺服器",
"components.Settings.sonarrsettings": "Sonarr 設",
"components.Settings.radarrsettings": "Radarr 設",
"components.Settings.menuPlexSettings": "Plex",
"components.Settings.sonarrsettings": "Sonarr 設",
"components.Settings.radarrsettings": "Radarr 設",
"components.Settings.menuPlexSettings": "Plex 設定",
"components.UserList.importfromplexerror": "從 Plex 導入用戶中出了點問題。",
"components.UserList.importfromplex": "從 Plex 導入用戶",
"components.UserList.importedfromplex": "從 Plex 導入了 {userCount} 個用戶",
@@ -205,7 +205,7 @@
"components.NotificationTypeSelector.mediafailed": "請求失敗",
"components.NotificationTypeSelector.mediaapproved": "請求批准",
"components.NotificationTypeSelector.mediaavailableDescription": "將媒體可觀看時發送通知。",
"components.NotificationTypeSelector.mediaapprovedDescription": "將請求手動批准時發送通知。",
"components.NotificationTypeSelector.mediaapprovedDescription": "將請求批准時發送通知。默認情況下,自動批准的請求不會發送通知。",
"components.NotificationTypeSelector.mediaavailable": "媒體可觀看",
"components.MovieDetails.watchtrailer": "觀看預告片",
"components.MovieDetails.viewfullcrew": "檢視製作群",
@@ -285,7 +285,7 @@
"components.UserList.usertype": "用戶類型",
"i18n.movies": "電影",
"components.Setup.signinMessage": "首先,請使用您的 Plex 帳戶登入",
"components.CollectionDetails.numberofmovies": "{count} 部電影",
"components.CollectionDetails.numberofmovies": "電影數:{count}",
"components.CollectionDetails.movies": "電影",
"components.UserEdit.request4kMovies": "提交 4K 電影的請求",
"components.Settings.Notifications.validationFromRequired": "必須輸入發件人電子郵件地址",
@@ -382,7 +382,7 @@
"components.UserList.deleteconfirm": "確定要刪除這個用戶嗎?由這個用戶的所有儲存資料將被清除。",
"components.Settings.SettingsAbout.Releases.releasedataMissing": "無法獲取軟體版本資料。GitHub 崩潰了嗎?",
"components.UserList.passwordinfodescription": "啟用電子郵件通知才能自動生成密碼。",
"components.UserList.passwordinfo": "密碼生成",
"components.UserList.passwordinfo": "關於自動生成密碼",
"components.Settings.Notifications.validationBotAPIRequired": "必須輸入 bot 機器人應用程式密鑰",
"components.Settings.Notifications.botAPI": "Bot 機器人應用程式密鑰",
"components.Settings.menuServices": "伺服器",
@@ -449,7 +449,7 @@
"components.Settings.RadarrModal.validationNameRequired": "必須輸入伺服器名稱",
"components.Settings.RadarrModal.validationHostnameRequired": "必須輸入主機名稱或 IP 位址",
"components.Settings.RadarrModal.validationApiKeyRequired": "必須輸入應用程式密鑰",
"components.Settings.Notifications.validationChatIdRequired": "必須輸入有效聊天室 ID",
"components.Settings.Notifications.validationChatIdRequired": "必須輸入聊天室 ID",
"components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "必須輸入有效的 JSON 有效負載",
"components.Settings.Notifications.NotificationsWebhook.authheader": "Authorization 頭欄位",
"components.Settings.RadarrModal.minimumAvailability": "最低狀態",
@@ -488,7 +488,7 @@
"components.RequestModal.AdvancedRequester.qualityprofile": "質量設置",
"components.RequestModal.AdvancedRequester.animenote": "*這是個動漫節目。",
"components.RequestModal.AdvancedRequester.advancedoptions": "進階選項",
"components.RequestModal.AdvancedRequester.default": "{name}(默認)",
"components.RequestModal.AdvancedRequester.default": "(默認)",
"components.RequestModal.AdvancedRequester.destinationserver": "目標伺服器",
"components.RequestBlock.server": "目標伺服器",
"components.RequestModal.AdvancedRequester.rootfolder": "根目錄",
@@ -701,7 +701,7 @@
"components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsSuccess": "設置保存成功!",
"components.UserProfile.UserSettings.settings": "用戶設定",
"components.UserProfile.recentrequests": "最新請求",
"components.UserProfile.UserSettings.UserPermissions.permissions": "權限設置",
"components.UserProfile.UserSettings.UserPermissions.permissions": "權限",
"components.UserList.permissions": "權限",
"components.UserProfile.UserSettings.menuPermissions": "權限",
"components.UserProfile.UserSettings.menuNotifications": "通知",
@@ -712,13 +712,13 @@
"components.UserProfile.UserSettings.UserPermissions.displayName": "用戶名",
"components.UserProfile.UserSettings.UserPasswordChange.validationNewPasswordLength": "密碼必須至少包含八個字符",
"components.UserProfile.UserSettings.UserPasswordChange.validationConfirmPasswordSame": "密碼必須匹配",
"components.UserProfile.UserSettings.UserPasswordChange.password": "密碼設置",
"components.UserProfile.UserSettings.UserPasswordChange.password": "密碼",
"components.UserProfile.UserSettings.UserPasswordChange.confirmpassword": "確認密碼",
"components.UserProfile.UserSettings.UserNotificationSettings.plexuser": "Plex 用戶",
"components.UserProfile.UserSettings.UserNotificationSettings.notificationsettings": "通知設置",
"components.UserProfile.UserSettings.UserNotificationSettings.localuser": "本地用戶",
"components.UserProfile.UserSettings.UserNotificationSettings.enableNotifications": "啟用通知",
"components.UserList.edituser": "編輯用戶權限",
"components.UserList.edituser": "編輯用戶",
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsFailed": "Pushbullet 通知設置保存失敗。",
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "Pushbullet 通知設置保存成功!",
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbullet": "Pushbullet 通知設定",
@@ -779,7 +779,7 @@
"components.CollectionDetails.requestcollection4k": "提交 4K 系列請求",
"components.CollectionDetails.request4k": "提交 4K 請求",
"components.Settings.SettingsAbout.Releases.runningDevelopMessage": "開發版本的變更日誌不會顯示在以下。請直接到 <GithubLink>GitHub</GithubLink> 查看變更日誌。",
"components.Settings.Notifications.settinguptelegramDescription": "要設置 Telegram 通知,必須先<CreateBotLink>建立一個 「bot」 機器人</CreateBotLink>以及把 <GetIdBotLink>@get_id_bot</GetIdBotLink> 加到聊天室,然後在以下輸入機器人應用程式密鑰和聊天室的 ID 號(可在聊天室裡發出 <code>/my_id</code> 命令查找聊天室 ID。",
"components.Settings.Notifications.settinguptelegramDescription": "要設置 Telegram 通知,必須先<CreateBotLink>建立一個 「bot」 機器人</CreateBotLink>以及把 <GetIdBotLink>@get_id_bot</GetIdBotLink> 加到聊天室,然後在以下輸入機器人應用程式密鑰和聊天室的 ID 號。",
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbulletDescription": "要設置 Pushbullet 通知,必須先<CreateAccessTokenLink>獲取 API 令牌</CreateAccessTokenLink>,然後在下面輸入。",
"components.Settings.Notifications.NotificationsPushover.settinguppushoverDescription": "要設置 Pushover 通知,必須先<RegisterApplicationLink>建立一個應用程式</RegisterApplicationLink>,然後在以下輸入生成的 API 令牌和您的用戶密鑰。(添加應用時可以使用 <IconLink>Overseerr 的官方圖標</IconLink>。)",
"components.Settings.Notifications.NotificationsSlack.settingupslackDescription": "要設置 Slack 通知,必須先<WebhookLink>建立一個 「incoming webhook」</WebhookLink>,然後在以下輸入生成的網絡鉤手網址。",
@@ -799,7 +799,7 @@
"components.Settings.generalsettingsDescription": "Overseerr 的全局和默認設置。",
"components.Settings.notificationsettingsDescription": "關於通知的全局設置。",
"components.Settings.notificationAgentSettingsDescription": "設置通知類型和代理服務。",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "「<strong>請求提交</strong>」、「<strong>請求自動批准</strong>」、「<strong>請求失敗</strong>」這種通知類型,發送通知給所有具有「<strong>請求管理</strong>」權限的用戶。",
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "「請求提交」、「請求失敗」這種通知類型,發送通知給有「請求管理」權限的用戶。",
"components.UserProfile.UserSettings.UserGeneralSettings.regionTip": "以地區篩選結果(僅於「熱門」、「即將上映」)",
"components.Settings.regionTip": "以地區篩選結果(僅於「熱門」、「即將上映」)",
"components.UserProfile.UserSettings.UserGeneralSettings.originallanguageTip": "以原始語言篩選結果(僅於「熱門」、「即將上映」)",
@@ -845,7 +845,7 @@
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatId": "Telegram 聊天室 ID",
"components.UserProfile.UserSettings.UserNotificationSettings.sendSilently": "無聲 Telegram 通知",
"components.UserProfile.UserSettings.UserNotificationSettings.sendSilentlyDescription": "發送沒有聲音警報的通知",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "先<TelegramBotLink>建立一個聊天室</TelegramBotLink>以及把 <GetIdBotLink>@get_id_bot</GetIdBotLink> 加到聊天室,後在聊天室裡發出 <code>/my_id</code> 命令",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "先<TelegramBotLink>建立一個聊天室</TelegramBotLink>以及把 <GetIdBotLink>@get_id_bot</GetIdBotLink> 加到聊天室,後在聊天室裡發出 <code>/my_id</code> 命令",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTip": "把 <GetIdBotLink>@get_id_bot</GetIdBotLink> 加到聊天室",
"components.Settings.Notifications.botUsername": "Bot 機器人名",
"components.Discover.NetworkSlider.networks": "電視網",
@@ -867,35 +867,5 @@
"components.Settings.SettingsJobsCache.plex-recently-added-scan": "Plex 最新添加掃描",
"components.Settings.SettingsJobsCache.plex-full-scan": "Plex 媒體庫掃描",
"components.Discover.DiscoverTvLanguage.languageSeries": "{language}電視節目",
"components.Discover.DiscoverMovieLanguage.languageMovies": "{language}電影",
"components.UserProfile.ProfileHeader.userid": "用戶 ID{userid}",
"components.UserProfile.ProfileHeader.requests": "請求數:{requestCount}",
"components.UserProfile.ProfileHeader.joindate": "建立日期:{joindate}",
"components.Settings.SettingsUsers.saving": "保存中…",
"components.Settings.SettingsUsers.save": "保存",
"components.Settings.SettingsUsers.localLogin": "允許本地用戶登錄",
"components.Settings.SettingsUsers.defaultPermissions": "默認用戶權限",
"components.Settings.SettingsUsers.userSettingsDescription": "關於用戶的全局和默認設置。",
"components.Settings.SettingsUsers.userSettings": "用戶設定",
"components.Settings.menuUsers": "用戶",
"components.Settings.SettingsUsers.toastSettingsSuccess": "設置保存成功!",
"components.Settings.SettingsUsers.toastSettingsFailure": "保存設置中出了點問題。",
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "「<strong>請求批准</strong>」、「<strong>請求拒絕</strong>」、「<strong>媒體可觀看</strong>」通知類型,將發送通知給請求者。",
"components.NotificationTypeSelector.mediaAutoApprovedDescription": "將請求自動批准時發送通知。",
"components.NotificationTypeSelector.mediaAutoApproved": "請求自動批准",
"components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "您不能編輯自己的權限。",
"components.UserProfile.UserSettings.unauthorizedDescription": "您無權編輯此用戶的設置。",
"components.UserProfile.UserSettings.unauthorized": "未經授權",
"components.UserProfile.UserSettings.UserPermissions.unauthorized": "未經授權",
"components.Settings.Notifications.pgpPrivateKeyTip": "啟用電子郵件加密與簽章PGP 解密密碼也必須輸入)",
"components.Settings.Notifications.pgpPasswordTip": "啟用電子郵件加密與簽章PGP 私鑰也必須輸入)",
"components.UserProfile.UserSettings.UserNotificationSettings.pgpKeyTip": "啟用電子郵件加密",
"components.UserProfile.norequests": "無請求",
"components.Settings.Notifications.pgpPassword": "<PgpLink>PGP</PgpLink> 解密密碼",
"components.Settings.Notifications.pgpPrivateKey": "<PgpLink>PGP</PgpLink> 私鑰",
"components.UserProfile.UserSettings.UserNotificationSettings.pgpKey": "<PgpLink>PGP</PgpLink> 公鑰",
"components.TvDetails.episodeRuntime": "劇集片長",
"components.TvDetails.episodeRuntimeMinutes": "{runtime} 分鐘",
"components.RequestModal.AdvancedRequester.loading": "載入中…",
"components.RequestModal.AdvancedRequester.folder": "{path}{space}"
"components.Discover.DiscoverMovieLanguage.languageMovies": "{language}電影"
}

View File

@@ -16,7 +16,6 @@ import { InteractionProvider } from '../context/InteractionContext';
import StatusChecker from '../components/StatusChacker';
import { PublicSettingsResponse } from '../../server/interfaces/api/settingsInterfaces';
import { SettingsProvider } from '../context/SettingsContext';
import LoadingBar from '../components/LoadingBar';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const loadLocaleData = (locale: AvailableLocales): Promise<any> => {
@@ -114,7 +113,6 @@ const CoreApp: Omit<NextAppComponentType, 'origGetInitialProps'> = ({
defaultLocale="en"
messages={loadedMessages}
>
<LoadingBar />
<SettingsProvider currentSettings={currentSettings}>
<InteractionProvider>
<ToastProvider components={{ Toast }}>

View File

@@ -1,7 +1,6 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@tailwind screens;
body {
@apply bg-gray-900;
@@ -31,7 +30,7 @@ ul.cardList > li {
}
.slider-header {
@apply relative flex mt-6 mb-4;
@apply flex mt-6 mb-4;
}
.slider-title {
@@ -42,100 +41,17 @@ a.slider-title {
@apply hover:text-white;
}
.media-page {
@apply px-4 pt-16 -mx-4 -mt-16 bg-center bg-cover;
.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.media-header {
@apply flex flex-col items-center pt-4 xl:flex-row xl:items-end;
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.media-poster {
@apply w-32 rounded shadow md:rounded-lg md:shadow-2xl md:w-44 xl:w-52 xl:mr-4;
}
.media-status {
@apply mb-2 space-x-2;
}
.media-title {
@apply flex flex-col flex-1 mt-4 text-center text-white xl:mr-4 xl:mt-0 xl:text-left;
}
.media-title > h1 {
@apply text-2xl xl:text-4xl;
}
h1 > .media-year {
@apply text-2xl;
}
.media-attributes {
@apply mt-1 text-xs sm:text-sm xl:text-base xl:mt-0;
}
.media-actions {
@apply relative z-10 flex flex-wrap items-center justify-center flex-shrink-0 mt-4 sm:justify-end sm:flex-nowrap xl:mt-0;
}
.media-actions > * {
@apply mb-3 sm:mb-0;
}
.media-overview {
@apply flex flex-col pt-8 pb-4 text-white lg:flex-row;
}
.media-overview-left {
@apply flex-1 lg:mr-8;
}
.tagline {
@apply mb-4 text-xl italic text-gray-400 lg:text-2xl;
}
.media-overview h2 {
@apply text-xl sm:text-2xl;
}
.media-overview p {
@apply pt-2 text-sm text-gray-400 lg:text-base;
}
ul.media-crew {
@apply grid grid-cols-2 gap-6 mt-6 sm:grid-cols-3;
}
ul.media-crew > li {
@apply flex flex-col col-span-1 font-bold;
}
a.crew-name {
@apply font-normal text-gray-400 transition duration-300 hover:underline hover:text-gray-100;
}
.media-overview-right {
@apply w-full mt-8 lg:w-80 lg:mt-0;
}
.media-facts {
@apply text-sm bg-gray-900 border border-gray-700 rounded-lg shadow;
}
.media-fact {
@apply flex px-4 py-2 border-b border-gray-700 last:border-b-0;
}
.media-fact-value {
@apply flex-1 text-sm text-right text-gray-400;
}
.media-ratings {
@apply flex items-center justify-center px-4 py-2 border-b border-gray-700 last:border-b-0;
}
.media-rating {
@apply flex items-center mr-4 last:mr-0;
.toast {
width: 360px;
}
.error-message {
@@ -178,10 +94,6 @@ img.avatar-sm {
@apply flex max-w-lg rounded-md shadow-sm;
}
textarea {
@apply flex-1 block w-full min-w-0 text-white transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5;
}
.label-required {
@apply text-red-500;
}
@@ -194,22 +106,14 @@ textarea {
@apply pt-5 mt-8 text-white border-t border-gray-700;
}
label {
@apply block mb-1 text-sm font-medium leading-5 text-gray-400;
}
label.checkbox-label {
@apply sm:mt-1;
}
label.text-label {
@apply sm:mt-2;
}
input[type='checkbox'] {
@apply w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md;
}
.checkbox-label {
@apply block mb-1 text-sm font-medium leading-5 text-gray-400 sm:mt-1;
}
input[type='text'],
input[type='password'],
select {
@@ -234,6 +138,11 @@ select.short {
.protocol {
@apply inline-flex items-center px-3 text-gray-100 bg-gray-600 border border-r-0 border-gray-500 cursor-default rounded-l-md sm:text-sm;
}
.text-label {
@apply block mb-1 text-sm font-medium leading-5 text-gray-400 sm:mt-2;
}
.error {
@apply mt-2 text-sm text-red-500;
}
@@ -246,24 +155,11 @@ select.short {
@apply block mb-1 text-sm font-medium leading-6 text-gray-400;
}
.toast {
width: 360px;
}
/* Used for animating height */
.extra-max-height {
max-height: 100rem;
}
.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for Chrome, Safari and Opera */
.hide-scrollbar::-webkit-scrollbar {
display: none;

View File

@@ -7,7 +7,6 @@ module.exports = {
extend: {
transitionProperty: {
'max-height': 'max-height',
width: 'width',
},
fontFamily: {
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
@@ -62,7 +61,7 @@ module.exports = {
padding: ['first', 'last', 'responsive'],
borderWidth: ['first', 'last'],
margin: ['first', 'last', 'responsive'],
boxShadow: ['group-focus', 'responsive'],
boxShadow: ['group-focus'],
opacity: ['disabled', 'hover', 'group-hover'],
ringColor: ['focus', 'focus-within', 'hover', 'active'],
scale: ['hover', 'focus', 'group-hover'],

354
yarn.lock
View File

@@ -1034,13 +1034,6 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.18":
version "7.13.10"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d"
integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
@@ -2011,16 +2004,6 @@
lodash.merge "^4.6.2"
lodash.uniq "^4.5.0"
"@tanem/react-nprogress@^3.0.57":
version "3.0.57"
resolved "https://registry.yarnpkg.com/@tanem/react-nprogress/-/react-nprogress-3.0.57.tgz#926f0477574659dcbaa4d892743a11dac675c81b"
integrity sha512-hYNDAENoAQK3LttNs4IfWF4ByLoAaxJ/rxBTXeTR+x4kk5lLdRBqR0rcU6XrX0oyx+mXLqJk5IXterui6usBfg==
dependencies:
"@babel/runtime" "^7.12.18"
hoist-non-react-statics "^3.3.2"
prop-types "^15.7.2"
react-use "^15.3.8"
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@@ -2208,11 +2191,6 @@
resolved "https://registry.yarnpkg.com/@types/html-to-text/-/html-to-text-5.1.2.tgz#59a723cce41b573b7fa606414e2ceaa886038098"
integrity sha512-56PHFwRe18fmZ+UsN6GqUaoKfalOwFzxaBMRA2O5URde3d5mxdH1HvnIV7LSugCiO8JWlRdSL2L3xJXykCTKVg==
"@types/js-cookie@2.2.6":
version "2.2.6"
resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.6.tgz#f1a1cb35aff47bc5cfb05cb0c441ca91e914c26f"
integrity sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw==
"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6":
version "7.0.6"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
@@ -2269,15 +2247,25 @@
dependencies:
"@types/node" "*"
"@types/node@*", "@types/node@>= 8", "@types/node@^14.14.34":
version "14.14.34"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.34.tgz#07935194fc049069a1c56c0c274265abeddf88da"
integrity sha512-dBPaxocOK6UVyvhbnpFIj2W+S+1cBTkHQbFQfeeJhoKFbzYcVUGHvddeWPSucKATb3F0+pgDq0i6ghEaZjsugA==
"@types/node@*":
version "14.10.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.0.tgz#15815dff82c8dc30827f6b1286f865902945095a"
integrity sha512-SOIyrdADB4cq6eY1F+9iU48iIomFAPltu11LCvA9PKcyEwHadjCFzNVPotAR+oEJA0bCP4Xvvgy+vwu1ZjVh8g==
"@types/nodemailer@*", "@types/nodemailer@^6.4.1":
version "6.4.1"
resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.1.tgz#31f96f4410632f781d3613bd1f4293649e423f75"
integrity sha512-8081UY/0XTTDpuGqCnDc8IY+Q3DSg604wB3dBH0CaZlj4nZWHWuxtZ3NRZ9c9WUrz1Vfm6wioAUnqL3bsh49uQ==
"@types/node@>= 8":
version "14.14.10"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.10.tgz#5958a82e41863cfc71f2307b3748e3491ba03785"
integrity sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ==
"@types/node@^14.14.33":
version "14.14.33"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.33.tgz#9e4f8c64345522e4e8ce77b334a8aaa64e2b6c78"
integrity sha512-oJqcTrgPUF29oUP8AsUqbXGJNuPutsetaa9kTQAQce5Lx5dTYWV02ScBiT/k1BX/Z7pKeqedmvp39Wu4zR7N7g==
"@types/nodemailer@*", "@types/nodemailer@^6.4.0":
version "6.4.0"
resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.0.tgz#d8c039be3ed685c4719a026455555be82c124b74"
integrity sha512-KY7bFWB0MahRZvVW4CuW83qcCDny59pJJ0MQ5ifvfcjNwPlIT0vW4uARO4u1gtkYnWdhSvURegecY/tzcukJcA==
dependencies:
"@types/node" "*"
@@ -2655,11 +2643,6 @@
"@webassemblyjs/wast-parser" "1.9.0"
"@xtuc/long" "4.2.2"
"@xobotyi/scrollbar-width@1.9.5":
version "1.9.5"
resolved "https://registry.yarnpkg.com/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d"
integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==
"@xtuc/ieee754@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
@@ -3067,7 +3050,7 @@ asap@^2.0.0, asap@~2.0.3:
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
asn1.js@^5.0.0, asn1.js@^5.2.0:
asn1.js@^5.2.0:
version "5.4.1"
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07"
integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==
@@ -4619,7 +4602,7 @@ copy-descriptor@^0.1.0:
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
copy-to-clipboard@^3.2.0, copy-to-clipboard@^3.3.1:
copy-to-clipboard@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae"
integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==
@@ -4766,6 +4749,17 @@ cross-spawn@^5.0.1:
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
semver "^5.5.0"
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -4826,14 +4820,6 @@ css-has-pseudo@^0.10.0:
postcss "^7.0.6"
postcss-selector-parser "^5.0.0-rc.4"
css-in-js-utils@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz#3b472b398787291b47cfe3e44fecfdd9e914ba99"
integrity sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==
dependencies:
hyphenate-style-name "^1.0.2"
isobject "^3.0.1"
css-loader@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.3.0.tgz#c888af64b2a5b2e85462c72c0f4a85c7e2e0821e"
@@ -4900,14 +4886,6 @@ css-tree@1.0.0-alpha.39:
mdn-data "2.0.6"
source-map "^0.6.1"
css-tree@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.2.tgz#9ae393b5dafd7dae8a622475caec78d3d8fbd7b5"
integrity sha512-wCoWush5Aeo48GLhfHPbmvZs59Z+M7k5+B1xDnXbdWNcEF423DoFdqSWE0PM5aNk5nI5cp1q7ms36zGApY/sKQ==
dependencies:
mdn-data "2.0.14"
source-map "^0.6.1"
css-unit-converter@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21"
@@ -5002,11 +4980,6 @@ csstype@^3.0.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.2.tgz#ee5ff8f208c8cd613b389f7b222c9801ca62b3f7"
integrity sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw==
csstype@^3.0.6:
version "3.0.7"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b"
integrity sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g==
csurf@^1.11.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/csurf/-/csurf-1.11.0.tgz#ab0c3c6634634192bd3d6f4b861be20800eeb61a"
@@ -5106,20 +5079,34 @@ debug@3.1.0:
dependencies:
ms "2.0.0"
debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
dependencies:
ms "2.1.2"
ms "^2.1.1"
debug@^3.1.0, debug@^3.2.6:
debug@^3.1.0:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
dependencies:
ms "^2.1.1"
debug@^3.2.6:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
dependencies:
ms "^2.1.1"
debug@^4.0.0, debug@^4.2.0, debug@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
dependencies:
ms "2.1.2"
debuglog@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
@@ -5742,13 +5729,6 @@ error-ex@^1.2.0, error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
error-stack-parser@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8"
integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==
dependencies:
stackframe "^1.1.1"
es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5:
version "1.17.6"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a"
@@ -6076,6 +6056,19 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
md5.js "^1.3.4"
safe-buffer "^5.1.1"
execa@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
dependencies:
cross-spawn "^6.0.0"
get-stream "^3.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
execa@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
@@ -6293,7 +6286,7 @@ extsprintf@^1.2.0:
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
@@ -6335,16 +6328,6 @@ fast-safe-stringify@^2.0.4:
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
fast-shallow-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b"
integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==
fastest-stable-stringify@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz#3757a6774f6ec8de40c4e86ec28ea02417214c76"
integrity sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==
fastq@^1.6.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481"
@@ -7169,20 +7152,13 @@ hosted-git-info@^2.1.4, hosted-git-info@^2.7.1, hosted-git-info@^2.8.8:
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
hosted-git-info@^3.0.6:
hosted-git-info@^3.0.0, hosted-git-info@^3.0.6:
version "3.0.7"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.7.tgz#a30727385ea85acfcee94e0aad9e368c792e036c"
integrity sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==
dependencies:
lru-cache "^6.0.0"
hosted-git-info@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.0.tgz#9f06639a90beff66cacae6e77f8387b431d61ddc"
integrity sha512-fqhGdjk4av7mT9fU/B01dUtZ+WZSc/XEXMoLXDVZukiQRXxeHSSz3AqbeWRJHtF8EQYHlAgB1NSAHU0Cm7aqZA==
dependencies:
lru-cache "^6.0.0"
html-tags@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
@@ -7353,11 +7329,6 @@ husky@4.3.8:
slash "^3.0.0"
which-pm-runs "^1.0.0"
hyphenate-style-name@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==
i18n-locales@^0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/i18n-locales/-/i18n-locales-0.0.4.tgz#95d6505f6563f870f68860c23d35f82bd805cbf5"
@@ -7529,13 +7500,6 @@ init-package-json@^1.10.3:
validate-npm-package-license "^3.0.1"
validate-npm-package-name "^3.0.0"
inline-style-prefixer@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-6.0.0.tgz#f73d5dbf2855733d6b153a4d24b7b47a73e9770b"
integrity sha512-XTHvRUS4ZJNzC1GixJRmOlWSS45fSt+DJoyQC9ytj0WxQfcgofQtDtyKKYxHUqEsWCs+LIWftPF1ie7+i012Fg==
dependencies:
css-in-js-utils "^2.0.0"
inquirer@6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca"
@@ -8087,11 +8051,6 @@ jest-worker@24.9.0:
merge-stream "^2.0.0"
supports-color "^6.1.0"
js-cookie@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
js-stringify@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
@@ -8813,7 +8772,12 @@ lodash.zipobject@^4.1.3:
resolved "https://registry.yarnpkg.com/lodash.zipobject/-/lodash.zipobject-4.1.3.tgz#b399f5aba8ff62a746f6979bf20b214f964dbef8"
integrity sha1-s5n1q6j/YqdG9peb8gshT5ZNvvg=
lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4:
version "4.17.20"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -9063,11 +9027,6 @@ mdast-util-to-string@^2.0.0:
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b"
integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==
mdn-data@2.0.14:
version "2.0.14"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==
mdn-data@2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
@@ -9524,20 +9483,6 @@ nan@^2.12.1:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
nano-css@^5.2.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.3.1.tgz#b709383e07ad3be61f64edffacb9d98250b87a1f"
integrity sha512-ENPIyNzANQRyYVvb62ajDd7PAyIgS2LIUnT9ewih4yrXSZX4hKoUwssy8WjUH++kEOA5wUTMgNnV7ko5n34kUA==
dependencies:
css-tree "^1.1.2"
csstype "^3.0.6"
fastest-stable-stringify "^2.0.2"
inline-style-prefixer "^6.0.0"
rtl-css-js "^1.14.0"
sourcemap-codec "^1.4.8"
stacktrace-js "^2.0.2"
stylis "^4.0.6"
nanoclone@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4"
@@ -9668,6 +9613,11 @@ next@10.0.3:
optionalDependencies:
sharp "0.26.2"
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
node-abi@^2.7.0:
version "2.19.3"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.3.tgz#252f5dcab12dad1b5503b2d27eddd4733930282d"
@@ -10389,13 +10339,6 @@ opener@^1.5.1:
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
openpgp@^5.0.0-1:
version "5.0.0-1"
resolved "https://registry.yarnpkg.com/openpgp/-/openpgp-5.0.0-1.tgz#28456d930895483770f099e373045e3ce9dbf9f9"
integrity sha512-yfmRStdmOQPZbNbvwyQrqjLOTGW4QO0/aok/Vt08Zhf4UB9w0tGA5c6zBxDefxq+SmXlqEsmdNu+AtYx5G8D6A==
dependencies:
asn1.js "^5.0.0"
optionator@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
@@ -10755,7 +10698,7 @@ path-is-inside@^1.0.1, path-is-inside@^1.0.2, path-is-inside@~1.0.2:
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
path-key@^2.0.0:
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
@@ -11954,11 +11897,6 @@ react-truncate-markup@^5.1.0:
prop-types "^15.6.0"
resize-observer-polyfill "1.5.x"
react-universal-interface@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b"
integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==
react-use-clipboard@1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/react-use-clipboard/-/react-use-clipboard-1.0.7.tgz#34cccdfb4f17f5e6522e38f2cee62d05f605597a"
@@ -11966,26 +11904,6 @@ react-use-clipboard@1.0.7:
dependencies:
copy-to-clipboard "^3.3.1"
react-use@^15.3.8:
version "15.3.8"
resolved "https://registry.yarnpkg.com/react-use/-/react-use-15.3.8.tgz#ca839ac7fb3d696e5ccbeabbc8dadc2698969d30"
integrity sha512-GeGcrmGuUvZrY5wER3Lnph9DSYhZt5nEjped4eKDq8BRGr2CnLf9bDQWG9RFc7oCPphnscUUdOovzq0E5F2c6Q==
dependencies:
"@types/js-cookie" "2.2.6"
"@xobotyi/scrollbar-width" "1.9.5"
copy-to-clipboard "^3.2.0"
fast-deep-equal "^3.1.3"
fast-shallow-equal "^1.0.0"
js-cookie "^2.2.1"
nano-css "^5.2.1"
react-universal-interface "^0.6.2"
resize-observer-polyfill "^1.5.1"
screenfull "^5.0.0"
set-harmonic-interval "^1.0.1"
throttle-debounce "^2.1.0"
ts-easing "^0.2.0"
tslib "^2.0.0"
react@17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
@@ -12383,7 +12301,7 @@ require-main-filename@^2.0.0:
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
resize-observer-polyfill@1.5.x, resize-observer-polyfill@^1.5.1:
resize-observer-polyfill@1.5.x:
version "1.5.1"
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
@@ -12532,13 +12450,6 @@ rndm@1.2.0:
resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c"
integrity sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=
rtl-css-js@^1.14.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.14.0.tgz#daa4f192a92509e292a0519f4b255e6e3c076b7d"
integrity sha512-Dl5xDTeN3e7scU1cWX8c9b6/Nqz3u/HgR4gePc1kWXYiQWVQbKCEyK6+Hxve9LbcJ5EieHy1J9nJCN3grTtGwg==
dependencies:
"@babel/runtime" "^7.1.2"
run-async@^2.2.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
@@ -12648,11 +12559,6 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
screenfull@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.1.0.tgz#85c13c70f4ead4c1b8a935c70010dfdcd2c0e5c8"
integrity sha512-dYaNuOdzr+kc6J6CFcBrzkLCfyGcMg+gWkJ8us93IQ7y1cevhQAugFsaCdMHb6lw8KV3xPzSxzH7zM1dQap9mA==
secure-random-password@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/secure-random-password/-/secure-random-password-0.2.2.tgz#eb043bcada24bc372bc98457845222b2a96d2058"
@@ -12665,17 +12571,25 @@ secure-random@^1.1.2:
resolved "https://registry.yarnpkg.com/secure-random/-/secure-random-1.1.2.tgz#ed103b460a851632d420d46448b2a900a41e7f7c"
integrity sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==
semantic-release-docker-buildx@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/semantic-release-docker-buildx/-/semantic-release-docker-buildx-1.0.1.tgz#9d63ee60638905bd4caba6e15190f091de4ded67"
integrity sha512-DU5OCNM2cDpjM1Gr83jJnPgxryQysPno9cvDbs0AY8NwUL/nZc5mZn59UZB9BjHtSKsjKX1pgRb0bFd7LWJOOQ==
semantic-release-docker-buildx@^0.0.0-development:
version "0.0.0-development"
resolved "https://registry.yarnpkg.com/semantic-release-docker-buildx/-/semantic-release-docker-buildx-0.0.0-development.tgz#c71df764298034fb388a1661f82fbc093342bf02"
integrity sha512-b+3QORi4ukNRymMQj3M45ips+8b/YHQ/VpREGY7iRVz9Gs+3mL4BDDEhzoLwwrnTQHpyBdbCg+b0TzEbhIHAFw==
dependencies:
execa "^5.0.0"
semantic-release@^17.4.2:
version "17.4.2"
resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.4.2.tgz#b5147b5a629c227b7074ad4cc89920a14cb08c96"
integrity sha512-TPLWuoe2L2DmgnQEh+OLWW5V1T+ZAa1xWuHXsuPAWEko0BqSdLPl+5+BlQ+D5Bp27S5gDJ1//Y1tgbmvUhnOCw==
semantic-release-docker@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/semantic-release-docker/-/semantic-release-docker-2.2.0.tgz#9a5e1c8b4fe2b85063e1dc64e15550e7bf26c26f"
integrity sha512-p5pZuyD05ax2OIJY3MTa9ekPbnR7hw3Pzv79sDELx4/MwHdkxjoLNsbNHnH4RNfgyRYGUfnS3R0CnYv3e713FQ==
dependencies:
"@semantic-release/error" "^2.1.0"
execa "^0.10.0"
semantic-release@^17.4.1:
version "17.4.1"
resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.4.1.tgz#71b89a772452f8cd3bbd55bbf99287630be1c81f"
integrity sha512-o/Rjk0HCBUWEYxN99Vq04Th+XtRQAxbC+FN+pBQ49wpqQ5NW/cfwhfw0qyxeTEhbchQ/1/KGMPWqD4/rRScAag==
dependencies:
"@semantic-release/commit-analyzer" "^8.0.0"
"@semantic-release/error" "^2.2.0"
@@ -12692,7 +12606,7 @@ semantic-release@^17.4.2:
get-stream "^6.0.0"
git-log-parser "^1.2.0"
hook-std "^2.0.0"
hosted-git-info "^4.0.0"
hosted-git-info "^3.0.0"
lodash "^4.17.15"
marked "^2.0.0"
marked-terminal "^4.1.1"
@@ -12740,7 +12654,7 @@ semver@7.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
semver@7.3.4, semver@^7.1.2, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4:
semver@7.3.4, semver@^7.1.2, semver@^7.3.4:
version "7.3.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
@@ -12752,6 +12666,11 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.2.1, semver@^7.3.2:
version "7.3.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
send@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
@@ -12798,11 +12717,6 @@ set-cookie-parser@^2.4.6:
resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.6.tgz#43bdea028b9e6f176474ee5298e758b4a44799c3"
integrity sha512-mNCnTUF0OYPwYzSHbdRdCfNNHqrne+HS5tS5xNb6yJbdP9wInV0q5xPLE0EyfV/Q3tImo3y/OXpD8Jn0Jtnjrg==
set-harmonic-interval@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249"
integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==
set-value@^2.0.0, set-value@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
@@ -13077,11 +12991,6 @@ source-map-url@^0.4.0:
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
source-map@0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
integrity sha1-dc449SvwczxafwwRjYEzSiu19BI=
source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
@@ -13104,11 +13013,6 @@ source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
sourcemap-codec@^1.4.8:
version "1.4.8"
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
spawn-error-forwarder@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz#1afd94738e999b0346d7b9fc373be55e07577029"
@@ -13220,40 +13124,11 @@ stable@^0.1.8:
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
stack-generator@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36"
integrity sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==
dependencies:
stackframe "^1.1.1"
stack-trace@0.0.x:
version "0.0.10"
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
stackframe@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303"
integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==
stacktrace-gps@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz#7688dc2fc09ffb3a13165ebe0dbcaf41bcf0c69a"
integrity sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg==
dependencies:
source-map "0.5.6"
stackframe "^1.1.1"
stacktrace-js@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b"
integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==
dependencies:
error-stack-parser "^2.0.6"
stack-generator "^2.0.5"
stacktrace-gps "^3.0.4"
stacktrace-parser@0.1.10:
version "0.1.10"
resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a"
@@ -13553,11 +13428,6 @@ stylis@3.5.4:
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==
stylis@^4.0.6:
version "4.0.7"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.7.tgz#412a90c28079417f3d27c028035095e4232d2904"
integrity sha512-OFFeUXFgwnGOKvEXaSv0D0KQ5ADP0n6g3SVONx6I/85JzNZ3u50FRwB3lVIk1QO2HNdI75tbVzc4Z66Gdp9voA==
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -13819,11 +13689,6 @@ thenify-all@^1.0.0:
dependencies:
any-promise "^1.0.0"
throttle-debounce@^2.1.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz#fd31865e66502071e411817e241465b3e9c372e2"
integrity sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==
through2@^2.0.0, through2@^2.0.1, through2@^2.0.2, through2@~2.0.0:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@@ -14010,11 +13875,6 @@ trough@^1.0.0:
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
ts-easing@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec"
integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==
ts-node@^9.1.1:
version "9.1.1"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
@@ -14037,16 +13897,16 @@ tslib@^1.10.0, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.0.0, tslib@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
tslib@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.2.tgz#462295631185db44b21b1ea3615b63cd1c038242"
integrity sha512-wAH28hcEKwna96/UacuWaVspVLkg4x1aDM9JlzqaQTOFczCktkVAb5fmXChgandR1EraDPs2w8P+ozM+oafwxg==
tslib@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
tsscmp@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"