feat(requests): add request quotas (#1277)

* feat(quotas): rebased

* feat: add getQuota() method to User entity

* feat(ui): add default quota setting options

* feat: user quota settings

* feat: quota display in request modals

* fix: only show user quotas on own profile or with manage users permission

* feat: add request progress circles to profile page

* feat: add migration

* fix: add missing restricted field to api schema

* fix: dont show auto approve message for movie request when restricted

* fix(lang): change enable checkbox langauge to "enable override"

Co-authored-by: Jakob Ankarhem <jakob.ankarhem@outlook.com>
Co-authored-by: TheCatLady <52870424+TheCatLady@users.noreply.github.com>
This commit is contained in:
sct
2021-03-24 19:26:13 +09:00
committed by GitHub
parent a65e3d5bb6
commit 6c75c88228
24 changed files with 1212 additions and 145 deletions

View File

@@ -1,15 +1,16 @@
import React from 'react';
import useSWR from 'swr';
import LoadingSpinner from '../../Common/LoadingSpinner';
import type { MainSettings } from '../../../../server/lib/settings';
import { Form, Formik, Field } from 'formik';
import axios from 'axios';
import Button from '../../Common/Button';
import { Field, Form, Formik } from 'formik';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import PermissionEdit from '../../PermissionEdit';
import PageTitle from '../../Common/PageTitle';
import useSWR from 'swr';
import type { MainSettings } from '../../../../server/lib/settings';
import globalMessages from '../../../i18n/globalMessages';
import Button from '../../Common/Button';
import LoadingSpinner from '../../Common/LoadingSpinner';
import PageTitle from '../../Common/PageTitle';
import PermissionEdit from '../../PermissionEdit';
import QuotaSelector from '../../QuotaSelector';
const messages = defineMessages({
users: 'Users',
@@ -19,8 +20,12 @@ const messages = defineMessages({
saving: 'Saving…',
toastSettingsSuccess: 'User settings saved successfully!',
toastSettingsFailure: 'Something went wrong while saving settings.',
localLogin: 'Enable Local User Sign-In',
defaultPermissions: 'Default User Permissions',
localLogin: 'Enable Local Sign-In',
movieRequestLimitLabel: 'Global Movie Request Limit',
movieRequestLimit: '{quotaLimit} movies per {quotaDays} days',
tvRequestLimitLabel: 'Global Series Request Limit',
tvRequestLimit: '{quotaLimit} seasons per {quotaDays} days',
defaultPermissions: 'Default Permissions',
});
const SettingsUsers: React.FC = () => {
@@ -52,6 +57,10 @@ const SettingsUsers: React.FC = () => {
<Formik
initialValues={{
localLogin: data?.localLogin,
movieQuotaLimit: data?.defaultQuotas.movie.quotaLimit ?? 0,
movieQuotaDays: data?.defaultQuotas.movie.quotaDays ?? 7,
tvQuotaLimit: data?.defaultQuotas.tv.quotaLimit ?? 0,
tvQuotaDays: data?.defaultQuotas.tv.quotaDays ?? 7,
defaultPermissions: data?.defaultPermissions ?? 0,
}}
enableReinitialize
@@ -59,6 +68,16 @@ const SettingsUsers: React.FC = () => {
try {
await axios.post('/api/v1/settings/main', {
localLogin: values.localLogin,
defaultQuotas: {
movie: {
quotaLimit: values.movieQuotaLimit,
quotaDays: values.movieQuotaDays,
},
tv: {
quotaLimit: values.tvQuotaLimit,
quotaDays: values.tvQuotaDays,
},
},
defaultPermissions: values.defaultPermissions,
});
@@ -94,6 +113,36 @@ const SettingsUsers: React.FC = () => {
/>
</div>
</div>
<div className="form-row">
<label htmlFor="applicationTitle" className="text-label">
{intl.formatMessage(messages.movieRequestLimitLabel)}
</label>
<div className="form-input">
<QuotaSelector
onChange={setFieldValue}
dayFieldName="movieQuotaDays"
limitFieldName="movieQuotaLimit"
mediaType="movie"
defaultDays={values.movieQuotaDays}
defaultLimit={values.movieQuotaLimit}
/>
</div>
</div>
<div className="form-row">
<label htmlFor="applicationTitle" className="text-label">
{intl.formatMessage(messages.tvRequestLimitLabel)}
</label>
<div className="form-input">
<QuotaSelector
onChange={setFieldValue}
dayFieldName="tvQuotaDays"
limitFieldName="tvQuotaLimit"
mediaType="tv"
defaultDays={values.tvQuotaDays}
defaultLimit={values.tvQuotaLimit}
/>
</div>
</div>
<div
role="group"
aria-labelledby="group-label"