348 lines
9.1 KiB
JavaScript

import { visMessages } from './i18n'
import { TinyEmitter } from "tiny-emitter";
/**
* Vis-network initial data/configuration script
* Notes:
* Use window.network and window.options to avoid conflict between vue and vis
* cfr. https://github.com/almende/vis/issues/2524#issuecomment-307108271
*/
console.log('@@@ init eventHub App @@@')
window.eventHub = new TinyEmitter()
window.network = {}
window.options = {
locale: 'fr',
locales: visMessages,
/*
configure: {
enabled: true,
filter: 'nodes,edges',
//container: undefined,
showButton: true
},
*/
physics: {
enabled: true,
barnesHut: {
theta: 0.5,
gravitationalConstant: -2000,
centralGravity: 0.08, //// 0.3
springLength: 220, //// 95
springConstant: 0.04,
damping: 0.09,
avoidOverlap: 0
},
forceAtlas2Based: {
theta: 0.5,
gravitationalConstant: -50,
centralGravity: 0.01,
springConstant: 0.08,
springLength: 100,
damping: 0.4,
avoidOverlap: 0
},
repulsion: {
centralGravity: 0.2,
springLength: 200,
springConstant: 0.05,
nodeDistance: 100,
damping: 0.09
},
hierarchicalRepulsion: {
centralGravity: 0.0,
springLength: 100,
springConstant: 0.01,
nodeDistance: 120,
damping: 0.09,
avoidOverlap: 0
},
maxVelocity: 50,
minVelocity: 0.1,
solver: 'barnesHut',
stabilization: {
enabled: true,
iterations: 1000,
updateInterval: 100,
onlyDynamicEdges: false,
fit: true
},
timestep: 0.5,
adaptiveTimestep: true,
wind: { x: 0, y: 0 }
},
interaction: {
hover: true,
keyboard: {
enabled: true,
speed: {x: 3, y: 3, zoom: 0.02},
bindToWindow: false
},
multiselect: true,
navigationButtons: false
},
manipulation: {
enabled: true,
initiallyActive: true,
addNode: function(nodeData, callback) {
console.log('addNode', nodeData)
//callback(nodeData) disabled
},
editNode: function(nodeData, callback) {
console.log('editNode', nodeData)
//callback(nodeData) disabled
},
deleteNode: function(nodeData, callback) {
console.log('deleteNode', nodeData)
//callback(nodeData) disabled
},
addEdge: function(edgeData, callback) {
if (
splitId(edgeData.from,'type') === 'person'
&& splitId(edgeData.to,'type') === 'person'
) {
console.log('addEdge', edgeData)
eventHub.emit('add-relationship-modal', edgeData)
callback(edgeData)
}
},
editEdge: function(edgeData, callback) {
if (
splitId(edgeData.from,'type') === 'person'
&& splitId(edgeData.to,'type') === 'person'
) {
console.log('editEdge', edgeData)
eventHub.emit('edit-relationship-modal', edgeData)
callback(edgeData)
}
},
deleteEdge: function(edgeData, callback) {
console.log('deleteEdge', edgeData) // array with edges id
eventHub.emit('delete-relationship-modal', edgeData)
callback(edgeData)
},
controlNodeStyle: {
/*
shape:'dot',
size: 6,
color: {
background: '#ff0000',
border: '#3c3c3c',
highlight: {
background: '#07f968',
border: '#3c3c3c'
}
},
borderWidth: 2,
borderWidthSelected: 2
*/
}
},
nodes: {
borderWidth: 1,
borderWidthSelected: 3,
font: {
multi: 'md'
}
},
edges: {
font: {
color: '#b0b0b0',
size: 9,
face: 'arial',
background: 'none',
strokeWidth: 2, // px
strokeColor: '#ffffff',
align: 'middle',
multi: false,
vadjust: 0,
},
scaling:{
label: true,
},
smooth: true,
},
groups: {
person: {
shape: 'box',
shapeProperties: {
borderDashes: false,
borderRadius: 3,
},
color: {
border: '#b0b0b0',
background: 'rgb(193,229,222)',
highlight: {
border: '#89c9a9',
background: 'rgb(156,213,203)'
},
hover: {
border: '#89c9a9',
background: 'rgb(156,213,203)'
}
},
opacity: 0.85,
shadow:{
enabled: true,
color: 'rgba(0,0,0,0.5)',
size:10,
x:5,
y:5
},
},
household: {
color: 'pink'
},
accompanying_period: {
color: 'orange',
},
}
}
/**
* Adapt entity to graph (id, label)
* rename id in _id and add properties needed by vis
* @param entity
* @param options
* @returns entity
*/
const adapt2vis = (entity, options = {}) => {
entity.group = entity.type
switch (entity.type) {
case 'person':
entity._id = entity.id
entity.label = `*${entity.text}*\n_${getGender(entity.gender)} - ${getAge(entity.birthdate)}_`
if (options.folded) {
entity.title = visMessages.fr.visgraph.click_to_expand
entity._label = entity.label // keep label
entity.label = null
}
entity.id = `person_${entity.id}`
break
case 'household':
entity._id = entity.id
entity.label = `${visMessages.fr.visgraph.Household}${entity.id}`
entity.id = `household_${entity.id}`
break
case 'accompanying_period':
entity._id = entity.id
entity.label = `${visMessages.fr.visgraph.Course}${entity.id}`
entity.id = `accompanying_period_${entity.id}`
break
case 'relationship':
entity._id = entity.id
entity.id = `relationship_${entity.id}`
break
default:
throw 'entity undefined'
}
return entity
}
/**
* @param gender
* @returns {string}
*/
const getGender = (gender) => {
switch (gender) {
case 'both':
return visMessages.fr.visgraph.both
case 'woman':
return visMessages.fr.visgraph.woman
case 'man':
return visMessages.fr.visgraph.man
default:
throw 'gender undefined'
}
}
/**
* TODO Repeat getAge() in PersonRenderBox.vue
* @param birthdate
* @returns {string|null}
*/
const getAge = (birthdate) => {
if (null === birthdate) {
return null
}
const birthday = new Date(birthdate.datetime)
const now = new Date()
return (now.getFullYear() - birthday.getFullYear()) + ' '+ visMessages.fr.visgraph.years
}
/**
* Return member position in household
* @param member
* @returns string
*/
const getHouseholdLabel = (member) => {
let position = member.position.label.fr
let holder = member.holder ? ` (${visMessages.fr.visgraph.Holder})` : ''
return position + holder
}
/**
* Return edge width for member (depends of position in household)
* @param member
* @returns integer (width)
*/
const getHouseholdWidth = (member) => {
if (member.holder) {
return 5
}
if (member.shareHousehold) {
return 2
}
return 1
}
/**
* Return label edge
* @param relationship
* @param reverse
* @returns string
*/
const getRelationshipLabel = (relationship, reverse) => {
return (!reverse) ? relationship.relation.title.fr : relationship.relation.reverseTitle.fr
}
/**
* Return title edge
* @param relationship
* @returns string
*/
const getRelationshipTitle = (relationship) => {
return relationship.relation.title.fr + ': '
+ relationship.fromPerson.text + '\n'
+ relationship.relation.reverseTitle.fr + ': '
+ relationship.toPerson.text
}
/**
* Split string id and return type|id substring
* @param id
* @param position
* @returns string
*/
const splitId = (id, position) => {
switch (position) {
case 'type':
return /(.+)_/.exec(id)[1] // return 'accompanying_period'
case 'id':
return id.split("_").pop() // return '124'
default:
throw 'position undefined'
}
}
export {
adapt2vis,
getHouseholdLabel,
getHouseholdWidth,
getRelationshipLabel,
getRelationshipTitle,
splitId
}