Make people page translatable
This commit is contained in:
parent
e2f6bdb365
commit
360db25ec3
|
@ -68,10 +68,58 @@
|
||||||
},
|
},
|
||||||
"people_page": {
|
"people_page": {
|
||||||
"face_group": {
|
"face_group": {
|
||||||
"label_placeholder": "Navn",
|
"action": {
|
||||||
"unlabeled": "Ikke navngivet"
|
"add_label": null,
|
||||||
|
"change_label": null,
|
||||||
|
"detach_face": null,
|
||||||
|
"merge_face": null,
|
||||||
|
"move_faces": null
|
||||||
},
|
},
|
||||||
"recognize_unlabeled_faces_button": "Genkend ikke navngivede ansigter"
|
"label_placeholder": "Navn",
|
||||||
|
"unlabeled": "Ikke navngivet",
|
||||||
|
"unlabeled_person": null
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"action": {
|
||||||
|
"merge": null
|
||||||
|
},
|
||||||
|
"detach_image_faces": {
|
||||||
|
"action": {
|
||||||
|
"detach": null,
|
||||||
|
"select_images": null
|
||||||
|
},
|
||||||
|
"description": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"merge_face_groups": {
|
||||||
|
"description": null,
|
||||||
|
"destination_table": {
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"move_image_faces": {
|
||||||
|
"description": null,
|
||||||
|
"destination_face_group_table": {
|
||||||
|
"move_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"image_select_table": {
|
||||||
|
"next_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recognize_unlabeled_faces_button": "Genkend ikke navngivede ansigter",
|
||||||
|
"table": {
|
||||||
|
"select_face_group": {
|
||||||
|
"search_faces_placeholder": null
|
||||||
|
},
|
||||||
|
"select_image_faces": {
|
||||||
|
"search_images_placeholder": null
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"photos_page": {
|
"photos_page": {
|
||||||
"title": "Billeder"
|
"title": "Billeder"
|
||||||
|
|
|
@ -68,10 +68,58 @@
|
||||||
},
|
},
|
||||||
"people_page": {
|
"people_page": {
|
||||||
"face_group": {
|
"face_group": {
|
||||||
"label_placeholder": "Zuordnung",
|
"action": {
|
||||||
"unlabeled": "Nicht zugeordnet"
|
"add_label": null,
|
||||||
|
"change_label": null,
|
||||||
|
"detach_face": null,
|
||||||
|
"merge_face": null,
|
||||||
|
"move_faces": null
|
||||||
},
|
},
|
||||||
"recognize_unlabeled_faces_button": "Nicht zugeordnete Gesichter erkennen"
|
"label_placeholder": "Zuordnung",
|
||||||
|
"unlabeled": "Nicht zugeordnet",
|
||||||
|
"unlabeled_person": null
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"action": {
|
||||||
|
"merge": null
|
||||||
|
},
|
||||||
|
"detach_image_faces": {
|
||||||
|
"action": {
|
||||||
|
"detach": null,
|
||||||
|
"select_images": null
|
||||||
|
},
|
||||||
|
"description": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"merge_face_groups": {
|
||||||
|
"description": null,
|
||||||
|
"destination_table": {
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"move_image_faces": {
|
||||||
|
"description": null,
|
||||||
|
"destination_face_group_table": {
|
||||||
|
"move_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"image_select_table": {
|
||||||
|
"next_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recognize_unlabeled_faces_button": "Nicht zugeordnete Gesichter erkennen",
|
||||||
|
"table": {
|
||||||
|
"select_face_group": {
|
||||||
|
"search_faces_placeholder": null
|
||||||
|
},
|
||||||
|
"select_image_faces": {
|
||||||
|
"search_images_placeholder": null
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"photos_page": {
|
"photos_page": {
|
||||||
"title": "Fotos"
|
"title": "Fotos"
|
||||||
|
|
|
@ -68,10 +68,58 @@
|
||||||
},
|
},
|
||||||
"people_page": {
|
"people_page": {
|
||||||
"face_group": {
|
"face_group": {
|
||||||
"label_placeholder": "Label",
|
"action": {
|
||||||
"unlabeled": "Unlabeled"
|
"add_label": "Add Label",
|
||||||
|
"change_label": "Change Label",
|
||||||
|
"detach_face": "Detach Face",
|
||||||
|
"merge_face": "Merge Face",
|
||||||
|
"move_faces": "Move Faces"
|
||||||
},
|
},
|
||||||
"recognize_unlabeled_faces_button": "Recognize unlabeled faces"
|
"label_placeholder": "Label",
|
||||||
|
"unlabeled": "Unlabeled",
|
||||||
|
"unlabeled_person": "Unlabeled person"
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"action": {
|
||||||
|
"merge": "Merge"
|
||||||
|
},
|
||||||
|
"detach_image_faces": {
|
||||||
|
"action": {
|
||||||
|
"detach": "Detach image faces",
|
||||||
|
"select_images": "Select images to detach"
|
||||||
|
},
|
||||||
|
"description": "Detach selected images of this face group and move them to a new face groups",
|
||||||
|
"title": "Detach Image Faces"
|
||||||
|
},
|
||||||
|
"merge_face_groups": {
|
||||||
|
"description": "All images within this face group will be merged into the selected face group.",
|
||||||
|
"destination_table": {
|
||||||
|
"title": "Select the destination face"
|
||||||
|
},
|
||||||
|
"title": "Merge Face Groups"
|
||||||
|
},
|
||||||
|
"move_image_faces": {
|
||||||
|
"description": "Move selected images of this face group to another face group",
|
||||||
|
"destination_face_group_table": {
|
||||||
|
"move_action": "Move image faces",
|
||||||
|
"title": "Select destination face group"
|
||||||
|
},
|
||||||
|
"image_select_table": {
|
||||||
|
"next_action": "Next",
|
||||||
|
"title": "Select images to move"
|
||||||
|
},
|
||||||
|
"title": "Move Image Faces"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recognize_unlabeled_faces_button": "Recognize unlabeled faces",
|
||||||
|
"table": {
|
||||||
|
"select_face_group": {
|
||||||
|
"search_faces_placeholder": "Search faces..."
|
||||||
|
},
|
||||||
|
"select_image_faces": {
|
||||||
|
"search_images_placeholder": "Search images..."
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"photos_page": {
|
"photos_page": {
|
||||||
"title": "Photos"
|
"title": "Photos"
|
||||||
|
|
|
@ -68,10 +68,58 @@
|
||||||
},
|
},
|
||||||
"people_page": {
|
"people_page": {
|
||||||
"face_group": {
|
"face_group": {
|
||||||
"label_placeholder": "Etiqueta",
|
"action": {
|
||||||
"unlabeled": "Sin etiquetar"
|
"add_label": null,
|
||||||
|
"change_label": null,
|
||||||
|
"detach_face": null,
|
||||||
|
"merge_face": null,
|
||||||
|
"move_faces": null
|
||||||
},
|
},
|
||||||
"recognize_unlabeled_faces_button": "Reconocer caras sin etiquetar"
|
"label_placeholder": "Etiqueta",
|
||||||
|
"unlabeled": "Sin etiquetar",
|
||||||
|
"unlabeled_person": null
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"action": {
|
||||||
|
"merge": null
|
||||||
|
},
|
||||||
|
"detach_image_faces": {
|
||||||
|
"action": {
|
||||||
|
"detach": null,
|
||||||
|
"select_images": null
|
||||||
|
},
|
||||||
|
"description": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"merge_face_groups": {
|
||||||
|
"description": null,
|
||||||
|
"destination_table": {
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"move_image_faces": {
|
||||||
|
"description": null,
|
||||||
|
"destination_face_group_table": {
|
||||||
|
"move_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"image_select_table": {
|
||||||
|
"next_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recognize_unlabeled_faces_button": "Reconocer caras sin etiquetar",
|
||||||
|
"table": {
|
||||||
|
"select_face_group": {
|
||||||
|
"search_faces_placeholder": null
|
||||||
|
},
|
||||||
|
"select_image_faces": {
|
||||||
|
"search_images_placeholder": null
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"photos_page": {
|
"photos_page": {
|
||||||
"title": "Fotos"
|
"title": "Fotos"
|
||||||
|
|
|
@ -68,10 +68,58 @@
|
||||||
},
|
},
|
||||||
"people_page": {
|
"people_page": {
|
||||||
"face_group": {
|
"face_group": {
|
||||||
"label_placeholder": "Étiquette",
|
"action": {
|
||||||
"unlabeled": "Sans étiquette"
|
"add_label": null,
|
||||||
|
"change_label": null,
|
||||||
|
"detach_face": null,
|
||||||
|
"merge_face": null,
|
||||||
|
"move_faces": null
|
||||||
},
|
},
|
||||||
"recognize_unlabeled_faces_button": "Reconnaître les visages sans étiquette"
|
"label_placeholder": "Étiquette",
|
||||||
|
"unlabeled": "Sans étiquette",
|
||||||
|
"unlabeled_person": null
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"action": {
|
||||||
|
"merge": null
|
||||||
|
},
|
||||||
|
"detach_image_faces": {
|
||||||
|
"action": {
|
||||||
|
"detach": null,
|
||||||
|
"select_images": null
|
||||||
|
},
|
||||||
|
"description": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"merge_face_groups": {
|
||||||
|
"description": null,
|
||||||
|
"destination_table": {
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"move_image_faces": {
|
||||||
|
"description": null,
|
||||||
|
"destination_face_group_table": {
|
||||||
|
"move_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"image_select_table": {
|
||||||
|
"next_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recognize_unlabeled_faces_button": "Reconnaître les visages sans étiquette",
|
||||||
|
"table": {
|
||||||
|
"select_face_group": {
|
||||||
|
"search_faces_placeholder": null
|
||||||
|
},
|
||||||
|
"select_image_faces": {
|
||||||
|
"search_images_placeholder": null
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"photos_page": {
|
"photos_page": {
|
||||||
"title": "Photos"
|
"title": "Photos"
|
||||||
|
|
|
@ -68,10 +68,58 @@
|
||||||
},
|
},
|
||||||
"people_page": {
|
"people_page": {
|
||||||
"face_group": {
|
"face_group": {
|
||||||
"label_placeholder": "Etichetta",
|
"action": {
|
||||||
"unlabeled": "Senza etichetta"
|
"add_label": null,
|
||||||
|
"change_label": null,
|
||||||
|
"detach_face": null,
|
||||||
|
"merge_face": null,
|
||||||
|
"move_faces": null
|
||||||
},
|
},
|
||||||
"recognize_unlabeled_faces_button": "Identifica facce senza etichetta"
|
"label_placeholder": "Etichetta",
|
||||||
|
"unlabeled": "Senza etichetta",
|
||||||
|
"unlabeled_person": null
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"action": {
|
||||||
|
"merge": null
|
||||||
|
},
|
||||||
|
"detach_image_faces": {
|
||||||
|
"action": {
|
||||||
|
"detach": null,
|
||||||
|
"select_images": null
|
||||||
|
},
|
||||||
|
"description": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"merge_face_groups": {
|
||||||
|
"description": null,
|
||||||
|
"destination_table": {
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"move_image_faces": {
|
||||||
|
"description": null,
|
||||||
|
"destination_face_group_table": {
|
||||||
|
"move_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"image_select_table": {
|
||||||
|
"next_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recognize_unlabeled_faces_button": "Identifica facce senza etichetta",
|
||||||
|
"table": {
|
||||||
|
"select_face_group": {
|
||||||
|
"search_faces_placeholder": null
|
||||||
|
},
|
||||||
|
"select_image_faces": {
|
||||||
|
"search_images_placeholder": null
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"photos_page": {
|
"photos_page": {
|
||||||
"title": "Foto"
|
"title": "Foto"
|
||||||
|
|
|
@ -68,10 +68,58 @@
|
||||||
},
|
},
|
||||||
"people_page": {
|
"people_page": {
|
||||||
"face_group": {
|
"face_group": {
|
||||||
"label_placeholder": "Etykieta",
|
"action": {
|
||||||
"unlabeled": "Nieoznakowany"
|
"add_label": null,
|
||||||
|
"change_label": null,
|
||||||
|
"detach_face": null,
|
||||||
|
"merge_face": null,
|
||||||
|
"move_faces": null
|
||||||
},
|
},
|
||||||
"recognize_unlabeled_faces_button": "Rozpoznaj nieoznakowane twarze"
|
"label_placeholder": "Etykieta",
|
||||||
|
"unlabeled": "Nieoznakowany",
|
||||||
|
"unlabeled_person": null
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"action": {
|
||||||
|
"merge": null
|
||||||
|
},
|
||||||
|
"detach_image_faces": {
|
||||||
|
"action": {
|
||||||
|
"detach": null,
|
||||||
|
"select_images": null
|
||||||
|
},
|
||||||
|
"description": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"merge_face_groups": {
|
||||||
|
"description": null,
|
||||||
|
"destination_table": {
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"move_image_faces": {
|
||||||
|
"description": null,
|
||||||
|
"destination_face_group_table": {
|
||||||
|
"move_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"image_select_table": {
|
||||||
|
"next_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recognize_unlabeled_faces_button": "Rozpoznaj nieoznakowane twarze",
|
||||||
|
"table": {
|
||||||
|
"select_face_group": {
|
||||||
|
"search_faces_placeholder": null
|
||||||
|
},
|
||||||
|
"select_image_faces": {
|
||||||
|
"search_images_placeholder": null
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"photos_page": {
|
"photos_page": {
|
||||||
"title": "Zdjęcia"
|
"title": "Zdjęcia"
|
||||||
|
|
|
@ -68,10 +68,58 @@
|
||||||
},
|
},
|
||||||
"people_page": {
|
"people_page": {
|
||||||
"face_group": {
|
"face_group": {
|
||||||
"label_placeholder": "Märkning",
|
"action": {
|
||||||
"unlabeled": "Omärkt"
|
"add_label": null,
|
||||||
|
"change_label": null,
|
||||||
|
"detach_face": null,
|
||||||
|
"merge_face": null,
|
||||||
|
"move_faces": null
|
||||||
},
|
},
|
||||||
"recognize_unlabeled_faces_button": "Känna igen omärkta ansikten"
|
"label_placeholder": "Märkning",
|
||||||
|
"unlabeled": "Omärkt",
|
||||||
|
"unlabeled_person": null
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"action": {
|
||||||
|
"merge": null
|
||||||
|
},
|
||||||
|
"detach_image_faces": {
|
||||||
|
"action": {
|
||||||
|
"detach": null,
|
||||||
|
"select_images": null
|
||||||
|
},
|
||||||
|
"description": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"merge_face_groups": {
|
||||||
|
"description": null,
|
||||||
|
"destination_table": {
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"move_image_faces": {
|
||||||
|
"description": null,
|
||||||
|
"destination_face_group_table": {
|
||||||
|
"move_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"image_select_table": {
|
||||||
|
"next_action": null,
|
||||||
|
"title": null
|
||||||
|
},
|
||||||
|
"title": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recognize_unlabeled_faces_button": "Känna igen omärkta ansikten",
|
||||||
|
"table": {
|
||||||
|
"select_face_group": {
|
||||||
|
"search_faces_placeholder": null
|
||||||
|
},
|
||||||
|
"select_image_faces": {
|
||||||
|
"search_images_placeholder": null
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"photos_page": {
|
"photos_page": {
|
||||||
"title": "Bilder"
|
"title": "Bilder"
|
||||||
|
|
|
@ -1,10 +1,23 @@
|
||||||
import { gql, useMutation } from '@apollo/client'
|
import { gql, useMutation } from '@apollo/client'
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
import { Button, Modal } from 'semantic-ui-react'
|
import { Button, Modal } from 'semantic-ui-react'
|
||||||
|
import { isNil } from '../../../helpers/utils'
|
||||||
import { MY_FACES_QUERY } from '../PeoplePage'
|
import { MY_FACES_QUERY } from '../PeoplePage'
|
||||||
|
import {
|
||||||
|
myFaces_myFaceGroups,
|
||||||
|
myFaces_myFaceGroups_imageFaces,
|
||||||
|
} from '../__generated__/myFaces'
|
||||||
import SelectImageFacesTable from './SelectImageFacesTable'
|
import SelectImageFacesTable from './SelectImageFacesTable'
|
||||||
|
import {
|
||||||
|
detachImageFaces,
|
||||||
|
detachImageFacesVariables,
|
||||||
|
} from './__generated__/detachImageFaces'
|
||||||
|
import {
|
||||||
|
singleFaceGroup_faceGroup,
|
||||||
|
singleFaceGroup_faceGroup_imageFaces,
|
||||||
|
} from './__generated__/singleFaceGroup'
|
||||||
|
|
||||||
const DETACH_IMAGE_FACES_MUTATION = gql`
|
const DETACH_IMAGE_FACES_MUTATION = gql`
|
||||||
mutation detachImageFaces($faceIDs: [ID!]!) {
|
mutation detachImageFaces($faceIDs: [ID!]!) {
|
||||||
|
@ -15,12 +28,28 @@ const DETACH_IMAGE_FACES_MUTATION = gql`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const DetachImageFacesModal = ({ open, setOpen, faceGroup }) => {
|
type DetachImageFacesModalProps = {
|
||||||
const [selectedImageFaces, setSelectedImageFaces] = useState([])
|
open: boolean
|
||||||
let history = useHistory()
|
setOpen(open: boolean): void
|
||||||
|
faceGroup: myFaces_myFaceGroups | singleFaceGroup_faceGroup
|
||||||
|
}
|
||||||
|
|
||||||
const [detachImageFacesMutation] = useMutation(DETACH_IMAGE_FACES_MUTATION, {
|
const DetachImageFacesModal = ({
|
||||||
variables: {},
|
open,
|
||||||
|
setOpen,
|
||||||
|
faceGroup,
|
||||||
|
}: DetachImageFacesModalProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const [selectedImageFaces, setSelectedImageFaces] = useState<
|
||||||
|
(myFaces_myFaceGroups_imageFaces | singleFaceGroup_faceGroup_imageFaces)[]
|
||||||
|
>([])
|
||||||
|
const history = useHistory()
|
||||||
|
|
||||||
|
const [detachImageFacesMutation] = useMutation<
|
||||||
|
detachImageFaces,
|
||||||
|
detachImageFacesVariables
|
||||||
|
>(DETACH_IMAGE_FACES_MUTATION, {
|
||||||
refetchQueries: [
|
refetchQueries: [
|
||||||
{
|
{
|
||||||
query: MY_FACES_QUERY,
|
query: MY_FACES_QUERY,
|
||||||
|
@ -44,6 +73,7 @@ const DetachImageFacesModal = ({ open, setOpen, faceGroup }) => {
|
||||||
faceIDs,
|
faceIDs,
|
||||||
},
|
},
|
||||||
}).then(({ data }) => {
|
}).then(({ data }) => {
|
||||||
|
if (isNil(data)) throw new Error('Expected data not to be null')
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
history.push(`/people/${data.detachImageFaces.id}`)
|
history.push(`/people/${data.detachImageFaces.id}`)
|
||||||
})
|
})
|
||||||
|
@ -57,18 +87,25 @@ const DetachImageFacesModal = ({ open, setOpen, faceGroup }) => {
|
||||||
onOpen={() => setOpen(true)}
|
onOpen={() => setOpen(true)}
|
||||||
open={open}
|
open={open}
|
||||||
>
|
>
|
||||||
<Modal.Header>Detach Image Faces</Modal.Header>
|
<Modal.Header>
|
||||||
|
{t('people_page.modal.detach_image_faces.title', 'Detach Image Faces')}
|
||||||
|
</Modal.Header>
|
||||||
<Modal.Content scrolling>
|
<Modal.Content scrolling>
|
||||||
<Modal.Description>
|
<Modal.Description>
|
||||||
<p>
|
<p>
|
||||||
Detach selected images of this face group and move them to a new
|
{t(
|
||||||
face group
|
'people_page.modal.detach_image_faces.description',
|
||||||
|
'Detach selected images of this face group and move them to a new face groups'
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
<SelectImageFacesTable
|
<SelectImageFacesTable
|
||||||
imageFaces={imageFaces}
|
imageFaces={imageFaces}
|
||||||
selectedImageFaces={selectedImageFaces}
|
selectedImageFaces={selectedImageFaces}
|
||||||
setSelectedImageFaces={setSelectedImageFaces}
|
setSelectedImageFaces={setSelectedImageFaces}
|
||||||
title="Select images to detach"
|
title={t(
|
||||||
|
'people_page.modal.detach_image_faces.action.select_images',
|
||||||
|
'Select images to detach'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Modal.Description>
|
</Modal.Description>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
|
@ -76,7 +113,10 @@ const DetachImageFacesModal = ({ open, setOpen, faceGroup }) => {
|
||||||
<Button onClick={() => setOpen(false)}>Cancel</Button>
|
<Button onClick={() => setOpen(false)}>Cancel</Button>
|
||||||
<Button
|
<Button
|
||||||
disabled={selectedImageFaces.length == 0}
|
disabled={selectedImageFaces.length == 0}
|
||||||
content="Detach image faces"
|
content={t(
|
||||||
|
'people_page.modal.detach_image_faces.action.detach',
|
||||||
|
'Detach image faces'
|
||||||
|
)}
|
||||||
labelPosition="right"
|
labelPosition="right"
|
||||||
icon="checkmark"
|
icon="checkmark"
|
||||||
onClick={() => detachImageFaces()}
|
onClick={() => detachImageFaces()}
|
||||||
|
@ -87,10 +127,4 @@ const DetachImageFacesModal = ({ open, setOpen, faceGroup }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
DetachImageFacesModal.propTypes = {
|
|
||||||
open: PropTypes.bool.isRequired,
|
|
||||||
setOpen: PropTypes.func.isRequired,
|
|
||||||
faceGroup: PropTypes.object,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DetachImageFacesModal
|
export default DetachImageFacesModal
|
|
@ -1,5 +1,6 @@
|
||||||
import { useMutation } from '@apollo/client'
|
import { useMutation } from '@apollo/client'
|
||||||
import React, { useState, useEffect, createRef } from 'react'
|
import React, { useState, useEffect, createRef } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Dropdown, Input } from 'semantic-ui-react'
|
import { Dropdown, Input } from 'semantic-ui-react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { isNil } from '../../../helpers/utils'
|
import { isNil } from '../../../helpers/utils'
|
||||||
|
@ -38,6 +39,8 @@ type FaceGroupTitleProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const FaceGroupTitle = ({ faceGroup }: FaceGroupTitleProps) => {
|
const FaceGroupTitle = ({ faceGroup }: FaceGroupTitleProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const [editLabel, setEditLabel] = useState(false)
|
const [editLabel, setEditLabel] = useState(false)
|
||||||
const [inputValue, setInputValue] = useState(faceGroup?.label ?? '')
|
const [inputValue, setInputValue] = useState(faceGroup?.label ?? '')
|
||||||
const inputRef = createRef<Input>()
|
const inputRef = createRef<Input>()
|
||||||
|
@ -91,7 +94,8 @@ const FaceGroupTitle = ({ faceGroup }: FaceGroupTitleProps) => {
|
||||||
title = (
|
title = (
|
||||||
<TitleWrapper>
|
<TitleWrapper>
|
||||||
<TitleLabel labeled={!!faceGroup?.label}>
|
<TitleLabel labeled={!!faceGroup?.label}>
|
||||||
{faceGroup?.label ?? 'Unlabeled person'}
|
{faceGroup?.label ??
|
||||||
|
t('people_page.face_group.unlabeled_person', 'Unlabeled person')}
|
||||||
</TitleLabel>
|
</TitleLabel>
|
||||||
<TitleDropdown
|
<TitleDropdown
|
||||||
icon={{
|
icon={{
|
||||||
|
@ -102,22 +106,32 @@ const FaceGroupTitle = ({ faceGroup }: FaceGroupTitleProps) => {
|
||||||
<Dropdown.Menu>
|
<Dropdown.Menu>
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
icon="pencil"
|
icon="pencil"
|
||||||
text={faceGroup?.label ? 'Change Label' : 'Add Label'}
|
text={
|
||||||
|
faceGroup?.label
|
||||||
|
? t(
|
||||||
|
'people_page.face_group.action.change_label',
|
||||||
|
'Change Label'
|
||||||
|
)
|
||||||
|
: t('people_page.face_group.action.add_label', 'Add Label')
|
||||||
|
}
|
||||||
onClick={() => setEditLabel(true)}
|
onClick={() => setEditLabel(true)}
|
||||||
/>
|
/>
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
icon="object group"
|
icon="object group"
|
||||||
text="Merge Face"
|
text={t('people_page.face_group.action.merge_face', 'Merge Face')}
|
||||||
onClick={() => setMergeModalOpen(true)}
|
onClick={() => setMergeModalOpen(true)}
|
||||||
/>
|
/>
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
icon="object ungroup"
|
icon="object ungroup"
|
||||||
text="Detach Faces"
|
text={t(
|
||||||
|
'people_page.face_group.action.detach_face',
|
||||||
|
'Detach Face'
|
||||||
|
)}
|
||||||
onClick={() => setDetachModalOpen(true)}
|
onClick={() => setDetachModalOpen(true)}
|
||||||
/>
|
/>
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
icon="clone"
|
icon="clone"
|
||||||
text="Move Faces"
|
text={t('people_page.face_group.action.move_faces', 'Move Faces')}
|
||||||
onClick={() => setMoveModalOpen(true)}
|
onClick={() => setMoveModalOpen(true)}
|
||||||
/>
|
/>
|
||||||
</Dropdown.Menu>
|
</Dropdown.Menu>
|
||||||
|
@ -130,7 +144,7 @@ const FaceGroupTitle = ({ faceGroup }: FaceGroupTitleProps) => {
|
||||||
<Input
|
<Input
|
||||||
loading={setLabelLoading}
|
loading={setLabelLoading}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
placeholder="Label"
|
placeholder={t('people_page.face_group.label_placeholder', 'Label')}
|
||||||
icon="arrow right"
|
icon="arrow right"
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
onKeyUp={onKeyUp}
|
onKeyUp={onKeyUp}
|
||||||
|
@ -143,9 +157,10 @@ const FaceGroupTitle = ({ faceGroup }: FaceGroupTitleProps) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
let modals = null
|
||||||
|
if (faceGroup) {
|
||||||
|
modals = (
|
||||||
<>
|
<>
|
||||||
{title}
|
|
||||||
<MergeFaceGroupsModal
|
<MergeFaceGroupsModal
|
||||||
open={mergeModalOpen}
|
open={mergeModalOpen}
|
||||||
setOpen={setMergeModalOpen}
|
setOpen={setMergeModalOpen}
|
||||||
|
@ -163,6 +178,14 @@ const FaceGroupTitle = ({ faceGroup }: FaceGroupTitleProps) => {
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{title}
|
||||||
|
{modals}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FaceGroupTitle
|
export default FaceGroupTitle
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
import { gql, useMutation, useQuery } from '@apollo/client'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import React, { useState } from 'react'
|
|
||||||
import { useHistory } from 'react-router-dom'
|
|
||||||
import { Button, Modal } from 'semantic-ui-react'
|
|
||||||
import { MY_FACES_QUERY } from '../PeoplePage'
|
|
||||||
import SelectFaceGroupTable from './SelectFaceGroupTable'
|
|
||||||
|
|
||||||
const COMBINE_FACES_MUTATION = gql`
|
|
||||||
mutation combineFaces($destID: ID!, $srcID: ID!) {
|
|
||||||
combineFaceGroups(
|
|
||||||
destinationFaceGroupID: $destID
|
|
||||||
sourceFaceGroupID: $srcID
|
|
||||||
) {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const MergeFaceGroupsModal = ({ open, setOpen, sourceFaceGroup }) => {
|
|
||||||
const [selectedFaceGroup, setSelectedFaceGroup] = useState(null)
|
|
||||||
|
|
||||||
let history = useHistory()
|
|
||||||
const { data } = useQuery(MY_FACES_QUERY)
|
|
||||||
const [combineFacesMutation] = useMutation(COMBINE_FACES_MUTATION, {
|
|
||||||
variables: {
|
|
||||||
srcID: sourceFaceGroup?.id,
|
|
||||||
},
|
|
||||||
refetchQueries: [
|
|
||||||
{
|
|
||||||
query: MY_FACES_QUERY,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
if (open == false) return null
|
|
||||||
|
|
||||||
const filteredFaceGroups =
|
|
||||||
data?.myFaceGroups.filter(x => x.id != sourceFaceGroup?.id) ?? []
|
|
||||||
|
|
||||||
const mergeFaceGroups = () => {
|
|
||||||
combineFacesMutation({
|
|
||||||
variables: {
|
|
||||||
destID: selectedFaceGroup.id,
|
|
||||||
},
|
|
||||||
}).then(() => {
|
|
||||||
setOpen(false)
|
|
||||||
history.push(`/people/${selectedFaceGroup.id}`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
onClose={() => setOpen(false)}
|
|
||||||
onOpen={() => setOpen(true)}
|
|
||||||
open={open}
|
|
||||||
>
|
|
||||||
<Modal.Header>Merge Face Groups</Modal.Header>
|
|
||||||
<Modal.Content scrolling>
|
|
||||||
<Modal.Description>
|
|
||||||
<p>
|
|
||||||
All images within this face group will be merged into the selected
|
|
||||||
face group.
|
|
||||||
</p>
|
|
||||||
<SelectFaceGroupTable
|
|
||||||
title="Select the destination face"
|
|
||||||
faceGroups={filteredFaceGroups}
|
|
||||||
selectedFaceGroup={selectedFaceGroup}
|
|
||||||
setSelectedFaceGroup={setSelectedFaceGroup}
|
|
||||||
/>
|
|
||||||
</Modal.Description>
|
|
||||||
</Modal.Content>
|
|
||||||
<Modal.Actions>
|
|
||||||
<Button onClick={() => setOpen(false)}>Cancel</Button>
|
|
||||||
<Button
|
|
||||||
disabled={selectedFaceGroup == null}
|
|
||||||
content="Merge"
|
|
||||||
labelPosition="right"
|
|
||||||
icon="checkmark"
|
|
||||||
onClick={() => mergeFaceGroups()}
|
|
||||||
positive
|
|
||||||
/>
|
|
||||||
</Modal.Actions>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
MergeFaceGroupsModal.propTypes = {
|
|
||||||
open: PropTypes.bool.isRequired,
|
|
||||||
setOpen: PropTypes.func.isRequired,
|
|
||||||
sourceFaceGroup: PropTypes.object,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MergeFaceGroupsModal
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
import { gql, useMutation, useQuery } from '@apollo/client'
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useHistory } from 'react-router-dom'
|
||||||
|
import { Button, Modal } from 'semantic-ui-react'
|
||||||
|
import { isNil } from '../../../helpers/utils'
|
||||||
|
import { MY_FACES_QUERY } from '../PeoplePage'
|
||||||
|
import {
|
||||||
|
myFaces,
|
||||||
|
myFacesVariables,
|
||||||
|
myFaces_myFaceGroups,
|
||||||
|
} from '../__generated__/myFaces'
|
||||||
|
import SelectFaceGroupTable from './SelectFaceGroupTable'
|
||||||
|
import {
|
||||||
|
combineFaces,
|
||||||
|
combineFacesVariables,
|
||||||
|
} from './__generated__/combineFaces'
|
||||||
|
import { singleFaceGroup_faceGroup } from './__generated__/singleFaceGroup'
|
||||||
|
|
||||||
|
const COMBINE_FACES_MUTATION = gql`
|
||||||
|
mutation combineFaces($destID: ID!, $srcID: ID!) {
|
||||||
|
combineFaceGroups(
|
||||||
|
destinationFaceGroupID: $destID
|
||||||
|
sourceFaceGroupID: $srcID
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
type MergeFaceGroupsModalProps = {
|
||||||
|
open: boolean
|
||||||
|
setOpen(open: boolean): void
|
||||||
|
sourceFaceGroup: myFaces_myFaceGroups | singleFaceGroup_faceGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
const MergeFaceGroupsModal = ({
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
|
sourceFaceGroup,
|
||||||
|
}: MergeFaceGroupsModalProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const [selectedFaceGroup, setSelectedFaceGroup] =
|
||||||
|
useState<myFaces_myFaceGroups | singleFaceGroup_faceGroup | null>(null)
|
||||||
|
|
||||||
|
const history = useHistory()
|
||||||
|
const { data } = useQuery<myFaces, myFacesVariables>(MY_FACES_QUERY)
|
||||||
|
const [combineFacesMutation] = useMutation<
|
||||||
|
combineFaces,
|
||||||
|
combineFacesVariables
|
||||||
|
>(COMBINE_FACES_MUTATION, {
|
||||||
|
refetchQueries: [
|
||||||
|
{
|
||||||
|
query: MY_FACES_QUERY,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
if (open == false) return null
|
||||||
|
|
||||||
|
const filteredFaceGroups =
|
||||||
|
data?.myFaceGroups.filter(x => x.id != sourceFaceGroup?.id) ?? []
|
||||||
|
|
||||||
|
const mergeFaceGroups = () => {
|
||||||
|
if (isNil(selectedFaceGroup)) throw new Error('No selected face group')
|
||||||
|
|
||||||
|
combineFacesMutation({
|
||||||
|
variables: {
|
||||||
|
srcID: sourceFaceGroup.id,
|
||||||
|
destID: selectedFaceGroup.id,
|
||||||
|
},
|
||||||
|
}).then(() => {
|
||||||
|
setOpen(false)
|
||||||
|
history.push(`/people/${selectedFaceGroup.id}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
onClose={() => setOpen(false)}
|
||||||
|
onOpen={() => setOpen(true)}
|
||||||
|
open={open}
|
||||||
|
>
|
||||||
|
<Modal.Header>
|
||||||
|
{t('people_page.modal.merge_face_groups.title', 'Merge Face Groups')}
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Content scrolling>
|
||||||
|
<Modal.Description>
|
||||||
|
<p>
|
||||||
|
{t(
|
||||||
|
'people_page.modal.merge_face_groups.description',
|
||||||
|
'All images within this face group will be merged into the selected face group.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<SelectFaceGroupTable
|
||||||
|
title={t(
|
||||||
|
'people_page.modal.merge_face_groups.destination_table.title',
|
||||||
|
'Select the destination face'
|
||||||
|
)}
|
||||||
|
faceGroups={filteredFaceGroups}
|
||||||
|
selectedFaceGroup={selectedFaceGroup}
|
||||||
|
setSelectedFaceGroup={setSelectedFaceGroup}
|
||||||
|
/>
|
||||||
|
</Modal.Description>
|
||||||
|
</Modal.Content>
|
||||||
|
<Modal.Actions>
|
||||||
|
<Button onClick={() => setOpen(false)}>
|
||||||
|
{t('general.action.cancel', 'Cancel')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
disabled={selectedFaceGroup == null}
|
||||||
|
content={t('people_page.modal.action.merge', 'Merge')}
|
||||||
|
labelPosition="right"
|
||||||
|
icon="checkmark"
|
||||||
|
onClick={() => mergeFaceGroups()}
|
||||||
|
positive
|
||||||
|
/>
|
||||||
|
</Modal.Actions>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MergeFaceGroupsModal
|
|
@ -20,6 +20,7 @@ import {
|
||||||
moveImageFaces,
|
moveImageFaces,
|
||||||
moveImageFacesVariables,
|
moveImageFacesVariables,
|
||||||
} from './__generated__/moveImageFaces'
|
} from './__generated__/moveImageFaces'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const MOVE_IMAGE_FACES_MUTATION = gql`
|
const MOVE_IMAGE_FACES_MUTATION = gql`
|
||||||
mutation moveImageFaces($faceIDs: [ID!]!, $destFaceGroupID: ID!) {
|
mutation moveImageFaces($faceIDs: [ID!]!, $destFaceGroupID: ID!) {
|
||||||
|
@ -38,7 +39,7 @@ const MOVE_IMAGE_FACES_MUTATION = gql`
|
||||||
type MoveImageFacesModalProps = {
|
type MoveImageFacesModalProps = {
|
||||||
open: boolean
|
open: boolean
|
||||||
setOpen: React.Dispatch<React.SetStateAction<boolean>>
|
setOpen: React.Dispatch<React.SetStateAction<boolean>>
|
||||||
faceGroup?: singleFaceGroup_faceGroup
|
faceGroup: singleFaceGroup_faceGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
const MoveImageFacesModal = ({
|
const MoveImageFacesModal = ({
|
||||||
|
@ -46,6 +47,8 @@ const MoveImageFacesModal = ({
|
||||||
setOpen,
|
setOpen,
|
||||||
faceGroup,
|
faceGroup,
|
||||||
}: MoveImageFacesModalProps) => {
|
}: MoveImageFacesModalProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const [selectedImageFaces, setSelectedImageFaces] = useState<
|
const [selectedImageFaces, setSelectedImageFaces] = useState<
|
||||||
(singleFaceGroup_faceGroup_imageFaces | myFaces_myFaceGroups_imageFaces)[]
|
(singleFaceGroup_faceGroup_imageFaces | myFaces_myFaceGroups_imageFaces)[]
|
||||||
>([])
|
>([])
|
||||||
|
@ -102,7 +105,7 @@ const MoveImageFacesModal = ({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageFaces = faceGroup?.imageFaces ?? []
|
const imageFaces = faceGroup.imageFaces
|
||||||
|
|
||||||
let table = null
|
let table = null
|
||||||
if (!imagesSelected) {
|
if (!imagesSelected) {
|
||||||
|
@ -111,7 +114,10 @@ const MoveImageFacesModal = ({
|
||||||
imageFaces={imageFaces}
|
imageFaces={imageFaces}
|
||||||
selectedImageFaces={selectedImageFaces}
|
selectedImageFaces={selectedImageFaces}
|
||||||
setSelectedImageFaces={setSelectedImageFaces}
|
setSelectedImageFaces={setSelectedImageFaces}
|
||||||
title="Select images to move"
|
title={t(
|
||||||
|
'people_page.modal.move_image_faces.image_select_table.title',
|
||||||
|
'Select images to move'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -121,14 +127,17 @@ const MoveImageFacesModal = ({
|
||||||
)
|
)
|
||||||
table = (
|
table = (
|
||||||
<SelectFaceGroupTable
|
<SelectFaceGroupTable
|
||||||
title="Select destination face group"
|
title={t(
|
||||||
|
'people_page.modal.move_image_faces.destination_face_group_table.title',
|
||||||
|
'Select destination face group'
|
||||||
|
)}
|
||||||
faceGroups={filteredFaceGroups}
|
faceGroups={filteredFaceGroups}
|
||||||
selectedFaceGroup={selectedFaceGroup}
|
selectedFaceGroup={selectedFaceGroup}
|
||||||
setSelectedFaceGroup={setSelectedFaceGroup}
|
setSelectedFaceGroup={setSelectedFaceGroup}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
table = <div>Loading...</div>
|
table = <div>{t('general.loading.default', 'Loading...')}</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +146,10 @@ const MoveImageFacesModal = ({
|
||||||
positiveButton = (
|
positiveButton = (
|
||||||
<Button
|
<Button
|
||||||
disabled={selectedImageFaces.length == 0}
|
disabled={selectedImageFaces.length == 0}
|
||||||
content="Next"
|
content={t(
|
||||||
|
'people_page.modal.move_image_faces.image_select_table.next_action',
|
||||||
|
'Next'
|
||||||
|
)}
|
||||||
labelPosition="right"
|
labelPosition="right"
|
||||||
icon="arrow right"
|
icon="arrow right"
|
||||||
onClick={() => setImagesSelected(true)}
|
onClick={() => setImagesSelected(true)}
|
||||||
|
@ -148,7 +160,10 @@ const MoveImageFacesModal = ({
|
||||||
positiveButton = (
|
positiveButton = (
|
||||||
<Button
|
<Button
|
||||||
disabled={!selectedFaceGroup}
|
disabled={!selectedFaceGroup}
|
||||||
content="Move image faces"
|
content={t(
|
||||||
|
'people_page.modal.move_image_faces.destination_face_group_table.move_action',
|
||||||
|
'Move image faces'
|
||||||
|
)}
|
||||||
labelPosition="right"
|
labelPosition="right"
|
||||||
icon="checkmark"
|
icon="checkmark"
|
||||||
onClick={() => moveImageFaces()}
|
onClick={() => moveImageFaces()}
|
||||||
|
@ -163,15 +178,24 @@ const MoveImageFacesModal = ({
|
||||||
onOpen={() => setOpen(true)}
|
onOpen={() => setOpen(true)}
|
||||||
open={open}
|
open={open}
|
||||||
>
|
>
|
||||||
<Modal.Header>Move Image Faces</Modal.Header>
|
<Modal.Header>
|
||||||
|
{t('people_page.modal.move_image_faces.title', 'Move Image Faces')}
|
||||||
|
</Modal.Header>
|
||||||
<Modal.Content scrolling>
|
<Modal.Content scrolling>
|
||||||
<Modal.Description>
|
<Modal.Description>
|
||||||
<p>Move selected images of this face group to another face group</p>
|
<p>
|
||||||
|
{t(
|
||||||
|
'people_page.modal.move_image_faces.description',
|
||||||
|
'Move selected images of this face group to another face group'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
{table}
|
{table}
|
||||||
</Modal.Description>
|
</Modal.Description>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
<Modal.Actions>
|
<Modal.Actions>
|
||||||
<Button onClick={() => setOpen(false)}>Cancel</Button>
|
<Button onClick={() => setOpen(false)}>
|
||||||
|
{t('general.action.cancel', 'Cancel')}
|
||||||
|
</Button>
|
||||||
{positiveButton}
|
{positiveButton}
|
||||||
</Modal.Actions>
|
</Modal.Actions>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Input, Pagination, Table } from 'semantic-ui-react'
|
import { Input, Pagination, Table } from 'semantic-ui-react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import FaceCircleImage from '../FaceCircleImage'
|
import FaceCircleImage from '../FaceCircleImage'
|
||||||
|
@ -66,6 +67,8 @@ const SelectFaceGroupTable = ({
|
||||||
setSelectedFaceGroup,
|
setSelectedFaceGroup,
|
||||||
title,
|
title,
|
||||||
}: SelectFaceGroupTableProps) => {
|
}: SelectFaceGroupTableProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const PAGE_SIZE = 6
|
const PAGE_SIZE = 6
|
||||||
|
|
||||||
const [page, setPage] = useState(0)
|
const [page, setPage] = useState(0)
|
||||||
|
@ -106,7 +109,10 @@ const SelectFaceGroupTable = ({
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
onChange={e => setSearchValue(e.target.value)}
|
onChange={e => setSearchValue(e.target.value)}
|
||||||
icon="search"
|
icon="search"
|
||||||
placeholder="Search faces..."
|
placeholder={t(
|
||||||
|
'people_page.table.select_face_group.search_faces_placeholder',
|
||||||
|
'Search faces...'
|
||||||
|
)}
|
||||||
fluid
|
fluid
|
||||||
/>
|
/>
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Checkbox, Input, Pagination, Table } from 'semantic-ui-react'
|
import { Checkbox, Input, Pagination, Table } from 'semantic-ui-react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { ProtectedImage } from '../../../components/photoGallery/ProtectedMedia'
|
import { ProtectedImage } from '../../../components/photoGallery/ProtectedMedia'
|
||||||
|
@ -67,6 +68,8 @@ const SelectImageFacesTable = ({
|
||||||
setSelectedImageFaces,
|
setSelectedImageFaces,
|
||||||
title,
|
title,
|
||||||
}: SelectImageFacesTable) => {
|
}: SelectImageFacesTable) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const PAGE_SIZE = 6
|
const PAGE_SIZE = 6
|
||||||
|
|
||||||
const [page, setPage] = useState(0)
|
const [page, setPage] = useState(0)
|
||||||
|
@ -115,7 +118,10 @@ const SelectImageFacesTable = ({
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
onChange={e => setSearchValue(e.target.value)}
|
onChange={e => setSearchValue(e.target.value)}
|
||||||
icon="search"
|
icon="search"
|
||||||
placeholder="Search images..."
|
placeholder={t(
|
||||||
|
'people_page.table.select_image_faces.search_images_placeholder',
|
||||||
|
'Search images...'
|
||||||
|
)}
|
||||||
fluid
|
fluid
|
||||||
/>
|
/>
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { gql, useQuery } from '@apollo/client'
|
import { gql, useQuery } from '@apollo/client'
|
||||||
import React, { useEffect, useReducer } from 'react'
|
import React, { useEffect, useReducer } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import PaginateLoader from '../../../components/PaginateLoader'
|
import PaginateLoader from '../../../components/PaginateLoader'
|
||||||
import PhotoGallery from '../../../components/photoGallery/PhotoGallery'
|
import PhotoGallery from '../../../components/photoGallery/PhotoGallery'
|
||||||
import { photoGalleryReducer } from '../../../components/photoGallery/photoGalleryReducer'
|
import { photoGalleryReducer } from '../../../components/photoGallery/photoGalleryReducer'
|
||||||
|
@ -47,6 +48,8 @@ type SingleFaceGroupProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SingleFaceGroup = ({ faceGroupID }: SingleFaceGroupProps) => {
|
const SingleFaceGroup = ({ faceGroupID }: SingleFaceGroupProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const { data, error, loading, fetchMore } = useQuery<
|
const { data, error, loading, fetchMore } = useQuery<
|
||||||
singleFaceGroup,
|
singleFaceGroup,
|
||||||
singleFaceGroupVariables
|
singleFaceGroupVariables
|
||||||
|
@ -94,7 +97,7 @@ const SingleFaceGroup = ({ faceGroupID }: SingleFaceGroupProps) => {
|
||||||
/>
|
/>
|
||||||
<PaginateLoader
|
<PaginateLoader
|
||||||
active={!finishedLoadingMore && !loading}
|
active={!finishedLoadingMore && !loading}
|
||||||
text="Loading more photos"
|
text={t('general.loading.paginate.media', 'Loading more media')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue