Merge branch 'master' into redesign
This commit is contained in:
commit
07550b5d06
|
@ -72,7 +72,7 @@ jobs:
|
||||||
sudo add-apt-repository ppa:strukturag/libheif
|
sudo add-apt-repository ppa:strukturag/libheif
|
||||||
sudo add-apt-repository ppa:strukturag/libde265
|
sudo add-apt-repository ppa:strukturag/libde265
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y libdlib-dev libblas-dev liblapack-dev libjpeg-turbo8-dev libheif-dev
|
sudo apt-get install -y libdlib-dev libblas-dev libatlas-base-dev liblapack-dev libjpeg-turbo8-dev libheif-dev
|
||||||
|
|
||||||
- name: Get GO dependencies
|
- name: Get GO dependencies
|
||||||
run: |
|
run: |
|
||||||
|
|
20
README.md
20
README.md
|
@ -30,7 +30,7 @@ Password: **demo**
|
||||||
- [Main features](#main-features)
|
- [Main features](#main-features)
|
||||||
- [Why yet another self-hosted photo gallery](#why-yet-another-self-hosted-photo-gallery)
|
- [Why yet another self-hosted photo gallery](#why-yet-another-self-hosted-photo-gallery)
|
||||||
- [Getting started - Setup with Docker](#getting-started---setup-with-docker)
|
- [Getting started - Setup with Docker](#getting-started---setup-with-docker)
|
||||||
- [Setup development environment](#setup-development-environment)
|
- [Set up development environment](#setup-development-environment)
|
||||||
- [Sponsors](#sponsors)
|
- [Sponsors](#sponsors)
|
||||||
|
|
||||||
## Main features
|
## Main features
|
||||||
|
@ -102,7 +102,7 @@ A new admin user will be created, with access to the photos located at the path
|
||||||
|
|
||||||
The photos will have to be scanned before they show up, you can start a scan manually, by navigating to `Settings` and clicking on `Scan All`
|
The photos will have to be scanned before they show up, you can start a scan manually, by navigating to `Settings` and clicking on `Scan All`
|
||||||
|
|
||||||
## Setup development environment
|
## Set up development environment
|
||||||
|
|
||||||
### Local setup
|
### Local setup
|
||||||
|
|
||||||
|
@ -119,9 +119,9 @@ They can be installed as shown below:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Ubuntu
|
# Ubuntu
|
||||||
sudo apt-get install libdlib-dev libblas-dev liblapack-dev libjpeg-turbo8-dev libheif-dev
|
sudo apt-get install libdlib-dev libblas-dev libatlas-base-dev liblapack-dev libjpeg-turbo8-dev libheif-dev
|
||||||
# Debian
|
# Debian
|
||||||
sudo apt-get install libdlib-dev libblas-dev liblapack-dev libjpeg62-turbo-dev libheif-dev
|
sudo apt-get install libdlib-dev libblas-dev libatlas-base-dev liblapack-dev libjpeg62-turbo-dev libheif-dev
|
||||||
# macOS
|
# macOS
|
||||||
brew install dlib libheif
|
brew install dlib libheif
|
||||||
|
|
||||||
|
@ -167,4 +167,16 @@ And the graphql playground at [localhost:4001](http://localhost:4001)
|
||||||
<b>@Revorge</b>
|
<b>@Revorge</b>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/deexno">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/50229919?v=4" height="auto" width="100" style="border-radius:50%"><br/>
|
||||||
|
<b>@deexno</b>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/FKrauss">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/4820683?v=4" height="auto" width="100" style="border-radius:50%"><br/>
|
||||||
|
<b>@FKrauss</b>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -4,7 +4,7 @@ go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/99designs/gqlgen v0.13.0
|
github.com/99designs/gqlgen v0.13.0
|
||||||
github.com/Kagami/go-face v0.0.0-20200825065730-3dd2d74dccfb
|
github.com/Kagami/go-face v0.0.0-20210604182630-c482b0e1acfb
|
||||||
github.com/agnivade/levenshtein v1.1.0 // indirect
|
github.com/agnivade/levenshtein v1.1.0 // indirect
|
||||||
github.com/barasher/go-exiftool v1.4.0
|
github.com/barasher/go-exiftool v1.4.0
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
|
|
|
@ -5,8 +5,8 @@ github.com/99designs/gqlgen v0.13.0 h1:haLTcUp3Vwp80xMVEg5KRNwzfUrgFdRmtBY8fuB8s
|
||||||
github.com/99designs/gqlgen v0.13.0/go.mod h1:NV130r6f4tpRWuAI+zsrSdooO/eWUv+Gyyoi3rEfXIk=
|
github.com/99designs/gqlgen v0.13.0/go.mod h1:NV130r6f4tpRWuAI+zsrSdooO/eWUv+Gyyoi3rEfXIk=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Kagami/go-face v0.0.0-20200825065730-3dd2d74dccfb h1:DXwA1Te9paM+nsdTGc7uve37lq7WEbQO+gwGBPVwQuQ=
|
github.com/Kagami/go-face v0.0.0-20210604182630-c482b0e1acfb h1:/XDrbCx+BZHdUz8cudJBGdCVqMI+b4HMdH5Y8D7k7sA=
|
||||||
github.com/Kagami/go-face v0.0.0-20200825065730-3dd2d74dccfb/go.mod h1:9wdDJkRgo3SGTcFwbQ7elVIQhIr2bbBjecuY7VoqmPU=
|
github.com/Kagami/go-face v0.0.0-20210604182630-c482b0e1acfb/go.mod h1:9wdDJkRgo3SGTcFwbQ7elVIQhIr2bbBjecuY7VoqmPU=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||||
|
|
|
@ -67,6 +67,7 @@ const (
|
||||||
TypeMOV MediaType = "video/quicktime"
|
TypeMOV MediaType = "video/quicktime"
|
||||||
TypeTS MediaType = "video/mp2t"
|
TypeTS MediaType = "video/mp2t"
|
||||||
TypeMTS MediaType = "video/MP2T"
|
TypeMTS MediaType = "video/MP2T"
|
||||||
|
TypeMKV MediaType = "video/x-matroska"
|
||||||
)
|
)
|
||||||
|
|
||||||
var SupportedMimetypes = [...]MediaType{
|
var SupportedMimetypes = [...]MediaType{
|
||||||
|
@ -130,6 +131,7 @@ var VideoMimetypes = [...]MediaType{
|
||||||
TypeMOV,
|
TypeMOV,
|
||||||
TypeTS,
|
TypeTS,
|
||||||
TypeMTS,
|
TypeMTS,
|
||||||
|
TypeMKV,
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebVideoMimetypes are video types that can be played directly in the browser without transcoding
|
// WebVideoMimetypes are video types that can be played directly in the browser without transcoding
|
||||||
|
@ -196,6 +198,7 @@ var fileExtensions = map[string]MediaType{
|
||||||
".ts": TypeTS,
|
".ts": TypeTS,
|
||||||
".m2ts": TypeMTS,
|
".m2ts": TypeMTS,
|
||||||
".mts": TypeMTS,
|
".mts": TypeMTS,
|
||||||
|
".mkv": TypeMKV,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (imgType *MediaType) IsRaw() bool {
|
func (imgType *MediaType) IsRaw() bool {
|
||||||
|
|
|
@ -31,6 +31,7 @@ apt-get install -y ca-certificates golang
|
||||||
apt-get install -y \
|
apt-get install -y \
|
||||||
libdlib-dev:${DEBIAN_ARCH} \
|
libdlib-dev:${DEBIAN_ARCH} \
|
||||||
libblas-dev:${DEBIAN_ARCH} \
|
libblas-dev:${DEBIAN_ARCH} \
|
||||||
|
libatlas-base-dev:${DEBIAN_ARCH} \
|
||||||
liblapack-dev:${DEBIAN_ARCH} \
|
liblapack-dev:${DEBIAN_ARCH} \
|
||||||
libjpeg-dev:${DEBIAN_ARCH} \
|
libjpeg-dev:${DEBIAN_ARCH} \
|
||||||
libheif-dev:${DEBIAN_ARCH}
|
libheif-dev:${DEBIAN_ARCH}
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
import '@testing-library/jest-dom'
|
import '@testing-library/jest-dom'
|
||||||
|
|
||||||
import React from 'react'
|
|
||||||
import { MockedProvider } from '@apollo/client/testing'
|
|
||||||
import { render, screen } from '@testing-library/react'
|
import { render, screen } from '@testing-library/react'
|
||||||
|
import React from 'react'
|
||||||
|
import Layout from './Layout'
|
||||||
|
|
||||||
import Layout, { ADMIN_QUERY, MAPBOX_QUERY, SideMenu } from './Layout'
|
require('../../localization').setupLocalization()
|
||||||
import { MemoryRouter } from 'react-router-dom'
|
|
||||||
|
|
||||||
import * as authentication from './helpers/authentication'
|
|
||||||
|
|
||||||
require('./localization').setupLocalization()
|
|
||||||
|
|
||||||
jest.mock('./helpers/authentication.ts')
|
|
||||||
|
|
||||||
test('Layout component', async () => {
|
test('Layout component', async () => {
|
||||||
render(
|
render(
|
||||||
|
@ -23,50 +15,3 @@ test('Layout component', async () => {
|
||||||
expect(screen.getByTestId('Layout')).toBeInTheDocument()
|
expect(screen.getByTestId('Layout')).toBeInTheDocument()
|
||||||
expect(screen.getByText('layout_content')).toBeInTheDocument()
|
expect(screen.getByText('layout_content')).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
authentication.authToken.mockClear()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Layout sidebar component', async () => {
|
|
||||||
authentication.authToken.mockImplementation(() => true)
|
|
||||||
|
|
||||||
const mockedGraphql = [
|
|
||||||
{
|
|
||||||
request: {
|
|
||||||
query: ADMIN_QUERY,
|
|
||||||
},
|
|
||||||
result: {
|
|
||||||
data: {
|
|
||||||
myUser: {
|
|
||||||
admin: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
request: {
|
|
||||||
query: MAPBOX_QUERY,
|
|
||||||
},
|
|
||||||
result: {
|
|
||||||
data: {
|
|
||||||
mapboxToken: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
render(
|
|
||||||
<MockedProvider mocks={mockedGraphql} addTypename={false}>
|
|
||||||
<MemoryRouter>
|
|
||||||
<SideMenu />
|
|
||||||
</MemoryRouter>
|
|
||||||
</MockedProvider>
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(screen.getByText('Photos')).toBeInTheDocument()
|
|
||||||
expect(screen.getByText('Albums')).toBeInTheDocument()
|
|
||||||
|
|
||||||
expect(await screen.findByText('Settings')).toBeInTheDocument()
|
|
||||||
expect(await screen.findByText('Places')).toBeInTheDocument()
|
|
||||||
})
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
import '@testing-library/jest-dom'
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { MockedProvider } from '@apollo/client/testing'
|
||||||
|
import { render, screen } from '@testing-library/react'
|
||||||
|
|
||||||
|
import * as authentication from '../../helpers/authentication'
|
||||||
|
import { ADMIN_QUERY } from './Layout'
|
||||||
|
import { MemoryRouter } from 'react-router-dom'
|
||||||
|
import MainMenu, { MAPBOX_QUERY } from './MainMenu'
|
||||||
|
|
||||||
|
require('../../localization').setupLocalization()
|
||||||
|
|
||||||
|
jest.mock('../../helpers/authentication.ts')
|
||||||
|
|
||||||
|
const authTokenMock = authentication.authToken as jest.MockedFunction<
|
||||||
|
typeof authentication.authToken
|
||||||
|
>
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
authTokenMock.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Layout sidebar component', async () => {
|
||||||
|
authTokenMock.mockImplementation(() => 'test-token')
|
||||||
|
|
||||||
|
const mockedGraphql = [
|
||||||
|
{
|
||||||
|
request: {
|
||||||
|
query: ADMIN_QUERY,
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
myUser: {
|
||||||
|
admin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
request: {
|
||||||
|
query: MAPBOX_QUERY,
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
mapboxToken: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
render(
|
||||||
|
<MockedProvider mocks={mockedGraphql} addTypename={false}>
|
||||||
|
<MemoryRouter>
|
||||||
|
<MainMenu />
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(screen.getByText('Timeline')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('Albums')).toBeInTheDocument()
|
||||||
|
|
||||||
|
expect(await screen.findByText('Settings')).toBeInTheDocument()
|
||||||
|
expect(await screen.findByText('Places')).toBeInTheDocument()
|
||||||
|
})
|
|
@ -69,55 +69,55 @@
|
||||||
"people_page": {
|
"people_page": {
|
||||||
"face_group": {
|
"face_group": {
|
||||||
"action": {
|
"action": {
|
||||||
"add_label": null,
|
"add_label": "Aggiungi etichetta",
|
||||||
"change_label": null,
|
"change_label": "Cambia etichetta",
|
||||||
"detach_face": null,
|
"detach_face": "Separa volto",
|
||||||
"merge_face": null,
|
"merge_face": "Unisci volto",
|
||||||
"move_faces": null
|
"move_faces": "Sposta volti"
|
||||||
},
|
},
|
||||||
"label_placeholder": "Etichetta",
|
"label_placeholder": "Etichetta",
|
||||||
"unlabeled": "Senza etichetta",
|
"unlabeled": "Senza etichetta",
|
||||||
"unlabeled_person": null
|
"unlabeled_person": "Persona senza etichetta"
|
||||||
},
|
},
|
||||||
"modal": {
|
"modal": {
|
||||||
"action": {
|
"action": {
|
||||||
"merge": null
|
"merge": "Unisci"
|
||||||
},
|
},
|
||||||
"detach_image_faces": {
|
"detach_image_faces": {
|
||||||
"action": {
|
"action": {
|
||||||
"detach": null,
|
"detach": "Separa immagini",
|
||||||
"select_images": null
|
"select_images": "Seleziona le immagini da separare"
|
||||||
},
|
},
|
||||||
"description": null,
|
"description": "Separa le immagini selezionate di questo volto e muovile in nuovo volto",
|
||||||
"title": null
|
"title": "Separa immagini volto"
|
||||||
},
|
},
|
||||||
"merge_face_groups": {
|
"merge_face_groups": {
|
||||||
"description": null,
|
"description": "Tutte le immagini di questo volto saranno unite alle immagini del volto selezionato",
|
||||||
"destination_table": {
|
"destination_table": {
|
||||||
"title": null
|
"title": "Seleziona il volto di destinazione"
|
||||||
},
|
},
|
||||||
"title": null
|
"title": "Unisci immagini volto"
|
||||||
},
|
},
|
||||||
"move_image_faces": {
|
"move_image_faces": {
|
||||||
"description": null,
|
"description": "Sposta le immagini selezionate di questo volto in un altro volto",
|
||||||
"destination_face_group_table": {
|
"destination_face_group_table": {
|
||||||
"move_action": null,
|
"move_action": "Muovi immagini",
|
||||||
"title": null
|
"title": "Seleziona il volto di destinazione"
|
||||||
},
|
},
|
||||||
"image_select_table": {
|
"image_select_table": {
|
||||||
"next_action": null,
|
"next_action": "Avanti",
|
||||||
"title": null
|
"title": "Seleziona immagini"
|
||||||
},
|
},
|
||||||
"title": null
|
"title": "Muovi immagini volto"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"recognize_unlabeled_faces_button": "Identifica facce senza etichetta",
|
"recognize_unlabeled_faces_button": "Identifica facce senza etichetta",
|
||||||
"table": {
|
"table": {
|
||||||
"select_face_group": {
|
"select_face_group": {
|
||||||
"search_faces_placeholder": null
|
"search_faces_placeholder": "Cerca volti..."
|
||||||
},
|
},
|
||||||
"select_image_faces": {
|
"select_image_faces": {
|
||||||
"search_images_placeholder": null
|
"search_images_placeholder": "Cerca immagini..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue