1
Fork 0

Replace vite with create-react-app

This commit is contained in:
viktorstrate 2021-07-15 13:07:35 +02:00
parent 477a499ba9
commit 2442ad96ba
No known key found for this signature in database
GPG Key ID: 3F855605109C1E8A
49 changed files with 25712 additions and 9836 deletions

View File

@ -55,6 +55,11 @@ module.exports = {
'jest/valid-title': 'off',
}
),
settings: {
jest: {
version: 26,
},
},
}),
{
files: ['**/*.js'],

7
ui/craco.config.js Normal file
View File

@ -0,0 +1,7 @@
module.exports = {
style: {
postcss: {
plugins: [require('tailwindcss'), require('autoprefixer')],
},
},
}

View File

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <link rel="manifest" href="/manifest.json" />
<link rel="stylesheet" href="/index.css" /> -->
<link rel="icon" href="/src/favicon.ico" />
<link rel="icon" href="/src/favicon.svg" type="image/svg+xml" />
<!-- Apple touch devices -->
<link rel="apple-touch-icon" href="/src/assets/apple-touch-icon.png" />
<meta name="apple-mobile-web-app-title" content="Photoview" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="white" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

34894
ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,90 +9,70 @@
"license": "GPL-3.0",
"description": "UI app for Photoview",
"dependencies": {
"@apollo/client": "^3.3.17",
"@babel/core": "^7.14.0",
"@babel/preset-react": "^7.13.13",
"@babel/preset-typescript": "^7.13.0",
"@headlessui/react": "^1.2.0",
"@react-aria/focus": "^3.3.0",
"@apollo/client": "^3.3.21",
"@babel/preset-typescript": "^7.14.5",
"@craco/craco": "^6.2.0",
"@headlessui/react": "^1.3.0",
"@react-aria/focus": "^3.4.0",
"@rollup/plugin-babel": "^5.3.0",
"@vitejs/plugin-react-refresh": "^1.3.3",
"autoprefixer": "^10.2.5",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"babel-plugin-graphql-tag": "^3.2.0",
"babel-plugin-i18next-extract": "^0.8.3",
"babel-plugin-styled-components": "^1.12.0",
"babel-plugin-transform-semantic-ui-react-imports": "^1.4.1",
"autoprefixer": "^9.8.6",
"babel-plugin-graphql-tag": "^3.3.0",
"classnames": "^2.3.1",
"connect-history-api-fallback": "^1.6.0",
"copy-to-clipboard": "^3.3.1",
"esbuild": "^0.11.20",
"esbuild-plugin-babel": "^0.2.3",
"eslint": "^7.26.0",
"eslint-plugin-jest": "^24.3.6",
"eslint-plugin-jest-dom": "^3.9.0",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0",
"fs-extra": "^10.0.0",
"i18next": "^20.2.2",
"mapbox-gl": "^2.2.0",
"postcss": "^8.3.0",
"i18next": "^20.3.2",
"mapbox-gl": "^2.3.1",
"postcss": "^7.0.36",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-helmet": "^6.1.0",
"react-hook-form": "^7.6.3",
"react-i18next": "^11.8.15",
"react-hook-form": "^7.11.0",
"react-i18next": "^11.11.1",
"react-router-dom": "^5.2.0",
"react-router-prop-types": "^1.0.5",
"react-scripts": "^4.0.3",
"react-spring": "^8.0.27",
"react-test-renderer": "^17.0.2",
"semantic-ui-react": "^2.0.3",
"styled-components": "^5.3.0",
"subscriptions-transport-ws": "^0.9.18",
"tailwindcss": "^2.1.2",
"typescript": "^4.2.4",
"url-join": "^4.0.1",
"vite": "^2.3.3",
"vite-plugin-svgr": "^0.2.0"
"subscriptions-transport-ws": "^0.9.19",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.4",
"typescript": "^4.3.5",
"url-join": "^4.0.1"
},
"scripts": {
"start": "vite",
"build": "vite build",
"serve": "vite preview",
"test": "npm run lint && npm run jest",
"start": "craco start",
"build": "craco build",
"test": "npm run lint && npm run jest -- --watchAll=false",
"test:ci": "npm run lint && npm run jest:ci",
"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 --verbose",
"jest:ci": "jest --verbose --ci --coverage",
"genSchemaTypes": "npx apollo client:codegen --target=typescript",
"jest": "craco test",
"jest:ci": "CI=true craco test --verbose --ci --coverage",
"genSchemaTypes": "npx apollo client:codegen --target=typescript --globalTypesFile=src/__generated__/globalTypes.ts",
"prepare": "(cd .. && npx husky install)"
},
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.13.15",
"@babel/preset-env": "^7.14.1",
"@testing-library/jest-dom": "^5.12.0",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^13.1.8",
"@types/geojson": "^7946.0.7",
"@types/jest": "^26.0.23",
"@types/mapbox-gl": "^2.1.2",
"@types/react": "^17.0.5",
"@types/react-dom": "^17.0.4",
"@types/react-helmet": "^6.1.1",
"@types/react-router-dom": "^5.1.7",
"@types/styled-components": "^5.1.9",
"@types/url-join": "^4.0.0",
"@typescript-eslint/eslint-plugin": "^4.23.0",
"@typescript-eslint/parser": "^4.23.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@testing-library/user-event": "^13.1.9",
"@types/geojson": "^7946.0.8",
"@types/jest": "^26.0.24",
"@types/mapbox-gl": "^2.3.3",
"@types/react": "^17.0.14",
"@types/react-dom": "^17.0.9",
"@types/react-helmet": "^6.1.2",
"@types/react-router-dom": "^5.1.8",
"@types/styled-components": "^5.1.11",
"@types/url-join": "^4.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-jest-dom": "^3.9.0",
"husky": "^6.0.0",
"jest": "^26.6.3",
"lint-staged": "^11.0.0",
"prettier": "^2.3.0",
"lint-staged": "^11.0.1",
"prettier": "^2.3.2",
"tsc-files": "^1.1.2"
},
"prettier": {
@ -102,27 +82,21 @@
"singleQuote": true,
"arrowParens": "avoid"
},
"jest": {
"testMatch": [
"**/__tests__/**/*.+(ts|tsx|js|jsx)",
"**/?(*.)+(spec|test).+(ts|tsx|js|jsx)"
],
"transformIgnorePatterns": [
"^.+\\.css$"
],
"transform": {
"^.+\\.(js|ts|tsx)$": "babel-jest",
"^.+\\.svg$": "<rootDir>/testing/transform-svg.js"
},
"collectCoverage": true,
"coverageReporters": [
"json",
"html"
]
},
"lint-staged": {
"*.{ts,tsx,js,json,css,md,graphql}": "prettier --write",
"*.{js,ts,tsx}": "eslint --cache --fix --max-warnings 0",
"*.{ts,tsx}": "tsc-files --noEmit"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

43
ui/public/index.html Normal file
View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<!--
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
-->
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<!--
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
-->
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
</head>
<body>
<noscript>You need to enable JavaScript to run Photoview.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -3,101 +3,101 @@
// @generated
// This file was automatically generated and should not be edited.
import { OrderDirection, MediaType } from "./../../../../__generated__/globalTypes";
import { OrderDirection, MediaType } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL query operation: albumQuery
// ====================================================
export interface albumQuery_album_subAlbums_thumbnail_thumbnail {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
}
export interface albumQuery_album_subAlbums_thumbnail {
__typename: "Media";
__typename: 'Media'
/**
* URL to display the media in a smaller resolution
*/
thumbnail: albumQuery_album_subAlbums_thumbnail_thumbnail | null;
thumbnail: albumQuery_album_subAlbums_thumbnail_thumbnail | null
}
export interface albumQuery_album_subAlbums {
__typename: "Album";
id: string;
title: string;
__typename: 'Album'
id: string
title: string
/**
* An image in this album used for previewing this album
*/
thumbnail: albumQuery_album_subAlbums_thumbnail | null;
thumbnail: albumQuery_album_subAlbums_thumbnail | null
}
export interface albumQuery_album_media_thumbnail {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
/**
* Width of the image in pixels
*/
width: number;
width: number
/**
* Height of the image in pixels
*/
height: number;
height: number
}
export interface albumQuery_album_media_highRes {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
}
export interface albumQuery_album_media_videoWeb {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
}
export interface albumQuery_album_media {
__typename: "Media";
id: string;
type: MediaType;
__typename: 'Media'
id: string
type: MediaType
/**
* URL to display the media in a smaller resolution
*/
thumbnail: albumQuery_album_media_thumbnail | null;
thumbnail: albumQuery_album_media_thumbnail | null
/**
* URL to display the photo in full resolution, will be null for videos
*/
highRes: albumQuery_album_media_highRes | null;
highRes: albumQuery_album_media_highRes | null
/**
* URL to get the video in a web format that can be played in the browser, will be null for photos
*/
videoWeb: albumQuery_album_media_videoWeb | null;
favorite: boolean;
videoWeb: albumQuery_album_media_videoWeb | null
favorite: boolean
}
export interface albumQuery_album {
__typename: "Album";
id: string;
title: string;
__typename: 'Album'
id: string
title: string
/**
* The albums contained in this album
*/
subAlbums: albumQuery_album_subAlbums[];
subAlbums: albumQuery_album_subAlbums[]
/**
* The media inside this album
*/
media: albumQuery_album_media[];
media: albumQuery_album_media[]
}
export interface albumQuery {
@ -105,14 +105,14 @@ export interface albumQuery {
* Get album by id, user must own the album or be admin
* If valid tokenCredentials are provided, the album may be retrived without further authentication
*/
album: albumQuery_album;
album: albumQuery_album
}
export interface albumQueryVariables {
id: string;
onlyFavorites?: boolean | null;
mediaOrderBy?: string | null;
mediaOrderDirection?: OrderDirection | null;
limit?: number | null;
offset?: number | null;
id: string
onlyFavorites?: boolean | null
mediaOrderBy?: string | null
mediaOrderDirection?: OrderDirection | null
limit?: number | null
offset?: number | null
}

View File

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { MediaType } from './../../../../../__generated__/globalTypes'
import { MediaType } from './../../../../__generated__/globalTypes'
// ====================================================
// GraphQL query operation: singleFaceGroup

View File

@ -10,7 +10,7 @@ import MapPresentMarker from './MapPresentMarker'
import { urlPresentModeSetupHook } from '../../components/photoGallery/photoGalleryReducer'
import { placesReducer } from './placesReducer'
import mapboxStyles from 'mapbox-gl/dist/mapbox-gl.css'
import 'mapbox-gl/dist/mapbox-gl.css'
const MapWrapper = styled.div`
width: 100%;
@ -148,7 +148,7 @@ const MapPage = () => {
<Layout title="Places">
<Helmet>
{/* <link rel="stylesheet" href="/mapbox-gl.css" /> */}
<style type="text/css">{mapboxStyles}</style>
{/* <style type="text/css">{mapboxStyles}</style> */}
</Helmet>
<MapWrapper>
<MapContainer ref={mapContainer}></MapContainer>

View File

@ -3,86 +3,86 @@
// @generated
// This file was automatically generated and should not be edited.
import { MediaType } from "./../../../../__generated__/globalTypes";
import { MediaType } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL query operation: placePageQueryMedia
// ====================================================
export interface placePageQueryMedia_mediaList_thumbnail {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
/**
* Width of the image in pixels
*/
width: number;
width: number
/**
* Height of the image in pixels
*/
height: number;
height: number
}
export interface placePageQueryMedia_mediaList_highRes {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
/**
* Width of the image in pixels
*/
width: number;
width: number
/**
* Height of the image in pixels
*/
height: number;
height: number
}
export interface placePageQueryMedia_mediaList_videoWeb {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
/**
* Width of the image in pixels
*/
width: number;
width: number
/**
* Height of the image in pixels
*/
height: number;
height: number
}
export interface placePageQueryMedia_mediaList {
__typename: "Media";
id: string;
title: string;
__typename: 'Media'
id: string
title: string
/**
* URL to display the media in a smaller resolution
*/
thumbnail: placePageQueryMedia_mediaList_thumbnail | null;
thumbnail: placePageQueryMedia_mediaList_thumbnail | null
/**
* URL to display the photo in full resolution, will be null for videos
*/
highRes: placePageQueryMedia_mediaList_highRes | null;
highRes: placePageQueryMedia_mediaList_highRes | null
/**
* URL to get the video in a web format that can be played in the browser, will be null for photos
*/
videoWeb: placePageQueryMedia_mediaList_videoWeb | null;
type: MediaType;
videoWeb: placePageQueryMedia_mediaList_videoWeb | null
type: MediaType
}
export interface placePageQueryMedia {
/**
* Get a list of media by their ids, user must own the media or be admin
*/
mediaList: placePageQueryMedia_mediaList[];
mediaList: placePageQueryMedia_mediaList[]
}
export interface placePageQueryMediaVariables {
mediaIDs: string[];
mediaIDs: string[]
}

View File

@ -3,7 +3,7 @@ import gql from 'graphql-tag'
import React, { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import { LanguageTranslation } from '../../../__generated__/globalTypes'
import { LanguageTranslation } from '../../__generated__/globalTypes'
import Dropdown from '../../primitives/form/Dropdown'
import { Button } from '../../primitives/form/Input'
import {

View File

@ -7,10 +7,10 @@ import {
SectionTitle,
} from './SettingsPage'
const VERSION = import.meta.env.VITE_BUILD_VERSION ?? 'undefined'
const BUILD_DATE = import.meta.env.VITE_BUILD_DATE ?? 'undefined'
const VERSION = process.env.REACT_APP_BUILD_VERSION ?? 'undefined'
const BUILD_DATE = process.env.REACT_APP_BUILD_DATE ?? 'undefined'
const COMMIT_SHA = import.meta.env.VITE_BUILD_COMMIT_SHA as string | undefined
const COMMIT_SHA = process.env.REACT_APP_BUILD_COMMIT_SHA as string | undefined
let commitLink: ReactElement
if (COMMIT_SHA) {

View File

@ -3,22 +3,22 @@
// @generated
// This file was automatically generated and should not be edited.
import { LanguageTranslation } from "./../../../../__generated__/globalTypes";
import { LanguageTranslation } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL mutation operation: changeUserPreferences
// ====================================================
export interface changeUserPreferences_changeUserPreferences {
__typename: "UserPreferences";
id: string;
language: LanguageTranslation | null;
__typename: 'UserPreferences'
id: string
language: LanguageTranslation | null
}
export interface changeUserPreferences {
changeUserPreferences: changeUserPreferences_changeUserPreferences;
changeUserPreferences: changeUserPreferences_changeUserPreferences
}
export interface changeUserPreferencesVariables {
language?: string | null;
language?: string | null
}

View File

@ -3,18 +3,18 @@
// @generated
// This file was automatically generated and should not be edited.
import { LanguageTranslation } from "./../../../../__generated__/globalTypes";
import { LanguageTranslation } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL query operation: myUserPreferences
// ====================================================
export interface myUserPreferences_myUserPreferences {
__typename: "UserPreferences";
id: string;
language: LanguageTranslation | null;
__typename: 'UserPreferences'
id: string
language: LanguageTranslation | null
}
export interface myUserPreferences {
myUserPreferences: myUserPreferences_myUserPreferences;
myUserPreferences: myUserPreferences_myUserPreferences
}

View File

@ -9,7 +9,7 @@ import { SidebarContext } from '../../components/sidebar/Sidebar'
import MediaSidebar from '../../components/sidebar/MediaSidebar'
import { useTranslation } from 'react-i18next'
import { SharePageToken_shareToken_media } from './__generated__/SharePageToken'
import { MediaType } from '../../../__generated__/globalTypes'
import { MediaType } from '../../__generated__/globalTypes'
import { exhaustiveCheck } from '../../helpers/utils'
const DisplayPhoto = styled(ProtectedImage)`

View File

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { MediaType } from './../../../../__generated__/globalTypes'
import { MediaType } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL query operation: SharePageToken

View File

@ -3,10 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import {
OrderDirection,
MediaType,
} from './../../../../__generated__/globalTypes'
import { OrderDirection, MediaType } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL query operation: shareAlbumQuery

View File

@ -3,18 +3,18 @@
// @generated
// This file was automatically generated and should not be edited.
import { LanguageTranslation } from "./../../__generated__/globalTypes";
import { LanguageTranslation } from './globalTypes'
// ====================================================
// GraphQL query operation: siteTranslation
// ====================================================
export interface siteTranslation_myUserPreferences {
__typename: "UserPreferences";
id: string;
language: LanguageTranslation | null;
__typename: 'UserPreferences'
id: string
language: LanguageTranslation | null
}
export interface siteTranslation {
myUserPreferences: siteTranslation_myUserPreferences;
myUserPreferences: siteTranslation_myUserPreferences
}

View File

@ -16,8 +16,8 @@ import { clearTokenCookie } from './helpers/authentication'
import { MessageState } from './components/messages/Messages'
import { Message } from './components/messages/SubscriptionsHook'
export const GRAPHQL_ENDPOINT = import.meta.env.VITE_API_ENDPOINT
? urlJoin(import.meta.env.VITE_API_ENDPOINT as string, '/graphql')
export const GRAPHQL_ENDPOINT = process.env.REACT_APP_API_ENDPOINT
? urlJoin(process.env.REACT_APP_API_ENDPOINT as string, '/graphql')
: urlJoin(location.origin, '/api/graphql')
const httpLink = new HttpLink({
@ -85,7 +85,7 @@ const linkError = onError(({ graphQLErrors, networkError }) => {
console.log(`[Network error]: ${JSON.stringify(networkError)}`)
clearTokenCookie()
const errors = (networkError as ServerError).result.errors
const errors = (networkError as ServerError)?.result.errors || []
if (errors.length == 1) {
errorMessages.push({

View File

@ -1,7 +1,7 @@
import React from 'react'
import { authToken } from '../../helpers/authentication'
import { useTranslation } from 'react-i18next'
import { OrderDirection } from '../../../__generated__/globalTypes'
import { OrderDirection } from '../../__generated__/globalTypes'
import { MediaOrdering, SetOrderingFn } from '../../hooks/useOrderingParams'
import Checkbox from '../../primitives/form/Checkbox'

View File

@ -1,7 +1,7 @@
import React from 'react'
import { Link } from 'react-router-dom'
import styled from 'styled-components'
import { MediaType } from '../../../__generated__/globalTypes'
import { MediaType } from '../../__generated__/globalTypes'
import { MediaSidebarMedia } from '../sidebar/MediaSidebar'
import { sidebarPhoto_media_faces } from '../sidebar/__generated__/sidebarPhoto'

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import { useEffect } from 'react'
import { useSubscription, gql } from '@apollo/client'
import { authToken } from '../../helpers/authentication'
import { NotificationType } from '../../../__generated__/globalTypes'
import { NotificationType } from '../../__generated__/globalTypes'
const NOTIFICATION_SUBSCRIPTION = gql`
subscription notificationSubscription {

View File

@ -3,27 +3,27 @@
// @generated
// This file was automatically generated and should not be edited.
import { NotificationType } from "./../../../../__generated__/globalTypes";
import { NotificationType } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL subscription operation: notificationSubscription
// ====================================================
export interface notificationSubscription_notification {
__typename: "Notification";
key: string;
type: NotificationType;
header: string;
content: string;
progress: number | null;
positive: boolean;
negative: boolean;
__typename: 'Notification'
key: string
type: NotificationType
header: string
content: string
progress: number | null
positive: boolean
negative: boolean
/**
* Time in milliseconds before the notification will close
*/
timeout: number | null;
timeout: number | null
}
export interface notificationSubscription {
notification: notificationSubscription_notification;
notification: notificationSubscription_notification
}

View File

@ -1,7 +1,7 @@
import React, { useCallback, useState } from 'react'
import styled from 'styled-components'
import { ProtectedImage } from './ProtectedMedia'
import { MediaType } from '../../../__generated__/globalTypes'
import { MediaType } from '../../__generated__/globalTypes'
import { ReactComponent as VideoThumbnailIconSVG } from './icons/videoThumbnailIcon.svg'
const MediaContainer = styled.div`

View File

@ -2,7 +2,7 @@ import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import React from 'react'
import { MediaType } from '../../../__generated__/globalTypes'
import { MediaType } from '../../__generated__/globalTypes'
import PhotoGallery from './PhotoGallery'
import { PhotoGalleryState } from './photoGalleryReducer'
@ -22,8 +22,7 @@ test('photo gallery with media', () => {
id: '165',
type: MediaType.Photo,
thumbnail: {
url:
'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
url: 'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
width: 768,
height: 1024,
__typename: 'MediaURL',
@ -97,8 +96,7 @@ describe('photo gallery presenting', () => {
id: '165',
type: MediaType.Photo,
thumbnail: {
url:
'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
url: 'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
width: 768,
height: 1024,
__typename: 'MediaURL',

View File

@ -1,5 +1,5 @@
import { photoGalleryReducer, PhotoGalleryState } from './photoGalleryReducer'
import { MediaType } from '../../../__generated__/globalTypes'
import { MediaType } from '../../__generated__/globalTypes'
describe('photo gallery reducer', () => {
const defaultState: PhotoGalleryState = {

View File

@ -2,7 +2,7 @@ import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import React from 'react'
import { MediaType } from '../../../../__generated__/globalTypes'
import { MediaType } from '../../../__generated__/globalTypes'
import PresentMedia, { PresentMediaProps_Media } from './PresentMedia'
test('render present image', () => {

View File

@ -1,6 +1,6 @@
import React from 'react'
import styled from 'styled-components'
import { MediaType } from '../../../../__generated__/globalTypes'
import { MediaType } from '../../../__generated__/globalTypes'
import { exhaustiveCheck } from '../../../helpers/utils'
import {
ProtectedImage,

View File

@ -13,7 +13,7 @@ import SidebarItem from './SidebarItem'
import { SidebarFacesOverlay } from '../facesOverlay/FacesOverlay'
import { isNil } from '../../helpers/utils'
import { useTranslation } from 'react-i18next'
import { MediaType } from '../../../__generated__/globalTypes'
import { MediaType } from '../../__generated__/globalTypes'
import { TranslationFn } from '../../localization'
import {
sidebarPhoto,
@ -411,8 +411,10 @@ type MediaSidebarType = {
}
const MediaSidebar = ({ media, hidePreview }: MediaSidebarType) => {
const [loadMedia, { loading, error, data }] =
useLazyQuery<sidebarPhoto, sidebarPhotoVariables>(SIDEBAR_MEDIA_QUERY)
const [loadMedia, { loading, error, data }] = useLazyQuery<
sidebarPhoto,
sidebarPhotoVariables
>(SIDEBAR_MEDIA_QUERY)
useEffect(() => {
if (media != null && authToken()) {

View File

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { MediaType } from './../../../../__generated__/globalTypes'
import { MediaType } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL query operation: sidebarPhoto

View File

@ -3,92 +3,92 @@
// @generated
// This file was automatically generated and should not be edited.
import { MediaType } from "./../../../../__generated__/globalTypes";
import { MediaType } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL query operation: myTimeline
// ====================================================
export interface myTimeline_myTimeline_album {
__typename: "Album";
id: string;
title: string;
__typename: 'Album'
id: string
title: string
}
export interface myTimeline_myTimeline_media_thumbnail {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
/**
* Width of the image in pixels
*/
width: number;
width: number
/**
* Height of the image in pixels
*/
height: number;
height: number
}
export interface myTimeline_myTimeline_media_highRes {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
/**
* Width of the image in pixels
*/
width: number;
width: number
/**
* Height of the image in pixels
*/
height: number;
height: number
}
export interface myTimeline_myTimeline_media_videoWeb {
__typename: "MediaURL";
__typename: 'MediaURL'
/**
* URL for previewing the image
*/
url: string;
url: string
}
export interface myTimeline_myTimeline_media {
__typename: "Media";
id: string;
title: string;
type: MediaType;
__typename: 'Media'
id: string
title: string
type: MediaType
/**
* URL to display the media in a smaller resolution
*/
thumbnail: myTimeline_myTimeline_media_thumbnail | null;
thumbnail: myTimeline_myTimeline_media_thumbnail | null
/**
* URL to display the photo in full resolution, will be null for videos
*/
highRes: myTimeline_myTimeline_media_highRes | null;
highRes: myTimeline_myTimeline_media_highRes | null
/**
* URL to get the video in a web format that can be played in the browser, will be null for photos
*/
videoWeb: myTimeline_myTimeline_media_videoWeb | null;
favorite: boolean;
videoWeb: myTimeline_myTimeline_media_videoWeb | null
favorite: boolean
}
export interface myTimeline_myTimeline {
__typename: "TimelineGroup";
album: myTimeline_myTimeline_album;
media: myTimeline_myTimeline_media[];
mediaTotal: number;
date: any;
__typename: 'TimelineGroup'
album: myTimeline_myTimeline_album
media: myTimeline_myTimeline_media[]
mediaTotal: number
date: any
}
export interface myTimeline {
myTimeline: myTimeline_myTimeline[];
myTimeline: myTimeline_myTimeline[]
}
export interface myTimelineVariables {
onlyFavorites?: boolean | null;
limit?: number | null;
offset?: number | null;
onlyFavorites?: boolean | null
limit?: number | null
offset?: number | null
}

View File

@ -1,5 +1,5 @@
import { myTimeline_myTimeline } from './__generated__/myTimeline'
import { MediaType } from '../../../__generated__/globalTypes'
import { MediaType } from '../../__generated__/globalTypes'
import {
timelineGalleryReducer,
TimelineGalleryState,
@ -30,8 +30,7 @@ describe('timeline gallery reducer', () => {
title: '3666760020.jpg',
type: MediaType.Photo,
thumbnail: {
url:
'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
url: 'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
width: 768,
height: 1024,
__typename: 'MediaURL',
@ -51,8 +50,7 @@ describe('timeline gallery reducer', () => {
title: '7414455077.jpg',
type: MediaType.Photo,
thumbnail: {
url:
'http://localhost:4001/photo/thumbnail_7414455077_jpg_9JYHHYh6.jpg',
url: 'http://localhost:4001/photo/thumbnail_7414455077_jpg_9JYHHYh6.jpg',
width: 768,
height: 1024,
__typename: 'MediaURL',
@ -84,8 +82,7 @@ describe('timeline gallery reducer', () => {
title: '3666760020.jpg',
type: MediaType.Photo,
thumbnail: {
url:
'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
url: 'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
width: 768,
height: 1024,
__typename: 'MediaURL',
@ -120,8 +117,7 @@ describe('timeline gallery reducer', () => {
favorite: false,
videoWeb: null,
thumbnail: {
url:
'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
url: 'http://localhost:4001/photo/thumbnail_3666760020_jpg_x76GG5pS.jpg',
width: 768,
height: 1024,
__typename: 'MediaURL',

View File

@ -1,5 +1,5 @@
import { useCallback } from 'react'
import { OrderDirection } from '../../__generated__/globalTypes'
import { OrderDirection } from '../__generated__/globalTypes'
import { UrlKeyValuePair, UrlParams } from './useURLParameters'
export type MediaOrdering = {

View File

@ -3,7 +3,7 @@ import { siteTranslation } from './__generated__/siteTranslation'
import { gql, useLazyQuery } from '@apollo/client'
import i18n from 'i18next'
import { initReactI18next, TFunction } from 'react-i18next'
import { LanguageTranslation } from '../__generated__/globalTypes'
import { LanguageTranslation } from './__generated__/globalTypes'
import { authToken } from './helpers/authentication'
import { exhaustiveCheck, isNil } from './helpers/utils'
@ -27,7 +27,7 @@ export function setupLocalization(): void {
},
react: {
useSuspense: import.meta.env.PROD,
useSuspense: process.env.NODE_ENV == 'production',
},
})
}
@ -59,49 +59,49 @@ export const loadTranslations = () => {
switch (language) {
case LanguageTranslation.Danish:
import('../extractedTranslations/da/translation.json').then(danish => {
import('./extractedTranslations/da/translation.json').then(danish => {
i18n.addResourceBundle('da', 'translation', danish)
i18n.changeLanguage('da')
})
return
case LanguageTranslation.English:
import('../extractedTranslations/en/translation.json').then(english => {
import('./extractedTranslations/en/translation.json').then(english => {
i18n.addResourceBundle('en', 'translation', english)
i18n.changeLanguage('en')
})
return
case LanguageTranslation.French:
import('../extractedTranslations/fr/translation.json').then(english => {
import('./extractedTranslations/fr/translation.json').then(english => {
i18n.addResourceBundle('fr', 'translation', english)
i18n.changeLanguage('fr')
})
return
case LanguageTranslation.Swedish:
import('../extractedTranslations/sv/translation.json').then(swedish => {
import('./extractedTranslations/sv/translation.json').then(swedish => {
i18n.addResourceBundle('sv', 'translation', swedish)
i18n.changeLanguage('sv')
})
return
case LanguageTranslation.Italian:
import('../extractedTranslations/it/translation.json').then(italian => {
import('./extractedTranslations/it/translation.json').then(italian => {
i18n.addResourceBundle('it', 'translation', italian)
i18n.changeLanguage('it')
})
return
case LanguageTranslation.Spanish:
import('../extractedTranslations/es/translation.json').then(spanish => {
import('./extractedTranslations/es/translation.json').then(spanish => {
i18n.addResourceBundle('es', 'translation', spanish)
i18n.changeLanguage('es')
})
return
case LanguageTranslation.Polish:
import('../extractedTranslations/pl/translation.json').then(polish => {
import('./extractedTranslations/pl/translation.json').then(polish => {
i18n.addResourceBundle('pl', 'translation', polish)
i18n.changeLanguage('pl')
})
return
case LanguageTranslation.German:
import('../extractedTranslations/de/translation.json').then(german => {
import('./extractedTranslations/de/translation.json').then(german => {
i18n.addResourceBundle('de', 'translation', german)
i18n.changeLanguage('de')
})

1
ui/src/react-app-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="react-scripts" />

View File

@ -8,7 +8,7 @@
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.
const isProduction = import.meta.env.PROD
const isProduction = process.env.NODE_ENV == 'production'
export default function register() {
if (isProduction && 'serviceWorker' in navigator) {

View File

@ -1,84 +1,21 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true /* Enable incremental compilation */,
"target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
"module": "ESNEXT" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
"lib": [
"DOM",
"DOM.Iterable",
"ESNext"
] /* Specify library files to be included in the compilation. */,
"allowJs": true /* Allow javascript files to be compiled. */,
// "checkJs": true, /* Report errors in .js files. */
"jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */,
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
"noEmit": true /* Do not emit outputs. */,
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
"isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */,
/* Strict Type-Checking Options */
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"strictNullChecks": true /* Enable strict null checks. */,
"strictFunctionTypes": true /* Enable strict checking of function types. */,
"strictBindCallApply": true /* Enable strict 'bind', 'call', and 'apply' methods on functions. */,
"strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
"noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
"alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
/* Module Resolution Options */
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
"typeRoots": [
"node_modules/@types",
"./src/@types/"
] /* List of folders to include type definitions from. */,
"types": [
"vite/client",
"jest"
] /* Type declaration files to be included in compilation. */,
"allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */,
"esModuleInterop": false /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": false /* Skip type checking of declaration files. */,
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["./src"],
"include": ["src"],
"exclude": ["./node_modules", "./dist"]
}

View File

@ -1,20 +0,0 @@
import { defineConfig } from 'vite'
import reactRefresh from '@vitejs/plugin-react-refresh'
import { babel } from '@rollup/plugin-babel'
import svgr from 'vite-plugin-svgr'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
reactRefresh(),
babel({
babelHelpers: 'bundled',
exclude: 'node_modules/**',
extensions: ['.js', '.jsx', '.ts', '.tsx'],
}),
svgr(),
],
server: {
port: 1234,
},
})