Further work on typescript migration
This commit is contained in:
parent
c5d2f3dc8b
commit
f4e65eb58e
|
@ -68,7 +68,8 @@
|
||||||
"husky": "^6.0.0",
|
"husky": "^6.0.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"lint-staged": "^10.5.4",
|
"lint-staged": "^10.5.4",
|
||||||
"prettier": "^2.2.1"
|
"prettier": "^2.2.1",
|
||||||
|
"tsc-files": "^1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@apollo/client": {
|
"node_modules/@apollo/client": {
|
||||||
|
@ -13373,6 +13374,18 @@
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
|
||||||
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/tsc-files": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsc-files/-/tsc-files-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-biLtl4npoohZ9MBnTFw4NttqYM60RscjzjWxT538UCS8iXaGRZMi+AXj+vEEpDdcjIS2Kx0Acj++1gor5dbbBw==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"tsc-files": "lib/index.js"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": ">=3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "1.13.0",
|
"version": "1.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
||||||
|
@ -24801,6 +24814,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tsc-files": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsc-files/-/tsc-files-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-biLtl4npoohZ9MBnTFw4NttqYM60RscjzjWxT538UCS8iXaGRZMi+AXj+vEEpDdcjIS2Kx0Acj++1gor5dbbBw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "1.13.0",
|
"version": "1.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
||||||
|
|
|
@ -57,7 +57,9 @@
|
||||||
"start": "node --experimental-modules build.mjs watch",
|
"start": "node --experimental-modules build.mjs watch",
|
||||||
"build": "NODE_ENV=production node --experimental-modules build.mjs",
|
"build": "NODE_ENV=production node --experimental-modules build.mjs",
|
||||||
"test": "npm run lint && npm run jest",
|
"test": "npm run lint && npm run jest",
|
||||||
"lint": "eslint ./src --max-warnings 0 --cache --config .eslintrc.js",
|
"lint": "npm run lint:types & npm run lint:eslint",
|
||||||
|
"lint:eslint": "eslint ./src --max-warnings 0 --cache --config .eslintrc.js",
|
||||||
|
"lint:types": "tsc --noemit",
|
||||||
"jest": "jest",
|
"jest": "jest",
|
||||||
"genSchemaTypes": "npx apollo client:codegen --target=typescript",
|
"genSchemaTypes": "npx apollo client:codegen --target=typescript",
|
||||||
"prepare": "(cd .. && npx husky install)"
|
"prepare": "(cd .. && npx husky install)"
|
||||||
|
@ -77,7 +79,8 @@
|
||||||
"husky": "^6.0.0",
|
"husky": "^6.0.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"lint-staged": "^10.5.4",
|
"lint-staged": "^10.5.4",
|
||||||
"prettier": "^2.2.1"
|
"prettier": "^2.2.1",
|
||||||
|
"tsc-files": "^1.1.2"
|
||||||
},
|
},
|
||||||
"cache": {
|
"cache": {
|
||||||
"swDest": "service-worker.js"
|
"swDest": "service-worker.js"
|
||||||
|
@ -99,7 +102,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,json,css,md,graphql}": "prettier --write",
|
"*.{ts,tsx,js,json,css,md,graphql}": "prettier --write",
|
||||||
"*.js": "eslint --cache --fix --max-warnings 0"
|
"*.{js,ts,tsx}": "eslint --cache --fix --max-warnings 0",
|
||||||
|
"*.{ts,tsx}": "tsc-files --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { ProtectedImage } from '../photoGallery/ProtectedMedia'
|
import { ProtectedImage } from '../photoGallery/ProtectedMedia'
|
||||||
|
@ -28,7 +27,7 @@ const Image = styled(ProtectedImage)`
|
||||||
object-position: center;
|
object-position: center;
|
||||||
`
|
`
|
||||||
|
|
||||||
const Placeholder = styled.div`
|
const Placeholder = styled.div<{ overlap?: boolean; loaded?: boolean }>`
|
||||||
width: 220px;
|
width: 220px;
|
||||||
height: 220px;
|
height: 220px;
|
||||||
border-radius: 4%;
|
border-radius: 4%;
|
||||||
|
@ -47,14 +46,18 @@ const Placeholder = styled.div`
|
||||||
`}
|
`}
|
||||||
`
|
`
|
||||||
|
|
||||||
const AlbumBoxImage = ({ src, ...props }) => {
|
interface AlbumBoxImageProps {
|
||||||
|
src?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const AlbumBoxImage = ({ src, ...props }: AlbumBoxImageProps) => {
|
||||||
const [loaded, setLoaded] = useState(false)
|
const [loaded, setLoaded] = useState(false)
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
return (
|
return (
|
||||||
<ImageWrapper>
|
<ImageWrapper>
|
||||||
<Image {...props} onLoad={loaded => setLoaded(loaded)} src={src} />
|
<Image {...props} onLoad={() => setLoaded(true)} src={src} />
|
||||||
<Placeholder overlap loaded={loaded ? 1 : 0} />
|
<Placeholder overlap loaded={loaded} />
|
||||||
</ImageWrapper>
|
</ImageWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -62,11 +65,16 @@ const AlbumBoxImage = ({ src, ...props }) => {
|
||||||
return <Placeholder />
|
return <Placeholder />
|
||||||
}
|
}
|
||||||
|
|
||||||
AlbumBoxImage.propTypes = {
|
type AlbumBoxProps = {
|
||||||
src: PropTypes.string,
|
album?: {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
thumbnail?: { thumbnail?: { url: string } }
|
||||||
|
}
|
||||||
|
customLink?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AlbumBox = ({ album, customLink, ...props }) => {
|
export const AlbumBox = ({ album, customLink, ...props }: AlbumBoxProps) => {
|
||||||
if (!album) {
|
if (!album) {
|
||||||
return (
|
return (
|
||||||
<AlbumBoxLink {...props} to="#">
|
<AlbumBoxLink {...props} to="#">
|
||||||
|
@ -75,7 +83,7 @@ export const AlbumBox = ({ album, customLink, ...props }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let thumbnail = album.thumbnail?.thumbnail?.url
|
const thumbnail = album.thumbnail?.thumbnail?.url
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AlbumBoxLink {...props} to={customLink || `/album/${album.id}`}>
|
<AlbumBoxLink {...props} to={customLink || `/album/${album.id}`}>
|
||||||
|
@ -84,8 +92,3 @@ export const AlbumBox = ({ album, customLink, ...props }) => {
|
||||||
</AlbumBoxLink>
|
</AlbumBoxLink>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
AlbumBox.propTypes = {
|
|
||||||
album: PropTypes.object,
|
|
||||||
customLink: PropTypes.string,
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ import { useSubscription, gql } from '@apollo/client'
|
||||||
import { authToken } from '../../helpers/authentication'
|
import { authToken } from '../../helpers/authentication'
|
||||||
import { NotificationType } from '../../../__generated__/globalTypes'
|
import { NotificationType } from '../../../__generated__/globalTypes'
|
||||||
|
|
||||||
const notificationSubscription = gql`
|
const NOTIFICATION_SUBSCRIPTION = gql`
|
||||||
subscription notificationSubscription {
|
subscription notificationSubscription {
|
||||||
notification {
|
notification {
|
||||||
key
|
key
|
||||||
|
@ -49,7 +49,7 @@ const SubscriptionsHook = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data, error } = useSubscription<notificationSubscription>(
|
const { data, error } = useSubscription<notificationSubscription>(
|
||||||
notificationSubscription
|
NOTIFICATION_SUBSCRIPTION
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -3,8 +3,7 @@ import styled from 'styled-components'
|
||||||
import { Loader } from 'semantic-ui-react'
|
import { Loader } from 'semantic-ui-react'
|
||||||
import { MediaThumbnail, PhotoThumbnail } from './MediaThumbnail'
|
import { MediaThumbnail, PhotoThumbnail } from './MediaThumbnail'
|
||||||
import PresentView from './presentView/PresentView'
|
import PresentView from './presentView/PresentView'
|
||||||
import PropTypes from 'prop-types'
|
import { SidebarContext, UpdateSidebarFn } from '../sidebar/Sidebar'
|
||||||
import { SidebarContext } from '../sidebar/Sidebar'
|
|
||||||
import MediaSidebar from '../sidebar/MediaSidebar'
|
import MediaSidebar from '../sidebar/MediaSidebar'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
@ -31,6 +30,24 @@ const ClearWrap = styled.div`
|
||||||
clear: both;
|
clear: both;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
type PhotoGalleryProps = {
|
||||||
|
loading: boolean
|
||||||
|
media: {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
thumbnail?: {
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
activeIndex: number
|
||||||
|
presenting: boolean
|
||||||
|
onSelectImage(index: number): void
|
||||||
|
setPresenting(callback: (presenting: boolean) => void): void
|
||||||
|
nextImage(): void
|
||||||
|
previousImage(): void
|
||||||
|
onFavorite(): void
|
||||||
|
}
|
||||||
|
|
||||||
const PhotoGallery = ({
|
const PhotoGallery = ({
|
||||||
activeIndex = -1,
|
activeIndex = -1,
|
||||||
media,
|
media,
|
||||||
|
@ -41,17 +58,15 @@ const PhotoGallery = ({
|
||||||
nextImage,
|
nextImage,
|
||||||
previousImage,
|
previousImage,
|
||||||
onFavorite,
|
onFavorite,
|
||||||
}) => {
|
}: PhotoGalleryProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { updateSidebar } = useContext(SidebarContext)
|
const { updateSidebar } = useContext(SidebarContext)
|
||||||
|
|
||||||
const activeImage = media && activeIndex != -1 && media[activeIndex]
|
const activeImage = (media && activeIndex != -1 && media[activeIndex]) || {}
|
||||||
|
|
||||||
const getPhotoElements = updateSidebar => {
|
const getPhotoElements = (updateSidebar: UpdateSidebarFn) => {
|
||||||
let photoElements = []
|
let photoElements = []
|
||||||
if (media) {
|
if (media) {
|
||||||
media.filter(media => media.thumbnail)
|
|
||||||
|
|
||||||
photoElements = media.map((photo, index) => {
|
photoElements = media.map((photo, index) => {
|
||||||
const active = activeIndex == index
|
const active = activeIndex == index
|
||||||
|
|
||||||
|
@ -98,16 +113,4 @@ const PhotoGallery = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
PhotoGallery.propTypes = {
|
|
||||||
loading: PropTypes.bool,
|
|
||||||
media: PropTypes.array,
|
|
||||||
activeIndex: PropTypes.number,
|
|
||||||
presenting: PropTypes.bool,
|
|
||||||
onSelectImage: PropTypes.func,
|
|
||||||
setPresenting: PropTypes.func,
|
|
||||||
nextImage: PropTypes.func,
|
|
||||||
previousImage: PropTypes.func,
|
|
||||||
onFavorite: PropTypes.func,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PhotoGallery
|
export default PhotoGallery
|
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react'
|
import React, { DetailedHTMLProps, ImgHTMLAttributes } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
|
|
||||||
const isNativeLazyLoadSupported = 'loading' in HTMLImageElement.prototype
|
const isNativeLazyLoadSupported = 'loading' in HTMLImageElement.prototype
|
||||||
const placeholder = 'data:image/gif;base64,R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
|
const placeholder =
|
||||||
|
'data:image/gif;base64,R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
|
||||||
|
|
||||||
const getProtectedUrl = url => {
|
const getProtectedUrl = (url?: string) => {
|
||||||
if (url == null) return null
|
if (url == undefined) return undefined
|
||||||
|
|
||||||
const imgUrl = new URL(url, location.origin)
|
const imgUrl = new URL(url, location.origin)
|
||||||
|
|
||||||
|
@ -18,25 +18,40 @@ const getProtectedUrl = url => {
|
||||||
return imgUrl.href
|
return imgUrl.href
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProtectedImageProps
|
||||||
|
extends DetailedHTMLProps<
|
||||||
|
ImgHTMLAttributes<HTMLImageElement>,
|
||||||
|
HTMLImageElement
|
||||||
|
> {
|
||||||
|
lazyLoading?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An image that needs authorization to load
|
* An image that needs authorization to load
|
||||||
* Set lazyLoading to true if you want the image to be loaded once it enters the viewport
|
* Set lazyLoading to true if you want the image to be loaded once it enters the viewport
|
||||||
* Native lazy load via HTMLImageElement.loading attribute will be preferred if it is supported by the browser,
|
* Native lazy load via HTMLImageElement.loading attribute will be preferred if it is supported by the browser,
|
||||||
* otherwise IntersectionObserver will be used.
|
* otherwise IntersectionObserver will be used.
|
||||||
*/
|
*/
|
||||||
export const ProtectedImage = ({ src, lazyLoading, ...props }) => {
|
export const ProtectedImage = ({
|
||||||
|
src,
|
||||||
|
lazyLoading,
|
||||||
|
...props
|
||||||
|
}: ProtectedImageProps) => {
|
||||||
|
const lazyLoadProps: { 'data-src'?: string; loading?: 'lazy' | 'eager' } = {}
|
||||||
|
|
||||||
if (!isNativeLazyLoadSupported && lazyLoading) {
|
if (!isNativeLazyLoadSupported && lazyLoading) {
|
||||||
props['data-src'] = getProtectedUrl(src)
|
lazyLoadProps['data-src'] = getProtectedUrl(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNativeLazyLoadSupported && lazyLoading) {
|
if (isNativeLazyLoadSupported && lazyLoading) {
|
||||||
props.loading = 'lazy'
|
lazyLoadProps.loading = 'lazy'
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
key={src}
|
key={src}
|
||||||
{...props}
|
{...props}
|
||||||
|
{...lazyLoadProps}
|
||||||
src={
|
src={
|
||||||
lazyLoading && !isNativeLazyLoadSupported
|
lazyLoading && !isNativeLazyLoadSupported
|
||||||
? placeholder
|
? placeholder
|
||||||
|
@ -47,12 +62,21 @@ export const ProtectedImage = ({ src, lazyLoading, ...props }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtectedImage.propTypes = {
|
export interface ProtectedVideoProps_Media {
|
||||||
src: PropTypes.string,
|
id: string
|
||||||
lazyLoading: PropTypes.bool,
|
thumbnail: null | {
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
videoWeb: {
|
||||||
|
url: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProtectedVideo = ({ media, ...props }) => (
|
export interface ProtectedVideoProps {
|
||||||
|
media: ProtectedVideoProps_Media
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProtectedVideo = ({ media, ...props }: ProtectedVideoProps) => (
|
||||||
<video
|
<video
|
||||||
{...props}
|
{...props}
|
||||||
controls
|
controls
|
||||||
|
@ -63,7 +87,3 @@ export const ProtectedVideo = ({ media, ...props }) => (
|
||||||
<source src={getProtectedUrl(media.videoWeb.url)} type="video/mp4" />
|
<source src={getProtectedUrl(media.videoWeb.url)} type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
)
|
)
|
||||||
|
|
||||||
ProtectedVideo.propTypes = {
|
|
||||||
media: PropTypes.object.isRequired,
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { ReactChild, useEffect } from 'react'
|
import React, { ReactChild, useEffect } from 'react'
|
||||||
import PropTypes, { ReactComponentLike } from 'prop-types'
|
import PropTypes, { ReactComponentLike } from 'prop-types'
|
||||||
import { Route, Redirect } from 'react-router-dom'
|
import { Route, Redirect, RouteProps } from 'react-router-dom'
|
||||||
import { useLazyQuery } from '@apollo/client'
|
import { useLazyQuery } from '@apollo/client'
|
||||||
import { authToken } from '../../helpers/authentication'
|
import { authToken } from '../../helpers/authentication'
|
||||||
import { ADMIN_QUERY } from '../../Layout'
|
import { ADMIN_QUERY } from '../../Layout'
|
||||||
|
@ -27,9 +27,9 @@ export const Authorized = ({ children }: { children: JSX.Element }) => {
|
||||||
return token ? children : null
|
return token ? children : null
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthorizedRouteProps = {
|
interface AuthorizedRouteProps extends Omit<RouteProps, 'component'> {
|
||||||
component: ReactComponentLike
|
component: ReactComponentLike
|
||||||
admin: boolean
|
admin?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const AuthorizedRoute = ({
|
const AuthorizedRoute = ({
|
||||||
|
|
|
@ -8,8 +8,8 @@ import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const AuthorizedRoute = React.lazy(() => import('./AuthorizedRoute'))
|
const AuthorizedRoute = React.lazy(() => import('./AuthorizedRoute'))
|
||||||
|
|
||||||
const AlbumsPage = React.lazy(() =>
|
const AlbumsPage = React.lazy(
|
||||||
import('../../Pages/AllAlbumsPage/AlbumsPage')
|
() => import('../../Pages/AllAlbumsPage/AlbumsPage')
|
||||||
)
|
)
|
||||||
const AlbumPage = React.lazy(() => import('../../Pages/AlbumPage/AlbumPage'))
|
const AlbumPage = React.lazy(() => import('../../Pages/AlbumPage/AlbumPage'))
|
||||||
const PhotosPage = React.lazy(() => import('../../Pages/PhotosPage/PhotosPage'))
|
const PhotosPage = React.lazy(() => import('../../Pages/PhotosPage/PhotosPage'))
|
||||||
|
@ -18,12 +18,12 @@ const SharePage = React.lazy(() => import('../../Pages/SharePage/SharePage'))
|
||||||
const PeoplePage = React.lazy(() => import('../../Pages/PeoplePage/PeoplePage'))
|
const PeoplePage = React.lazy(() => import('../../Pages/PeoplePage/PeoplePage'))
|
||||||
|
|
||||||
const LoginPage = React.lazy(() => import('../../Pages/LoginPage/LoginPage'))
|
const LoginPage = React.lazy(() => import('../../Pages/LoginPage/LoginPage'))
|
||||||
const InitialSetupPage = React.lazy(() =>
|
const InitialSetupPage = React.lazy(
|
||||||
import('../../Pages/LoginPage/InitialSetupPage')
|
() => import('../../Pages/LoginPage/InitialSetupPage')
|
||||||
)
|
)
|
||||||
|
|
||||||
const SettingsPage = React.lazy(() =>
|
const SettingsPage = React.lazy(
|
||||||
import('../../Pages/SettingsPage/SettingsPage')
|
() => import('../../Pages/SettingsPage/SettingsPage')
|
||||||
)
|
)
|
||||||
|
|
||||||
const Routes = () => {
|
const Routes = () => {
|
||||||
|
@ -32,7 +32,7 @@ const Routes = () => {
|
||||||
return (
|
return (
|
||||||
<React.Suspense
|
<React.Suspense
|
||||||
fallback={
|
fallback={
|
||||||
<Layout>
|
<Layout title={t('general.loading.page', 'Loading page')}>
|
||||||
<Loader active>{t('general.loading.page', 'Loading page')}</Loader>
|
<Loader active>{t('general.loading.page', 'Loading page')}</Loader>
|
||||||
</Layout>
|
</Layout>
|
||||||
}
|
}
|
||||||
|
|
|
@ -370,7 +370,7 @@ const MediaSidebar = ({ media, hidePreview }) => {
|
||||||
return <SidebarContent media={media} hidePreview={hidePreview} />
|
return <SidebarContent media={media} hidePreview={hidePreview} />
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) return error
|
if (error) return <div>{error.message}</div>
|
||||||
|
|
||||||
if (loading || data == null) {
|
if (loading || data == null) {
|
||||||
return <SidebarContent media={media} hidePreview={hidePreview} />
|
return <SidebarContent media={media} hidePreview={hidePreview} />
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { Icon } from 'semantic-ui-react'
|
import { Icon } from 'semantic-ui-react'
|
||||||
|
|
||||||
const SidebarContainer = styled.div`
|
const SidebarContainer = styled.div<{ highlighted: boolean }>`
|
||||||
width: 28vw;
|
width: 28vw;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
|
@ -38,15 +38,34 @@ const SidebarDismissButton = styled(Icon)`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const SidebarContext = createContext()
|
export type UpdateSidebarFn = (content: React.ReactNode) => void
|
||||||
|
|
||||||
|
interface SidebarContextType {
|
||||||
|
updateSidebar: UpdateSidebarFn
|
||||||
|
content: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SidebarContext = createContext<SidebarContextType>({
|
||||||
|
updateSidebar: content => {
|
||||||
|
console.warn(
|
||||||
|
'SidebarContext: updateSidebar was called before initialezed',
|
||||||
|
content
|
||||||
|
)
|
||||||
|
},
|
||||||
|
content: null,
|
||||||
|
})
|
||||||
SidebarContext.displayName = 'SidebarContext'
|
SidebarContext.displayName = 'SidebarContext'
|
||||||
|
|
||||||
const Sidebar = ({ children }) => {
|
type SidebarProps = {
|
||||||
const [state, setState] = useState({
|
children: React.ReactElement
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sidebar = ({ children }: SidebarProps) => {
|
||||||
|
const [state, setState] = useState<{ content: React.ReactNode | null }>({
|
||||||
content: null,
|
content: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
const update = content => {
|
const update = (content: React.ReactNode | null) => {
|
||||||
setState({ content })
|
setState({ content })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import i18n from 'i18next'
|
import i18n from 'i18next'
|
||||||
import { initReactI18next } from 'react-i18next'
|
import { initReactI18next, TFunction } from 'react-i18next'
|
||||||
|
|
||||||
|
export type TranslationFn = TFunction<'translation'>
|
||||||
|
|
||||||
export default function setupLocalization(): void {
|
export default function setupLocalization(): void {
|
||||||
i18n.use(initReactI18next).init({
|
i18n.use(initReactI18next).init({
|
||||||
|
|
|
@ -74,5 +74,6 @@
|
||||||
"skipLibCheck": true /* Skip type checking of declaration files. */,
|
"skipLibCheck": true /* Skip type checking of declaration files. */,
|
||||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules/", "dist/"]
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules/**/*", "dist/**/*"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue