diff --git a/package.json b/package.json index 3e3aba30..2c25865a 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "license": "MIT", "dependencies": { "@headlessui/react": "^1.0.0", + "@heroicons/react": "^1.0.1", "@supercharge/request-ip": "^1.1.2", "@svgr/webpack": "^5.5.0", "@tanem/react-nprogress": "^3.0.62", diff --git a/src/assets/available.svg b/src/assets/available.svg deleted file mode 100644 index 87b9bdeb..00000000 --- a/src/assets/available.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/bolt.svg b/src/assets/bolt.svg deleted file mode 100644 index d83a0d8a..00000000 --- a/src/assets/bolt.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/download.svg b/src/assets/download.svg deleted file mode 100644 index 4dd0492b..00000000 --- a/src/assets/download.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/requested.svg b/src/assets/requested.svg deleted file mode 100644 index 825678d0..00000000 --- a/src/assets/requested.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/unavailable.svg b/src/assets/unavailable.svg deleted file mode 100644 index d9474805..00000000 --- a/src/assets/unavailable.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/useradd.svg b/src/assets/useradd.svg deleted file mode 100644 index 1c6055ec..00000000 --- a/src/assets/useradd.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/xcircle.svg b/src/assets/xcircle.svg deleted file mode 100644 index 7a7b4533..00000000 --- a/src/assets/xcircle.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/CollectionDetails/index.tsx b/src/components/CollectionDetails/index.tsx index 93447749..ea4f52b3 100644 --- a/src/components/CollectionDetails/index.tsx +++ b/src/components/CollectionDetails/index.tsx @@ -1,3 +1,4 @@ +import { DownloadIcon, DuplicateIcon } from '@heroicons/react/outline'; import axios from 'axios'; import { uniq } from 'lodash'; import Link from 'next/link'; @@ -248,22 +249,7 @@ const CollectionDetails: React.FC = ({ title={intl.formatMessage( is4k ? messages.requestcollection4k : messages.requestcollection )} - iconSvg={ - - - - } + iconSvg={} >

{intl.formatMessage( @@ -355,20 +341,7 @@ const CollectionDetails: React.FC = ({ }} text={ <> - - - + {intl.formatMessage( hasRequestable @@ -393,20 +366,7 @@ const CollectionDetails: React.FC = ({ setIs4k(true); }} > - - - + {intl.formatMessage(messages.requestcollection4k)} diff --git a/src/components/Common/Alert/index.tsx b/src/components/Common/Alert/index.tsx index b29513cc..9f62131a 100644 --- a/src/components/Common/Alert/index.tsx +++ b/src/components/Common/Alert/index.tsx @@ -1,3 +1,8 @@ +import { + ExclamationIcon, + InformationCircleIcon, + XCircleIcon, +} from '@heroicons/react/solid'; import React from 'react'; interface AlertProps { @@ -10,21 +15,7 @@ const Alert: React.FC = ({ title, children, type }) => { bgColor: 'bg-yellow-600', titleColor: 'text-yellow-200', textColor: 'text-yellow-300', - svg: ( - - ), + svg: , }; switch (type) { @@ -33,22 +24,7 @@ const Alert: React.FC = ({ title, children, type }) => { bgColor: 'bg-indigo-600', titleColor: 'text-indigo-200', textColor: 'text-indigo-300', - svg: ( - - - - ), + svg: , }; break; case 'error': @@ -56,22 +32,7 @@ const Alert: React.FC = ({ title, children, type }) => { bgColor: 'bg-red-600', titleColor: 'text-red-200', textColor: 'text-red-300', - svg: ( - - - - ), + svg: , }; break; } diff --git a/src/components/Common/ButtonWithDropdown/index.tsx b/src/components/Common/ButtonWithDropdown/index.tsx index d429e114..65a8c741 100644 --- a/src/components/Common/ButtonWithDropdown/index.tsx +++ b/src/components/Common/ButtonWithDropdown/index.tsx @@ -1,13 +1,14 @@ +import { ChevronDownIcon } from '@heroicons/react/solid'; import React, { - useState, - useRef, AnchorHTMLAttributes, - ReactNode, ButtonHTMLAttributes, + ReactNode, + useRef, + useState, } from 'react'; import useClickOutside from '../../../hooks/useClickOutside'; -import Transition from '../../Transition'; import { withProperties } from '../../../utils/typeHelpers'; +import Transition from '../../Transition'; interface DropdownItemProps extends AnchorHTMLAttributes { buttonType?: 'primary' | 'ghost'; @@ -102,18 +103,7 @@ const ButtonWithDropdown: React.FC = ({ {dropdownIcon ? ( dropdownIcon ) : ( - - - + )} = ({ links }) => { buttonType="ghost" text={ <> - - - - + {links[0].text} } diff --git a/src/components/Common/SlideOver/index.tsx b/src/components/Common/SlideOver/index.tsx index 79a9a0bb..4dac751a 100644 --- a/src/components/Common/SlideOver/index.tsx +++ b/src/components/Common/SlideOver/index.tsx @@ -1,4 +1,5 @@ /* eslint-disable jsx-a11y/click-events-have-key-events */ +import { XIcon } from '@heroicons/react/outline'; import React, { useEffect, useRef, useState } from 'react'; import ReactDOM from 'react-dom'; import { useLockBodyScroll } from '../../../hooks/useLockBodyScroll'; @@ -81,20 +82,7 @@ const SlideOver: React.FC = ({ className="text-indigo-200 transition duration-150 ease-in-out hover:text-white" onClick={() => onClose()} > - - - + diff --git a/src/components/Discover/MovieGenreSlider/index.tsx b/src/components/Discover/MovieGenreSlider/index.tsx index 6ebbed11..56abf7d9 100644 --- a/src/components/Discover/MovieGenreSlider/index.tsx +++ b/src/components/Discover/MovieGenreSlider/index.tsx @@ -1,12 +1,13 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; +import Link from 'next/link'; import React, { useContext } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; -import GenreCard from '../../GenreCard'; -import Slider from '../../Slider'; import { GenreSliderItem } from '../../../../server/interfaces/api/discoverInterfaces'; import { LanguageContext } from '../../../context/LanguageContext'; +import GenreCard from '../../GenreCard'; +import Slider from '../../Slider'; import { genreColorMap } from '../constants'; -import Link from 'next/link'; const messages = defineMessages({ moviegenres: 'Movie Genres', @@ -29,20 +30,7 @@ const MovieGenreSlider: React.FC = () => { {intl.formatMessage(messages.moviegenres)} - - - + diff --git a/src/components/Discover/TvGenreSlider/index.tsx b/src/components/Discover/TvGenreSlider/index.tsx index 20b1b1e2..37f1ee18 100644 --- a/src/components/Discover/TvGenreSlider/index.tsx +++ b/src/components/Discover/TvGenreSlider/index.tsx @@ -1,12 +1,13 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; +import Link from 'next/link'; import React, { useContext } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; -import GenreCard from '../../GenreCard'; -import Slider from '../../Slider'; import { GenreSliderItem } from '../../../../server/interfaces/api/discoverInterfaces'; import { LanguageContext } from '../../../context/LanguageContext'; +import GenreCard from '../../GenreCard'; +import Slider from '../../Slider'; import { genreColorMap } from '../constants'; -import Link from 'next/link'; const messages = defineMessages({ tvgenres: 'Series Genres', @@ -29,20 +30,7 @@ const TvGenreSlider: React.FC = () => { {intl.formatMessage(messages.tvgenres)} - - - + diff --git a/src/components/Discover/index.tsx b/src/components/Discover/index.tsx index 8560a535..bb80d08b 100644 --- a/src/components/Discover/index.tsx +++ b/src/components/Discover/index.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import Link from 'next/link'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -66,20 +67,7 @@ const Discover: React.FC = () => { {intl.formatMessage(messages.recentrequests)} - - - + diff --git a/src/components/Layout/LanguagePicker/index.tsx b/src/components/Layout/LanguagePicker/index.tsx index 25111f30..683fe5f4 100644 --- a/src/components/Layout/LanguagePicker/index.tsx +++ b/src/components/Layout/LanguagePicker/index.tsx @@ -1,3 +1,4 @@ +import { TranslateIcon } from '@heroicons/react/solid'; import React, { useContext, useRef, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { @@ -100,18 +101,7 @@ const LanguagePicker: React.FC = () => { aria-label="Language Picker" onClick={() => setDropdownOpen(true)} > - - - + { @@ -6,19 +7,7 @@ const Notifications: React.FC = () => { className="p-1 text-gray-400 rounded-full hover:bg-gray-500 hover:text-white focus:outline-none focus:ring focus:text-white" aria-label="Notifications" > - - - + ); }; diff --git a/src/components/Layout/SearchInput/index.tsx b/src/components/Layout/SearchInput/index.tsx index 9d0aa634..9042ef45 100644 --- a/src/components/Layout/SearchInput/index.tsx +++ b/src/components/Layout/SearchInput/index.tsx @@ -1,7 +1,8 @@ +import { XCircleIcon } from '@heroicons/react/outline'; +import { SearchIcon } from '@heroicons/react/solid'; import React from 'react'; -import useSearchInput from '../../../hooks/useSearchInput'; import { defineMessages, useIntl } from 'react-intl'; -import ClearButton from '../../../assets/xcircle.svg'; +import useSearchInput from '../../../hooks/useSearchInput'; const messages = defineMessages({ searchPlaceholder: 'Search Movies & TV', @@ -18,13 +19,7 @@ const SearchInput: React.FC = () => {

- - - +
{ className="absolute inset-y-0 p-1 m-auto text-gray-400 transition border-none outline-none right-2 h-7 w-7 focus:outline-none focus:border-none hover:text-white" onClick={() => clear()} > - + )}
diff --git a/src/components/Layout/Sidebar/index.tsx b/src/components/Layout/Sidebar/index.tsx index 7558b95b..dbd15625 100644 --- a/src/components/Layout/Sidebar/index.tsx +++ b/src/components/Layout/Sidebar/index.tsx @@ -1,3 +1,10 @@ +import { + ClockIcon, + CogIcon, + SparklesIcon, + XIcon, +} from '@heroicons/react/outline'; +import { UsersIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { ReactNode, useRef } from 'react'; @@ -33,20 +40,7 @@ const SidebarLinks: SidebarLinkProps[] = [ href: '/', messagesKey: 'dashboard', svgIcon: ( - - - + ), activeRegExp: /^\/(discover\/?(movies|tv)?)?$/, }, @@ -54,20 +48,7 @@ const SidebarLinks: SidebarLinkProps[] = [ href: '/requests', messagesKey: 'requests', svgIcon: ( - - - + ), activeRegExp: /^\/requests/, }, @@ -75,14 +56,7 @@ const SidebarLinks: SidebarLinkProps[] = [ href: '/users', messagesKey: 'users', svgIcon: ( - - - + ), activeRegExp: /^\/users/, requiredPermission: Permission.MANAGE_USERS, @@ -91,26 +65,7 @@ const SidebarLinks: SidebarLinkProps[] = [ href: '/settings', messagesKey: 'settings', svgIcon: ( - - - - + ), activeRegExp: /^\/settings/, requiredPermission: Permission.MANAGE_SETTINGS, @@ -157,19 +112,7 @@ const Sidebar: React.FC = ({ open, setClosed }) => { aria-label="Close sidebar" onClick={() => setClosed()} > - - - + diff --git a/src/components/Layout/VersionStatus/index.tsx b/src/components/Layout/VersionStatus/index.tsx index e5e07869..0a2ac43c 100644 --- a/src/components/Layout/VersionStatus/index.tsx +++ b/src/components/Layout/VersionStatus/index.tsx @@ -1,3 +1,9 @@ +import { + ArrowCircleUpIcon, + BeakerIcon, + CodeIcon, + ServerIcon, +} from '@heroicons/react/outline'; import Link from 'next/link'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -51,50 +57,11 @@ const VersionStatus: React.FC = ({ onClick }) => { }`} > {data.commitTag === 'local' ? ( - - - + ) : data.version.startsWith('develop-') ? ( - - - + ) : ( - - - + )}
{versionStream} @@ -114,22 +81,7 @@ const VersionStatus: React.FC = ({ onClick }) => { )}
- {data.updateAvailable && ( - - - - )} + {data.updateAvailable && } ); diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index 18519734..7ea9ac64 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -1,3 +1,5 @@ +import { MenuAlt2Icon } from '@heroicons/react/outline'; +import { InformationCircleIcon } from '@heroicons/react/solid'; import { useRouter } from 'next/router'; import React, { useEffect, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -57,19 +59,7 @@ const Layout: React.FC = ({ children }) => { aria-label="Open sidebar" onClick={() => setSidebarOpen(true)} > - - - +
@@ -87,18 +77,7 @@ const Layout: React.FC = ({ children }) => {
- - - +

diff --git a/src/components/Login/LocalLogin.tsx b/src/components/Login/LocalLogin.tsx index 4216bf4a..1dc6006d 100644 --- a/src/components/Login/LocalLogin.tsx +++ b/src/components/Login/LocalLogin.tsx @@ -1,3 +1,4 @@ +import { LoginIcon, SupportIcon } from '@heroicons/react/outline'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import Link from 'next/link'; @@ -103,6 +104,7 @@ const LocalLogin: React.FC = ({ revalidate }) => { @@ -113,6 +115,7 @@ const LocalLogin: React.FC = ({ revalidate }) => { type="submit" disabled={isSubmitting || !isValid} > + {isSubmitting ? intl.formatMessage(messages.signingin) : intl.formatMessage(messages.signin)} diff --git a/src/components/Login/index.tsx b/src/components/Login/index.tsx index 0474b9da..d877e160 100644 --- a/src/components/Login/index.tsx +++ b/src/components/Login/index.tsx @@ -1,3 +1,4 @@ +import { XCircleIcon } from '@heroicons/react/solid'; import axios from 'axios'; import { useRouter } from 'next/dist/client/router'; import React, { useEffect, useState } from 'react'; @@ -100,19 +101,7 @@ const Login: React.FC = () => {

- +

diff --git a/src/components/MediaSlider/ShowMoreCard/index.tsx b/src/components/MediaSlider/ShowMoreCard/index.tsx index e229ad7e..c4290966 100644 --- a/src/components/MediaSlider/ShowMoreCard/index.tsx +++ b/src/components/MediaSlider/ShowMoreCard/index.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -79,18 +80,7 @@ const ShowMoreCard: React.FC = ({ url, posters }) => { )}

- - - +
{intl.formatMessage(messages.seemore)}
diff --git a/src/components/MediaSlider/index.tsx b/src/components/MediaSlider/index.tsx index c46e16bc..64aa7915 100644 --- a/src/components/MediaSlider/index.tsx +++ b/src/components/MediaSlider/index.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import Link from 'next/link'; import React, { useContext, useEffect } from 'react'; import { useSWRInfinite } from 'swr'; @@ -140,20 +141,7 @@ const MediaSlider: React.FC = ({ {title} - - - + ) : ( diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx index dadd9c1a..baa39a8e 100644 --- a/src/components/MovieDetails/index.tsx +++ b/src/components/MovieDetails/index.tsx @@ -1,3 +1,9 @@ +import { ArrowCircleRightIcon, CogIcon } from '@heroicons/react/outline'; +import { + CheckCircleIcon, + DocumentRemoveIcon, + ExternalLinkIcon, +} from '@heroicons/react/solid'; import axios from 'axios'; import Link from 'next/link'; import { useRouter } from 'next/router'; @@ -50,7 +56,7 @@ const messages = defineMessages({ manageModalTitle: 'Manage Movie', manageModalRequests: 'Requests', manageModalNoRequests: 'No requests.', - manageModalClearMedia: 'Clear All Media Data', + manageModalClearMedia: 'Clear Media Data', manageModalClearMediaWarning: '* This will irreversibly remove all data for this movie, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.', studio: '{studioCount, plural, one {Studio} other {Studios}}', @@ -266,18 +272,7 @@ const MovieDetails: React.FC = ({ movie }) => { className="w-full sm:mb-0" buttonType="success" > - - - + {intl.formatMessage(messages.markavailable)}
@@ -291,18 +286,7 @@ const MovieDetails: React.FC = ({ movie }) => { className="w-full sm:mb-0" buttonType="success" > - - - + {intl.formatMessage(messages.mark4kavailable)} @@ -341,15 +325,7 @@ const MovieDetails: React.FC = ({ movie }) => { className="block mb-2 last:mb-0" > @@ -361,15 +337,7 @@ const MovieDetails: React.FC = ({ movie }) => { rel="noreferrer" > @@ -383,6 +351,7 @@ const MovieDetails: React.FC = ({ movie }) => { confirmText={intl.formatMessage(globalMessages.areyousure)} className="w-full" > + {intl.formatMessage(messages.manageModalClearMedia)}
@@ -463,27 +432,7 @@ const MovieDetails: React.FC = ({ movie }) => { className="ml-2 first:ml-0" onClick={() => setShowManager(true)} > - - - - + )}
@@ -513,20 +462,7 @@ const MovieDetails: React.FC = ({ movie }) => { {intl.formatMessage(messages.viewfullcrew)} - - - +
@@ -709,20 +645,7 @@ const MovieDetails: React.FC = ({ movie }) => { {intl.formatMessage(messages.cast)} - - - +
diff --git a/src/components/PersonCard/index.tsx b/src/components/PersonCard/index.tsx index 67cdf43f..85e41ff3 100644 --- a/src/components/PersonCard/index.tsx +++ b/src/components/PersonCard/index.tsx @@ -1,3 +1,4 @@ +import { UserCircleIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import React, { useState } from 'react'; import CachedImage from '../Common/CachedImage'; @@ -57,18 +58,7 @@ const PersonCard: React.FC = ({ />
) : ( - - - + )}
{name}
diff --git a/src/components/PlexLoginButton/index.tsx b/src/components/PlexLoginButton/index.tsx index f6bbb5b7..2125f005 100644 --- a/src/components/PlexLoginButton/index.tsx +++ b/src/components/PlexLoginButton/index.tsx @@ -1,3 +1,4 @@ +import { LoginIcon } from '@heroicons/react/outline'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import globalMessages from '../../i18n/globalMessages'; @@ -48,6 +49,7 @@ const PlexLoginButton: React.FC = ({ disabled={loading || isProcessing} className="plex-button" > + {loading ? intl.formatMessage(globalMessages.loading) : isProcessing diff --git a/src/components/RegionSelector/index.tsx b/src/components/RegionSelector/index.tsx index 2cbdc435..dbbae3f9 100644 --- a/src/components/RegionSelector/index.tsx +++ b/src/components/RegionSelector/index.tsx @@ -1,11 +1,12 @@ -import React, { useEffect, useMemo, useState } from 'react'; import { Listbox, Transition } from '@headlessui/react'; +import { CheckIcon, ChevronDownIcon } from '@heroicons/react/solid'; +import { hasFlag } from 'country-flag-icons'; +import 'country-flag-icons/3x2/flags.css'; +import React, { useEffect, useMemo, useState } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; import type { Region } from '../../../server/lib/settings'; -import { defineMessages, useIntl } from 'react-intl'; import useSettings from '../../hooks/useSettings'; -import { hasFlag } from 'country-flag-icons'; -import 'country-flag-icons/3x2/flags.css'; const messages = defineMessages({ regionDefault: 'All Regions', @@ -125,20 +126,7 @@ const RegionSelector: React.FC = ({ : intl.formatMessage(messages.regionDefault)} - - - + @@ -196,18 +184,7 @@ const RegionSelector: React.FC = ({ active ? 'text-white' : 'text-indigo-600' } absolute inset-y-0 left-0 flex items-center pl-1.5`} > - - - + )}
@@ -234,18 +211,7 @@ const RegionSelector: React.FC = ({ active ? 'text-white' : 'text-indigo-600' } absolute inset-y-0 left-0 flex items-center pl-1.5`} > - - - + )}
@@ -286,18 +252,7 @@ const RegionSelector: React.FC = ({ active ? 'text-white' : 'text-indigo-600' } absolute inset-y-0 left-0 flex items-center pl-1.5`} > - - - + )} diff --git a/src/components/RequestBlock/index.tsx b/src/components/RequestBlock/index.tsx index c23370e9..d003bcf7 100644 --- a/src/components/RequestBlock/index.tsx +++ b/src/components/RequestBlock/index.tsx @@ -1,3 +1,12 @@ +import { + CalendarIcon, + CheckIcon, + EyeIcon, + PencilIcon, + TrashIcon, + UserIcon, + XIcon, +} from '@heroicons/react/solid'; import axios from 'axios'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -69,37 +78,14 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => {
- - - + {request.requestedBy.displayName}
{request.modifiedBy && (
- - - - + {request.modifiedBy?.displayName} @@ -115,18 +101,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { onClick={() => updateRequest('approve')} disabled={isUpdating} > - - - + @@ -135,18 +110,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { onClick={() => updateRequest('decline')} disabled={isUpdating} > - - - + @@ -155,14 +119,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { onClick={() => setShowEditModal(true)} disabled={isUpdating} > - - - + @@ -173,18 +130,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { onClick={() => deleteRequest()} disabled={isUpdating} > - - - + )}
@@ -215,18 +161,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => {
- - - + {intl.formatDate(request.createdAt, { year: 'numeric', diff --git a/src/components/RequestButton/index.tsx b/src/components/RequestButton/index.tsx index 2c26c694..c5fef6fd 100644 --- a/src/components/RequestButton/index.tsx +++ b/src/components/RequestButton/index.tsx @@ -1,3 +1,9 @@ +import { DownloadIcon } from '@heroicons/react/outline'; +import { + CheckIcon, + InformationCircleIcon, + XIcon, +} from '@heroicons/react/solid'; import axios from 'axios'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -117,22 +123,7 @@ const RequestButton: React.FC = ({ action: () => { setShowRequestModal(true); }, - svg: ( - - - - ), + svg: , }); } @@ -150,22 +141,7 @@ const RequestButton: React.FC = ({ action: () => { setShowRequestModal(true); }, - svg: ( - - - - ), + svg: , }); } @@ -183,22 +159,7 @@ const RequestButton: React.FC = ({ action: () => { setShowRequest4kModal(true); }, - svg: ( - - - - ), + svg: , }); } @@ -218,22 +179,7 @@ const RequestButton: React.FC = ({ action: () => { setShowRequest4kModal(true); }, - svg: ( - - - - ), + svg: , }); } @@ -246,20 +192,7 @@ const RequestButton: React.FC = ({ id: 'active-request', text: intl.formatMessage(messages.viewrequest), action: () => setShowRequestModal(true), - svg: ( - - - - ), + svg: , }); } @@ -273,20 +206,7 @@ const RequestButton: React.FC = ({ id: 'active-4k-request', text: intl.formatMessage(messages.viewrequest4k), action: () => setShowRequest4kModal(true), - svg: ( - - - - ), + svg: , }); } @@ -302,20 +222,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequest(activeRequest, 'approve'); }, - svg: ( - - - - ), + svg: , }, { id: 'decline-request', @@ -323,20 +230,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequest(activeRequest, 'decline'); }, - svg: ( - - - - ), + svg: , } ); } @@ -356,20 +250,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequests(activeRequests, 'approve'); }, - svg: ( - - - - ), + svg: , }, { id: 'decline-request-batch', @@ -379,20 +260,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequests(activeRequests, 'decline'); }, - svg: ( - - - - ), + svg: , } ); } @@ -409,20 +277,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequest(active4kRequest, 'approve'); }, - svg: ( - - - - ), + svg: , }, { id: 'decline-4k-request', @@ -430,20 +285,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequest(active4kRequest, 'decline'); }, - svg: ( - - - - ), + svg: , } ); } @@ -456,50 +298,24 @@ const RequestButton: React.FC = ({ ) { buttons.push( { - id: 'approve-request-batch', + id: 'approve-4k-request-batch', text: intl.formatMessage(messages.approve4krequests, { requestCount: active4kRequests.length, }), action: () => { modifyRequests(active4kRequests, 'approve'); }, - svg: ( - - - - ), + svg: , }, { - id: 'decline-request-batch', + id: 'decline-4k-request-batch', text: intl.formatMessage(messages.decline4krequests, { requestCount: active4kRequests.length, }), action: () => { modifyRequests(active4kRequests, 'decline'); }, - svg: ( - - - - ), + svg: , } ); } diff --git a/src/components/RequestCard/index.tsx b/src/components/RequestCard/index.tsx index e6baf6b1..7e71813e 100644 --- a/src/components/RequestCard/index.tsx +++ b/src/components/RequestCard/index.tsx @@ -1,3 +1,4 @@ +import { CheckIcon, TrashIcon, XIcon } from '@heroicons/react/solid'; import axios from 'axios'; import Link from 'next/link'; import React, { useContext, useEffect } from 'react'; @@ -68,20 +69,7 @@ const RequestCardError: React.FC = ({ mediaId }) => { buttonSize="sm" onClick={() => deleteRequest()} > - - - + {intl.formatMessage(messages.deleterequest)}
@@ -261,18 +249,7 @@ const RequestCard: React.FC = ({ request, onTitleData }) => { buttonSize="sm" onClick={() => modifyRequest('approve')} > - - - + {intl.formatMessage(globalMessages.approve)} @@ -284,18 +261,7 @@ const RequestCard: React.FC = ({ request, onTitleData }) => { buttonSize="sm" onClick={() => modifyRequest('decline')} > - - - + {intl.formatMessage(globalMessages.decline)} diff --git a/src/components/RequestList/RequestItem/index.tsx b/src/components/RequestList/RequestItem/index.tsx index f9f512c9..13b7c01e 100644 --- a/src/components/RequestList/RequestItem/index.tsx +++ b/src/components/RequestList/RequestItem/index.tsx @@ -1,3 +1,10 @@ +import { + CheckIcon, + PencilIcon, + RefreshIcon, + TrashIcon, + XIcon, +} from '@heroicons/react/solid'; import axios from 'axios'; import Link from 'next/link'; import React, { useContext, useState } from 'react'; @@ -66,20 +73,7 @@ const RequestItemError: React.FC = ({ buttonSize="sm" onClick={() => deleteRequest()} > - - - + {intl.formatMessage(messages.deleterequest)} @@ -377,18 +371,7 @@ const RequestItem: React.FC = ({ confirmText={intl.formatMessage(globalMessages.areyousure)} className="w-full" > - - - + {intl.formatMessage(messages.cancelRequest)} @@ -404,19 +387,14 @@ const RequestItem: React.FC = ({ disabled={isRetrying} onClick={() => retryRequest()} > - - - - + - {intl.formatMessage(globalMessages.retry)} + {intl.formatMessage( + isRetrying ? globalMessages.retrying : globalMessages.retry + )} )} @@ -427,18 +405,7 @@ const RequestItem: React.FC = ({ confirmText={intl.formatMessage(globalMessages.areyousure)} className="w-full" > - - - + {intl.formatMessage(globalMessages.delete)} @@ -454,18 +421,7 @@ const RequestItem: React.FC = ({ buttonType="success" onClick={() => modifyRequest('approve')} > - - - + {intl.formatMessage(globalMessages.approve)} @@ -477,18 +433,7 @@ const RequestItem: React.FC = ({ buttonType="danger" onClick={() => modifyRequest('decline')} > - - - + {intl.formatMessage(globalMessages.decline)} @@ -501,14 +446,7 @@ const RequestItem: React.FC = ({ buttonType="primary" onClick={() => setShowEditModal(true)} > - - - + {intl.formatMessage(globalMessages.edit)} diff --git a/src/components/RequestList/index.tsx b/src/components/RequestList/index.tsx index d0177e64..fd328101 100644 --- a/src/components/RequestList/index.tsx +++ b/src/components/RequestList/index.tsx @@ -1,3 +1,4 @@ +import { FilterIcon, SortDescendingIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { useEffect, useState } from 'react'; @@ -119,18 +120,7 @@ const RequestList: React.FC = () => {
- - - + = ({ return ( <>
- - - - + {intl.formatMessage(messages.advancedoptions)}
@@ -526,19 +523,7 @@ const AdvancedRequester: React.FC = ({ - - - + @@ -592,18 +577,7 @@ const AdvancedRequester: React.FC = ({ : 'text-indigo-600' } absolute inset-y-0 left-0 flex items-center pl-1.5`} > - - - + )}
diff --git a/src/components/RequestModal/MovieRequestModal.tsx b/src/components/RequestModal/MovieRequestModal.tsx index 536dc5a7..c150d242 100644 --- a/src/components/RequestModal/MovieRequestModal.tsx +++ b/src/components/RequestModal/MovieRequestModal.tsx @@ -1,3 +1,4 @@ +import { DownloadIcon } from '@heroicons/react/outline'; import axios from 'axios'; import React, { useCallback, useEffect, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -11,7 +12,6 @@ import { MediaRequest } from '../../../server/entity/MediaRequest'; import { QuotaResponse } from '../../../server/interfaces/api/userInterfaces'; import { Permission } from '../../../server/lib/permissions'; import { MovieDetails } from '../../../server/models/Movie'; -import DownloadIcon from '../../assets/download.svg'; import { useUser } from '../../hooks/useUser'; import globalMessages from '../../i18n/globalMessages'; import Alert from '../Common/Alert'; diff --git a/src/components/RequestModal/QuotaDisplay/index.tsx b/src/components/RequestModal/QuotaDisplay/index.tsx index 5d3decdc..223540d5 100644 --- a/src/components/RequestModal/QuotaDisplay/index.tsx +++ b/src/components/RequestModal/QuotaDisplay/index.tsx @@ -1,3 +1,4 @@ +import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -90,31 +91,9 @@ const QuotaDisplay: React.FC = ({
{showDetails ? ( - - - + ) : ( - - - + )}
diff --git a/src/components/RequestModal/SearchByNameModal/index.tsx b/src/components/RequestModal/SearchByNameModal/index.tsx index 50df0469..111d6137 100644 --- a/src/components/RequestModal/SearchByNameModal/index.tsx +++ b/src/components/RequestModal/SearchByNameModal/index.tsx @@ -1,3 +1,4 @@ +import { DownloadIcon } from '@heroicons/react/outline'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; @@ -51,22 +52,7 @@ const SearchByNameModal: React.FC = ({ okText={intl.formatMessage(globalMessages.next)} okDisabled={!tvdbId} okButtonType="primary" - iconSvg={ - - - - } + iconSvg={} > = ({ ? intl.formatMessage(globalMessages.back) : intl.formatMessage(globalMessages.cancel) } - iconSvg={ - - - - } + iconSvg={} > {hasPermission( [ diff --git a/src/components/ResetPassword/RequestResetLink.tsx b/src/components/ResetPassword/RequestResetLink.tsx index f9359772..74c342fa 100644 --- a/src/components/ResetPassword/RequestResetLink.tsx +++ b/src/components/ResetPassword/RequestResetLink.tsx @@ -1,3 +1,4 @@ +import { AtSymbolIcon } from '@heroicons/react/outline'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import Link from 'next/link'; @@ -123,6 +124,7 @@ const ResetPassword: React.FC = () => { type="submit" disabled={isSubmitting || !isValid} > + {intl.formatMessage(messages.emailresetlink)} diff --git a/src/components/Settings/CopyButton.tsx b/src/components/Settings/CopyButton.tsx index abc5d09d..4ae21190 100644 --- a/src/components/Settings/CopyButton.tsx +++ b/src/components/Settings/CopyButton.tsx @@ -1,7 +1,8 @@ +import { ClipboardCopyIcon } from '@heroicons/react/solid'; import React, { useEffect } from 'react'; -import useClipboard from 'react-use-clipboard'; -import { useToasts } from 'react-toast-notifications'; import { defineMessages, useIntl } from 'react-intl'; +import { useToasts } from 'react-toast-notifications'; +import useClipboard from 'react-use-clipboard'; const messages = defineMessages({ copied: 'Copied API key to clipboard.', @@ -29,17 +30,9 @@ const CopyButton: React.FC<{ textToCopy: string }> = ({ textToCopy }) => { e.preventDefault(); setCopied(); }} - className="-ml-px relative inline-flex items-center px-4 py-2 border border-gray-500 text-sm leading-5 font-medium text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150" + className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700" > - - - - + ); }; diff --git a/src/components/Settings/LibraryItem.tsx b/src/components/Settings/LibraryItem.tsx index d7586454..a1accde4 100644 --- a/src/components/Settings/LibraryItem.tsx +++ b/src/components/Settings/LibraryItem.tsx @@ -1,3 +1,4 @@ +import { CheckIcon, XIcon } from '@heroicons/react/solid'; import React from 'react'; interface LibraryItemProps { @@ -12,8 +13,8 @@ const LibraryItem: React.FC = ({ onToggle, }) => { return ( -
  • -
    +
  • +
    {name}
    @@ -45,19 +46,7 @@ const LibraryItem: React.FC = ({ : 'opacity-100 ease-in duration-200' } absolute inset-0 h-full w-full flex items-center justify-center transition-opacity`} > - - - + = ({ : 'opacity-0 ease-out duration-100' } absolute inset-0 h-full w-full flex items-center justify-center transition-opacity`} > - - - + diff --git a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx index 5ad3bacf..8b6dffad 100644 --- a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx +++ b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx @@ -1,3 +1,4 @@ +import { QuestionMarkCircleIcon, RefreshIcon } from '@heroicons/react/solid'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import dynamic from 'next/dynamic'; @@ -232,18 +233,7 @@ const NotificationsWebhook: React.FC = () => { }} className="mr-2" > - - - + {intl.formatMessage(messages.resetPayload)} { rel="noreferrer" className="inline-flex items-center justify-center font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-transparent rounded-md focus:outline-none hover:bg-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-indigo-700 disabled:opacity-50 px-2.5 py-1.5 text-xs" > - - - + {intl.formatMessage(messages.templatevariablehelp)}
    diff --git a/src/components/Settings/RadarrModal/index.tsx b/src/components/Settings/RadarrModal/index.tsx index bf3b0f20..8ea9093a 100644 --- a/src/components/Settings/RadarrModal/index.tsx +++ b/src/components/Settings/RadarrModal/index.tsx @@ -1,3 +1,4 @@ +import { PencilIcon, PlusIcon } from '@heroicons/react/solid'; import axios from 'axios'; import { Field, Formik } from 'formik'; import dynamic from 'next/dynamic'; @@ -356,6 +357,13 @@ const RadarrModal: React.FC = ({ values.is4k ? messages.edit4kradarr : messages.editradarr ) } + iconSvg={ + !radarr ? ( + + ) : ( + + ) + } >
    diff --git a/src/components/Settings/SettingsAbout/Releases/index.tsx b/src/components/Settings/SettingsAbout/Releases/index.tsx index 1230185e..49a0c88b 100644 --- a/src/components/Settings/SettingsAbout/Releases/index.tsx +++ b/src/components/Settings/SettingsAbout/Releases/index.tsx @@ -1,3 +1,4 @@ +import { DocumentTextIcon } from '@heroicons/react/outline'; import React, { useState } from 'react'; import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl'; import ReactMarkdown from 'react-markdown'; @@ -70,22 +71,7 @@ const Release: React.FC = ({ > setModalOpen(false)} - iconSvg={ - - - - } + iconSvg={} title={intl.formatMessage(messages.versionChangelog)} cancelText={intl.formatMessage(globalMessages.close)} okText={intl.formatMessage(messages.viewongithub)} @@ -126,6 +112,7 @@ const Release: React.FC = ({
    diff --git a/src/components/Settings/SettingsJobsCache/index.tsx b/src/components/Settings/SettingsJobsCache/index.tsx index 46d0cd9d..ffd3446f 100644 --- a/src/components/Settings/SettingsJobsCache/index.tsx +++ b/src/components/Settings/SettingsJobsCache/index.tsx @@ -1,3 +1,4 @@ +import { PlayIcon, StopIcon, XCircleIcon } from '@heroicons/react/solid'; import axios from 'axios'; import React from 'react'; import { @@ -146,12 +147,12 @@ const SettingsJobs: React.FC = () => {
    - {job.running && } {intl.formatMessage( messages[job.id] ?? messages.unknownJob )} + {job.running && }
    @@ -180,10 +181,12 @@ const SettingsJobs: React.FC = () => { {job.running ? ( ) : ( )} @@ -223,6 +226,7 @@ const SettingsJobs: React.FC = () => { {formatBytes(cache.stats.vsize)} diff --git a/src/components/Settings/SettingsLogs/index.tsx b/src/components/Settings/SettingsLogs/index.tsx index fe1845c2..a4aaf755 100644 --- a/src/components/Settings/SettingsLogs/index.tsx +++ b/src/components/Settings/SettingsLogs/index.tsx @@ -1,3 +1,10 @@ +import { + ClipboardCopyIcon, + DocumentSearchIcon, + FilterIcon, + PauseIcon, + PlayIcon, +} from '@heroicons/react/solid'; import copy from 'copy-to-clipboard'; import { useRouter } from 'next/router'; import React, { useEffect, useState } from 'react'; @@ -135,6 +142,7 @@ const SettingsLogs: React.FC = () => { > } onCancel={() => setActiveLog(null)} cancelText={intl.formatMessage(globalMessages.close)} onOk={() => (activeLog ? copyLogString(activeLog) : undefined)} @@ -237,31 +245,9 @@ const SettingsLogs: React.FC = () => { > {refreshInterval ? ( - - - + ) : ( - - - + )} @@ -273,18 +259,7 @@ const SettingsLogs: React.FC = () => {
    - - - + { onClick={() => setShowBulkEditModal(true)} disabled={selectedUsers.length === 0} > + {intl.formatMessage(messages.bulkedit)} )} diff --git a/src/components/UserProfile/ProfileHeader/index.tsx b/src/components/UserProfile/ProfileHeader/index.tsx index 774935a7..a7f26f4c 100644 --- a/src/components/UserProfile/ProfileHeader/index.tsx +++ b/src/components/UserProfile/ProfileHeader/index.tsx @@ -1,3 +1,4 @@ +import { CogIcon, UserIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -92,18 +93,7 @@ const ProfileHeader: React.FC = ({ passHref > @@ -116,18 +106,7 @@ const ProfileHeader: React.FC = ({ passHref > diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx index b52db481..e0d68421 100644 --- a/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx +++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx @@ -1,3 +1,4 @@ +import { AtSymbolIcon } from '@heroicons/react/outline'; import { useRouter } from 'next/router'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -33,20 +34,7 @@ const UserNotificationSettings: React.FC = ({ children }) => { text: intl.formatMessage(messages.email), content: ( - - - + {intl.formatMessage(messages.email)} ), diff --git a/src/components/UserProfile/index.tsx b/src/components/UserProfile/index.tsx index f9a6d311..e4dd601d 100644 --- a/src/components/UserProfile/index.tsx +++ b/src/components/UserProfile/index.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { useCallback, useEffect, useState } from 'react'; @@ -236,20 +237,7 @@ const UserProfile: React.FC = () => { {intl.formatMessage(messages.recentrequests)} - - - +
    diff --git a/src/i18n/globalMessages.ts b/src/i18n/globalMessages.ts index 884acc4a..58d260e7 100644 --- a/src/i18n/globalMessages.ts +++ b/src/i18n/globalMessages.ts @@ -24,6 +24,7 @@ const globalMessages = defineMessages({ decline: 'Decline', delete: 'Delete', retry: 'Retry', + retrying: 'Retrying…', view: 'View', deleting: 'Deleting…', test: 'Test', diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 60c7ce3e..629deec2 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -64,7 +64,7 @@ "components.MovieDetails.budget": "Budget", "components.MovieDetails.cast": "Cast", "components.MovieDetails.downloadstatus": "Download Status", - "components.MovieDetails.manageModalClearMedia": "Clear All Media Data", + "components.MovieDetails.manageModalClearMedia": "Clear Media Data", "components.MovieDetails.manageModalClearMediaWarning": "* This will irreversibly remove all data for this movie, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.", "components.MovieDetails.manageModalNoRequests": "No requests.", "components.MovieDetails.manageModalRequests": "Requests", @@ -620,7 +620,7 @@ "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.manageModalClearMedia": "Clear 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.", "components.TvDetails.manageModalNoRequests": "No requests.", "components.TvDetails.manageModalRequests": "Requests", @@ -799,6 +799,7 @@ "i18n.requesting": "Requesting…", "i18n.resultsperpage": "Display {pageSize} results per page", "i18n.retry": "Retry", + "i18n.retrying": "Retrying…", "i18n.save": "Save Changes", "i18n.saving": "Saving…", "i18n.settings": "Settings", diff --git a/src/pages/404.tsx b/src/pages/404.tsx index 900f17af..da750750 100644 --- a/src/pages/404.tsx +++ b/src/pages/404.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import Link from 'next/link'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -22,22 +23,9 @@ const Custom404: React.FC = () => { })} - + {intl.formatMessage(messages.returnHome)} - - - + diff --git a/src/pages/_error.tsx b/src/pages/_error.tsx index bb24b57f..c1960638 100644 --- a/src/pages/_error.tsx +++ b/src/pages/_error.tsx @@ -1,9 +1,10 @@ -import React from 'react'; +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import type { NextPage } from 'next'; import Link from 'next/link'; -import type { Undefinable } from '../utils/typeHelpers'; +import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import PageTitle from '../components/Common/PageTitle'; +import type { Undefinable } from '../utils/typeHelpers'; interface ErrorProps { statusCode?: number; @@ -45,22 +46,9 @@ const Error: NextPage = ({ statusCode }) => { : getErrorMessage(statusCode)} - + {intl.formatMessage(messages.returnHome)} - - - + diff --git a/yarn.lock b/yarn.lock index 91f368f1..333bc243 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1533,6 +1533,11 @@ resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.0.0.tgz#661b50ebfd25041abb45d8eedd85e7559056bcaf" integrity sha512-mjqRJrgkbcHQBfAHnqH0yRxO/y/22jYrdltpE7WkurafREKZ+pj5bPBwYHMt935Sdz/n16yRcVmsSCqDFHee9A== +"@heroicons/react@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.1.tgz#66d25f6441920bd5c2146ea27fd33995885452dd" + integrity sha512-uikw2gKCmqnvjVxitecWfFLMOKyL9BTFcU4VM3hHj9OMwpkCr5Ke+MRMyY2/aQVmsYs4VTq7NCFX05MYwAHi3g== + "@iarna/cli@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@iarna/cli/-/cli-1.2.0.tgz#0f7af5e851afe895104583c4ca07377a8094d641"