mirror of
https://github.com/gramps-project/gramps-web.git
synced 2026-01-06 05:40:09 -06:00
Create persons from family view (#841)
* Allow creating new person in children table * WIP: allow creating new person for parent * Allow creating new person for parent * WIP: allow creating new persons from new familiy view * Remove select object list * Revert changes on new family view * Align unlink icon with text * Fix margin around parents * Adjust margin * Remove parent labels
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import {html} from 'lit'
|
||||
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-icon-button'
|
||||
import {mdiGenderFemale, mdiGenderMale} from '@mdi/js'
|
||||
import {GrampsjsEditableTable} from './GrampsjsEditableTable.js'
|
||||
import './GrampsjsFormChildRef.js'
|
||||
import {renderIcon} from '../icons.js'
|
||||
import {fireEvent} from '../util.js'
|
||||
|
||||
import '@material/mwc-icon-button'
|
||||
import '@material/mwc-button'
|
||||
import {GrampsjsEditableTable} from './GrampsjsEditableTable.js'
|
||||
import './GrampsjsFormChildRef.js'
|
||||
import './GrampsjsFormNewChild.js'
|
||||
|
||||
function genderIcon(gender) {
|
||||
if (gender === 'M') {
|
||||
@@ -24,6 +24,7 @@ export class GrampsjsChildren extends GrampsjsEditableTable {
|
||||
return {
|
||||
profile: {type: Array},
|
||||
highlightId: {type: String},
|
||||
dialogContent: {type: String},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,21 +60,26 @@ export class GrampsjsChildren extends GrampsjsEditableTable {
|
||||
return this.edit
|
||||
? html`
|
||||
<mwc-icon-button
|
||||
class="edit large"
|
||||
icon="add_circle"
|
||||
@click="${this._handleAddClick}"
|
||||
class="edit"
|
||||
icon="add_link"
|
||||
@click="${this._handleShare}"
|
||||
></mwc-icon-button>
|
||||
<mwc-icon-button
|
||||
class="edit"
|
||||
icon="add"
|
||||
@click="${this._handleAdd}"
|
||||
></mwc-icon-button>
|
||||
${this.dialogContent}
|
||||
`
|
||||
: ''
|
||||
}
|
||||
|
||||
_handleAddClick() {
|
||||
_handleShare() {
|
||||
this.dialogContent = html`
|
||||
<grampsjs-form-childref
|
||||
new
|
||||
@object:save="${this._handleChildRefSave}"
|
||||
@object:cancel="${this._handleChildRefCancel}"
|
||||
@object:cancel="${this._handleDialogCancel}"
|
||||
.appState="${this.appState}"
|
||||
objType="${this.objType}"
|
||||
dialogTitle=${this._('Add existing child to family')}
|
||||
@@ -82,6 +88,28 @@ export class GrampsjsChildren extends GrampsjsEditableTable {
|
||||
`
|
||||
}
|
||||
|
||||
_handleAdd() {
|
||||
this.dialogContent = html`
|
||||
<grampsjs-form-new-child
|
||||
@object:save="${this._handleNewChildSave}"
|
||||
@object:cancel="${this._handleDialogCancel}"
|
||||
.appState="${this.appState}"
|
||||
dialogTitle="${this._('Add a new person')}"
|
||||
>
|
||||
</grampsjs-form-new-child>
|
||||
`
|
||||
}
|
||||
|
||||
_handleNewChildSave(e) {
|
||||
fireEvent(this, 'edit:action', {
|
||||
action: 'newChild',
|
||||
data: e.detail.data,
|
||||
})
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
this.dialogContent = ''
|
||||
}
|
||||
|
||||
_handleChildRefSave(e) {
|
||||
fireEvent(this, 'edit:action', {action: 'addChildRef', data: e.detail.data})
|
||||
e.preventDefault()
|
||||
@@ -89,7 +117,7 @@ export class GrampsjsChildren extends GrampsjsEditableTable {
|
||||
this.dialogContent = ''
|
||||
}
|
||||
|
||||
_handleChildRefCancel() {
|
||||
_handleDialogCancel() {
|
||||
this.dialogContent = ''
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import {html, css} from 'lit'
|
||||
import {css, html} from 'lit'
|
||||
|
||||
import '@material/mwc-icon'
|
||||
|
||||
import {GrampsjsObject} from './GrampsjsObject.js'
|
||||
import {ringsIcon} from '../icons.js'
|
||||
import {renderPerson, fireEvent} from '../util.js'
|
||||
import {fireEvent, renderPerson} from '../util.js'
|
||||
import './GrampsjsFormEditFamily.js'
|
||||
import './GrampsjsFormNewPerson.js'
|
||||
import './GrampsjsFormPersonRef.js'
|
||||
import {GrampsjsObject} from './GrampsjsObject.js'
|
||||
|
||||
export class GrampsjsFamily extends GrampsjsObject {
|
||||
static get styles() {
|
||||
@@ -13,6 +15,19 @@ export class GrampsjsFamily extends GrampsjsObject {
|
||||
super.styles,
|
||||
css`
|
||||
:host {
|
||||
.items-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.parent {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.relationship-type {
|
||||
margin-top: 2em;
|
||||
}
|
||||
}
|
||||
`,
|
||||
]
|
||||
@@ -29,7 +44,11 @@ export class GrampsjsFamily extends GrampsjsObject {
|
||||
renderProfile() {
|
||||
return html`
|
||||
<h2>${this._renderTitle()}</h2>
|
||||
${this._renderFather()} ${this._renderMother()}
|
||||
${this._renderParent('father')} ${this._renderParent('mother')}
|
||||
<div class="relationship-type">
|
||||
${this._renderRelType()} ${this._renderMarriage()}
|
||||
${this._renderDivorce()}
|
||||
</div>
|
||||
${this.edit
|
||||
? html`
|
||||
<mwc-icon-button
|
||||
@@ -39,10 +58,6 @@ export class GrampsjsFamily extends GrampsjsObject {
|
||||
></mwc-icon-button>
|
||||
`
|
||||
: ''}
|
||||
<p>
|
||||
${this._renderRelType()} ${this._renderMarriage()}
|
||||
${this._renderDivorce()}
|
||||
</p>
|
||||
`
|
||||
}
|
||||
|
||||
@@ -66,12 +81,40 @@ export class GrampsjsFamily extends GrampsjsObject {
|
||||
`
|
||||
}
|
||||
|
||||
_renderFather() {
|
||||
return html` <p>${renderPerson(this.data?.profile?.father || {})}</p> `
|
||||
}
|
||||
_renderParent(parent) {
|
||||
const profile = this.data?.profile[parent]
|
||||
const hasProfile = Object.keys(profile ?? {}).length > 0
|
||||
|
||||
_renderMother() {
|
||||
return html` <p>${renderPerson(this.data?.profile?.mother || {})}</p> `
|
||||
return html`
|
||||
<div class="parent">
|
||||
<div class="items-center">
|
||||
${renderPerson(profile || {})}
|
||||
${this.edit && hasProfile
|
||||
? html`
|
||||
<mwc-icon-button
|
||||
class="edit"
|
||||
icon="link_off"
|
||||
@click="${e => this._handleParentChanged(e, parent)}"
|
||||
></mwc-icon-button>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
${this.edit
|
||||
? html`
|
||||
<mwc-icon-button
|
||||
class="edit"
|
||||
icon="add_link"
|
||||
@click="${() => this._handleParentShare(parent)}"
|
||||
></mwc-icon-button>
|
||||
<mwc-icon-button
|
||||
class="edit"
|
||||
icon="add"
|
||||
@click="${() => this._handleAddNewParent(parent)}"
|
||||
></mwc-icon-button>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
_renderMarriage() {
|
||||
@@ -101,16 +144,41 @@ export class GrampsjsFamily extends GrampsjsObject {
|
||||
`
|
||||
}
|
||||
|
||||
_handleAddNewParent(parent) {
|
||||
this.dialogContent = html`
|
||||
<grampsjs-form-new-person
|
||||
@object:save="${e => this._handleNewParentSave(e, parent)}"
|
||||
@object:cancel="${this._handleCancelDialog}"
|
||||
.appState="${this.appState}"
|
||||
dialogTitle="${this._('Add a new person')}"
|
||||
>
|
||||
</grampsjs-form-new-person>
|
||||
`
|
||||
}
|
||||
|
||||
_handleParentShare(parent) {
|
||||
this.dialogContent = html`
|
||||
<grampsjs-form-personref
|
||||
@object:save="${e => this._handleParentChanged(e, parent)}"
|
||||
@object:cancel="${this._handleCancelDialog}"
|
||||
.appState="${this.appState}"
|
||||
dialogTitle="${this._('Select an existing person')}"
|
||||
>
|
||||
</grampsjs-form-personref>
|
||||
`
|
||||
}
|
||||
|
||||
_handleParentChanged(e, parent) {
|
||||
const handle = e.detail.data?.ref ?? ''
|
||||
const updatedFamily = {[`${parent}_handle`]: handle}
|
||||
fireEvent(this, 'edit:action', {action: 'updateProp', data: updatedFamily})
|
||||
this.dialogContent = ''
|
||||
}
|
||||
|
||||
_handleEditFamily() {
|
||||
const data = {
|
||||
father_handle: this.data.father_handle,
|
||||
mother_handle: this.data.mother_handle,
|
||||
type: this.data?.type?.string || this.data.type,
|
||||
}
|
||||
const father = this.data?.extended?.father
|
||||
const mother = this.data?.extended?.mother
|
||||
const fatherProfile = this.data?.profile?.father
|
||||
const motherProfile = this.data?.profile?.mother
|
||||
|
||||
this.dialogContent = html`
|
||||
<grampsjs-form-edit-family
|
||||
@@ -118,15 +186,25 @@ export class GrampsjsFamily extends GrampsjsObject {
|
||||
@object:cancel="${this._handleCancelDialog}"
|
||||
.appState="${this.appState}"
|
||||
.data=${data}
|
||||
.father=${father}
|
||||
.mother=${mother}
|
||||
.fatherProfile=${fatherProfile}
|
||||
.motherProfile=${motherProfile}
|
||||
>
|
||||
</grampsjs-form-edit-family>
|
||||
`
|
||||
}
|
||||
|
||||
_handleNewParentSave(e, parent) {
|
||||
const data = {
|
||||
...e.detail.data,
|
||||
parent,
|
||||
}
|
||||
fireEvent(this, 'edit:action', {
|
||||
action: 'newParent',
|
||||
data,
|
||||
})
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
this.dialogContent = ''
|
||||
}
|
||||
|
||||
_handleSaveDetails(e) {
|
||||
fireEvent(this, 'edit:action', {action: 'updateProp', data: e.detail.data})
|
||||
e.preventDefault()
|
||||
|
||||
@@ -10,69 +10,8 @@ import './GrampsjsFormSelectObjectList.js'
|
||||
import {GrampsjsObjectForm} from './GrampsjsObjectForm.js'
|
||||
|
||||
class GrampsjsFormEditFamily extends GrampsjsObjectForm {
|
||||
static get properties() {
|
||||
return {
|
||||
father: {type: Object},
|
||||
mother: {type: Object},
|
||||
fatherProfile: {type: Object},
|
||||
motherProfile: {type: Object},
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.father = {}
|
||||
this.mother = {}
|
||||
this.fatherProfile = {}
|
||||
this.motherProfile = {}
|
||||
}
|
||||
|
||||
renderForm() {
|
||||
return html`
|
||||
<h4 class="label">${this._('Father')}</h4>
|
||||
|
||||
<grampsjs-form-select-object-list
|
||||
id="father"
|
||||
objectType="person"
|
||||
label="${this._('Select a person as the father')}"
|
||||
.appState="${this.appState}"
|
||||
.objectsInitial="${this.data.father_handle
|
||||
? [
|
||||
{
|
||||
object_type: 'person',
|
||||
object: {
|
||||
...this.father,
|
||||
profile: this.fatherProfile,
|
||||
},
|
||||
handle: this.data.father_handle,
|
||||
},
|
||||
]
|
||||
: []}"
|
||||
class="edit"
|
||||
></grampsjs-form-select-object-list>
|
||||
|
||||
<h4 class="label">${this._('Mother')}</h4>
|
||||
|
||||
<grampsjs-form-select-object-list
|
||||
id="mother"
|
||||
objectType="person"
|
||||
label="${this._('Select a person as the mother')}"
|
||||
.appState="${this.appState}"
|
||||
.objectsInitial="${this.data.mother_handle
|
||||
? [
|
||||
{
|
||||
object_type: 'person',
|
||||
object: {
|
||||
...this.mother,
|
||||
profile: this.motherProfile,
|
||||
},
|
||||
handle: this.data.mother_handle,
|
||||
},
|
||||
]
|
||||
: []}"
|
||||
class="edit"
|
||||
></grampsjs-form-select-object-list>
|
||||
|
||||
<grampsjs-form-select-type
|
||||
id="family-rel-type"
|
||||
heading="${this._('Relationship type:').replace(':', '')}"
|
||||
|
||||
56
src/components/GrampsjsFormNewChild.js
Normal file
56
src/components/GrampsjsFormNewChild.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import {html} from 'lit'
|
||||
import {GrampsjsNewPersonMixin} from '../mixins/GrampsjsNewPersonMixin.js'
|
||||
import {fireEvent} from '../util.js'
|
||||
import './GrampsjsFormSelectType.js'
|
||||
import {GrampsjsObjectForm} from './GrampsjsObjectForm.js'
|
||||
|
||||
export class GrampsjsFormNewChild extends GrampsjsNewPersonMixin(
|
||||
GrampsjsObjectForm
|
||||
) {
|
||||
_handleDialogSave() {
|
||||
const {frel, mrel} = this.data
|
||||
const processedData = this._processedData()
|
||||
|
||||
const data = {
|
||||
processedData,
|
||||
frel,
|
||||
mrel,
|
||||
}
|
||||
|
||||
fireEvent(this, 'object:save', {data})
|
||||
this._reset()
|
||||
}
|
||||
|
||||
renderForm() {
|
||||
return html`
|
||||
${super.renderForm()}
|
||||
|
||||
<grampsjs-form-select-type
|
||||
required
|
||||
id="child-frel"
|
||||
heading="${this._('Relationship to _Father:').replace(':', '')}"
|
||||
.appState="${this.appState}"
|
||||
?loadingTypes=${this.loadingTypes}
|
||||
typeName="child_reference_types"
|
||||
defaultValue="Birth"
|
||||
.types="${this.types}"
|
||||
.typesLocale="${this.typesLocale}"
|
||||
>
|
||||
</grampsjs-form-select-type>
|
||||
<grampsjs-form-select-type
|
||||
required
|
||||
id="child-mrel"
|
||||
heading="${this._('Relationship to _Mother:').replace(':', '')}"
|
||||
.appState="${this.appState}"
|
||||
?loadingTypes=${this.loadingTypes}
|
||||
typeName="child_reference_types"
|
||||
defaultValue="Birth"
|
||||
.types="${this.types}"
|
||||
.typesLocale="${this.typesLocale}"
|
||||
>
|
||||
</grampsjs-form-select-type>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('grampsjs-form-new-child', GrampsjsFormNewChild)
|
||||
21
src/components/GrampsjsFormNewPerson.js
Normal file
21
src/components/GrampsjsFormNewPerson.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import {GrampsjsNewPersonMixin} from '../mixins/GrampsjsNewPersonMixin.js'
|
||||
import {fireEvent} from '../util.js'
|
||||
import './GrampsjsFormSelectType.js'
|
||||
import {GrampsjsObjectForm} from './GrampsjsObjectForm.js'
|
||||
|
||||
export class GrampsjsFormNewPerson extends GrampsjsNewPersonMixin(
|
||||
GrampsjsObjectForm
|
||||
) {
|
||||
_handleDialogSave() {
|
||||
const processedData = this._processedData()
|
||||
|
||||
const data = {
|
||||
processedData,
|
||||
}
|
||||
|
||||
fireEvent(this, 'object:save', {data})
|
||||
this._reset()
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('grampsjs-form-new-person', GrampsjsFormNewPerson)
|
||||
25
src/components/GrampsjsFormPersonRef.js
Normal file
25
src/components/GrampsjsFormPersonRef.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Form for adding a new person reference
|
||||
*/
|
||||
|
||||
import {html} from 'lit'
|
||||
import './GrampsjsFormSelectObjectList.js'
|
||||
import {GrampsjsObjectForm} from './GrampsjsObjectForm.js'
|
||||
|
||||
class GrampsjsFormPersonRef extends GrampsjsObjectForm {
|
||||
renderForm() {
|
||||
return html`
|
||||
<grampsjs-form-select-object-list
|
||||
fixedMenuPosition
|
||||
style="min-height: 300px;"
|
||||
objectType="person"
|
||||
.appState="${this.appState}"
|
||||
id="person-select"
|
||||
label="${this._('Select')}"
|
||||
class="edit"
|
||||
></grampsjs-form-select-object-list>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('grampsjs-form-personref', GrampsjsFormPersonRef)
|
||||
@@ -20,6 +20,7 @@ import {GrampsjsAppStateMixin} from '../mixins/GrampsjsAppStateMixin.js'
|
||||
|
||||
// labels for button
|
||||
const btnLabel = {
|
||||
person: 'Select an existing person',
|
||||
place: 'Select an existing place',
|
||||
source: 'Select an existing source',
|
||||
media: 'Select an existing media object',
|
||||
|
||||
@@ -165,11 +165,11 @@ export const GrampsjsNewPersonMixin = superClass =>
|
||||
const handleDeath = makeHandle()
|
||||
const birthString = this.translateTypeName(false, 'event_types', 'Birth')
|
||||
const deathString = this.translateTypeName(false, 'event_types', 'Death')
|
||||
const {birth, death, ...person} = this.data
|
||||
const {birth, death, frel, mrel, ...person} = this.data
|
||||
const hasBirth = birth.place || (birth?.date && !dateIsEmpty(birth.date))
|
||||
const hasDeath = death.place || (death?.date && !dateIsEmpty(death.date))
|
||||
if (!hasBirth && !hasDeath) {
|
||||
return [person]
|
||||
return [{...person, handle: handlePerson}]
|
||||
}
|
||||
if (!hasDeath) {
|
||||
return [
|
||||
|
||||
@@ -82,6 +82,7 @@ export const grampsStrings = [
|
||||
'about',
|
||||
'About',
|
||||
'Above the name',
|
||||
'Add a new person',
|
||||
'Add a new event',
|
||||
'Add a new media object',
|
||||
'Add an existing person as a child of the family',
|
||||
@@ -525,6 +526,7 @@ export const grampsStrings = [
|
||||
'Select a file',
|
||||
'Select a person as the father',
|
||||
'Select a person as the mother',
|
||||
'Select an existing person',
|
||||
'Select an existing media object',
|
||||
'Select an existing note',
|
||||
'Select an existing place',
|
||||
|
||||
@@ -214,6 +214,7 @@ export const objectIcon = {
|
||||
}
|
||||
|
||||
export const objectTypeToEndpoint = {
|
||||
object: 'objects',
|
||||
person: 'people',
|
||||
family: 'families',
|
||||
event: 'events',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
/* eslint-disable class-methods-use-this */
|
||||
import {html, css} from 'lit'
|
||||
import {css, html} from 'lit'
|
||||
|
||||
import '@material/mwc-fab'
|
||||
import '@material/mwc-icon'
|
||||
@@ -304,6 +304,33 @@ export class GrampsjsViewObject extends GrampsjsView {
|
||||
)
|
||||
}
|
||||
})
|
||||
} else if (e.detail.action === 'newParent') {
|
||||
const {processedData, parent} = e.detail.data
|
||||
const {handle} = processedData.filter(obj => obj._class === 'Person')[0]
|
||||
this._postObject(processedData, 'object').then(data => {
|
||||
if ('data' in data) {
|
||||
const updatedFamily = {[`${parent}_handle`]: handle}
|
||||
this.updateProp(this._data, this._className, updatedFamily)
|
||||
}
|
||||
})
|
||||
} else if (e.detail.action === 'newChild') {
|
||||
const {processedData, frel, mrel} = e.detail.data
|
||||
const {handle} = processedData.filter(obj => obj._class === 'Person')[0]
|
||||
this._postObject(processedData, 'object').then(data => {
|
||||
if ('data' in data) {
|
||||
const childRefData = {
|
||||
ref: handle,
|
||||
frel,
|
||||
mrel,
|
||||
}
|
||||
this.addObject(
|
||||
childRefData,
|
||||
this._data,
|
||||
this._className,
|
||||
'child_ref_list'
|
||||
)
|
||||
}
|
||||
})
|
||||
} else if (e.detail.action === 'newEvent') {
|
||||
const {role, ...eventData} = e.detail.data
|
||||
this._postObject(eventData, 'event').then(data => {
|
||||
|
||||
Reference in New Issue
Block a user