NAVWEB and WEBCAL: some minor corrections (#980)

* NAVWEB: set unused media to False by default

Fixes #11496

* Navweb: Center correctly the map in the web page

* Webcal: Dropmenu doesn't work if only one year.

* Navweb: Add notes to updates and delete empty rows

* Navweb: some code cleanup.

* Navweb: remove unused variable

* Narweb: references enhancement on place pages.

* Navweb: convert the years in gregorian cal.

* Narweb: remove unused argument

* Narweb: really solves the pyICU problem

* WEBCAL: missing death symbol
This commit is contained in:
Serge Noiraud 2020-01-17 11:46:40 +01:00 committed by GitHub
parent a2ae7b93fc
commit 763f2738dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 233 additions and 42 deletions

View File

@ -31,7 +31,7 @@ body#FamilyMap {
margin-left: 10px; margin-left: 10px;
margin-right: 10px; margin-right: 10px;
border: solid 4px #000; border: solid 4px #000;
margin: 0px auto; margin: 20px auto;
width: 800px; width: 800px;
height: 400px; height: 400px;
max-width: 90%; max-width: 90%;

View File

@ -2984,7 +2984,7 @@ class BasePage: # pylint: disable=C1001
gid = self.report.obj_dict[bkref_class][bkref_handle][2] gid = self.report.obj_dict[bkref_class][bkref_handle][2]
if role != "": if role != "":
if self.reference_sort: if self.reference_sort:
role = "" role = self.birth_death_dates(gid)
elif role[1:2] == ':': elif role[1:2] == ':':
# cal is the original calendar # cal is the original calendar
cal, role = role.split(':') cal, role = role.split(':')
@ -3012,7 +3012,10 @@ class BasePage: # pylint: disable=C1001
# reset the date to the original calendar # reset the date to the original calendar
cdate = date.to_calendar(Date.calendar_names[int(cal)]) cdate = date.to_calendar(Date.calendar_names[int(cal)])
ldate = self.rlocale.get_date(cdate) ldate = self.rlocale.get_date(cdate)
role = " (%s) " % ldate evtype = self.event_for_date(gid, cdate)
if evtype:
evtype = " " + evtype
role = " (%s) " % (ldate + evtype)
else: else:
role = " (%s) " % self._(role) role = " (%s) " % self._(role)
ordered += list_html ordered += list_html
@ -3031,6 +3034,45 @@ class BasePage: # pylint: disable=C1001
list_html += Html("a", href=url) + name + role + gid_html list_html += Html("a", href=url) + name + role + gid_html
return ordered return ordered
def event_for_date(self, gid, date):
"""
return the event type
"""
pers = self.r_db.get_person_from_gramps_id(gid)
if pers:
evt_ref_list = pers.get_event_ref_list()
if evt_ref_list:
for evt_ref in evt_ref_list:
evt = self.r_db.get_event_from_handle(evt_ref.ref)
if evt:
evdate = evt.get_date_object()
# convert date to gregorian
_date = str(evdate.to_calendar("gregorian"))
if _date == str(date):
return self._(str(evt.get_type()))
return ""
def birth_death_dates(self, gid):
"""
return the birth and death date for the person
"""
pers = self.r_db.get_person_from_gramps_id(gid)
if pers:
birth = death = ""
evt_birth = get_birth_or_fallback(self.r_db, pers)
if evt_birth:
birthd = evt_birth.get_date_object()
# convert date to gregorian to avoid strange years
birth = str(birthd.to_calendar("gregorian").get_year())
evt_death = get_death_or_fallback(self.r_db, pers)
if evt_death:
deathd = evt_death.get_date_object()
# convert date to gregorian to avoid strange years
death = str(deathd.to_calendar("gregorian").get_year())
return "(%s-%s)" % (birth, death)
else:
return ""
def display_bkref_list(self, obj_class, obj_handle): def display_bkref_list(self, obj_class, obj_handle):
""" """
Display a reference list for an object class Display a reference list for an object class

View File

@ -31,6 +31,7 @@ from unicodedata import normalize
from collections import defaultdict from collections import defaultdict
from hashlib import md5 from hashlib import md5
import re import re
import locale # Used only with pyICU
import logging import logging
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
@ -439,7 +440,10 @@ def sort_places(dbase, handle_list, rlocale=glocale):
for name in temp_list: for name in temp_list:
if isinstance(name, bytes): if isinstance(name, bytes):
name = name.decode('utf-8') name = name.decode('utf-8')
sorted_lists.append((name, pname_sub[name][0])) slist = sorted(((sortnames[x], x) for x in pname_sub[name]),
key=lambda x: rlocale.sort_key(x[0]))
for entry in slist:
sorted_lists.append(entry)
return sorted_lists return sorted_lists
@ -622,10 +626,29 @@ def first_letter(string, rlocale=glocale):
# no special case # no special case
return norm_unicode[0].upper() return norm_unicode[0].upper()
def primary_difference(prev_key, new_key, rlocale=glocale):
try:
import PyICU # pylint : disable=wrong-import-position
PRIM_COLL = PyICU.Collator.createInstance(PyICU.Locale(COLLATE_LANG))
PRIM_COLL.setStrength(PRIM_COLL.PRIMARY)
def primary_difference(prev_key, new_key, rlocale=glocale):
""" """
The PyICU collation doesn't work if you want to sort in another language Try to use the PyICU collation.
So we use this method to do the work correctly. If we generate a report for another language, make sure we use the good
collation sequence
"""
collation = PRIM_COLL
if rlocale.lang != locale.getlocale(locale.LC_COLLATE)[0]:
encoding = rlocale.encoding if rlocale.encoding else "UTF-8"
collate_lang = PyICU.Locale(rlocale.collation+"."+encoding)
collation = PyICU.Collator.createInstance(collate_lang)
return collation.compare(prev_key, new_key) != 0
except:
def primary_difference(prev_key, new_key, rlocale=glocale):
"""
The PyICU collation is not available.
Returns true if there is a primary difference between the two parameters Returns true if there is a primary difference between the two parameters
See http://www.gramps-project.org/bugs/view.php?id=2933#c9317 if See http://www.gramps-project.org/bugs/view.php?id=2933#c9317 if

View File

@ -1948,7 +1948,7 @@ class NavWebOptions(MenuReportOptions):
self.__gallery_changed) self.__gallery_changed)
self.__unused = BooleanOption( self.__unused = BooleanOption(
_("Include unused images and media objects"), True) _("Include unused images and media objects"), False)
self.__unused.set_help(_('Whether to include unused or unreferenced' self.__unused.set_help(_('Whether to include unused or unreferenced'
' media objects')) ' media objects'))
addopt("unused", self.__unused) addopt("unused", self.__unused)

View File

@ -45,9 +45,9 @@ from gramps.plugins.lib.libhtml import Html
#------------------------------------------------ #------------------------------------------------
from gramps.plugins.webreport.basepage import BasePage from gramps.plugins.webreport.basepage import BasePage
from gramps.gen.display.place import displayer as _pd from gramps.gen.display.place import displayer as _pd
from gramps.plugins.webreport.common import (FULLCLEAR, _EVENTMAP) from gramps.plugins.webreport.common import (FULLCLEAR, _EVENTMAP, html_escape)
from gramps.gen.lib import (Person, Family, Event, Place, Source, Repository, from gramps.gen.lib import (Person, Family, Event, Place, Source, Repository,
Media) Media, Note, Citation)
from gramps.gen.lib.date import Date from gramps.gen.lib.date import Date
_ = glocale.translation.sgettext _ = glocale.translation.sgettext
@ -66,6 +66,12 @@ class UpdatesPage(BasePage):
""" """
BasePage.__init__(self, report, title) BasePage.__init__(self, report, title)
ldatec = 0 ldatec = 0
self.inc_repository = self.report.options['inc_repository']
self.inc_families = self.report.options['inc_families']
self.inc_events = self.report.options['inc_events']
self.inc_places = self.report.options['inc_places']
self.inc_sources = self.report.options['inc_sources']
self.inc_gallery = False
output_file, sio = self.report.create_file("updates") output_file, sio = self.report.create_file("updates")
result = self.write_header(self._('New and updated objects')) result = self.write_header(self._('New and updated objects'))
@ -93,35 +99,35 @@ class UpdatesPage(BasePage):
if people is not None: if people is not None:
section += people section += people
if self.report.options['inc_families']: if self.inc_families:
header = self._("Families") header = self._("Families")
section += Html("h4", header) section += Html("h4", header)
families = self.list_people_changed(Family) families = self.list_people_changed(Family)
if families is not None: if families is not None:
section += families section += families
if self.report.options['inc_events']: if self.inc_events:
header = self._("Events") header = self._("Events")
section += Html("h4", header) section += Html("h4", header)
events = self.list_people_changed(Event) events = self.list_people_changed(Event)
if events is not None: if events is not None:
section += events section += events
if self.report.options['inc_places']: if self.inc_places:
header = self._("Places") header = self._("Places")
section += Html("h4", header) section += Html("h4", header)
places = self.list_people_changed(Place) places = self.list_people_changed(Place)
if places is not None: if places is not None:
section += places section += places
if self.report.options['inc_sources']: if self.inc_sources:
header = self._("Sources") header = self._("Sources")
section += Html("h4", header) section += Html("h4", header)
sources = self.list_people_changed(Source) sources = self.list_people_changed(Source)
if sources is not None: if sources is not None:
section += sources section += sources
if self.report.options['inc_repository']: if self.inc_repository:
header = self._("Repositories") header = self._("Repositories")
section += Html("h4", header) section += Html("h4", header)
repos = self.list_people_changed(Repository) repos = self.list_people_changed(Repository)
@ -130,12 +136,19 @@ class UpdatesPage(BasePage):
if (self.report.options['gallery'] and not if (self.report.options['gallery'] and not
self.report.options['create_thumbs_only']): self.report.options['create_thumbs_only']):
self.inc_gallery = True
header = self._("Media") header = self._("Media")
section += Html("h4", header) section += Html("h4", header)
media = self.list_people_changed(Media) media = self.list_people_changed(Media)
if media is not None: if media is not None:
section += media section += media
header = self._("Notes")
section += Html("h4", header)
events = self.list_notes()
if events is not None:
section += events
# create clear line for proper styling # create clear line for proper styling
# create footer section # create footer section
footer = self.write_footer(ldatec) footer = self.write_footer(ldatec)
@ -145,6 +158,122 @@ class UpdatesPage(BasePage):
# and close the file # and close the file
self.xhtml_writer(homepage, output_file, sio, ldatec) self.xhtml_writer(homepage, output_file, sio, ldatec)
def list_notes(self):
"""
List all notes with last change date
"""
nb_items = 0
section = ""
def sort_on_change(handle):
""" sort records based on the last change time """
fct = self.report.database.get_note_from_handle
obj = fct(handle)
timestamp = obj.get_change_time()
return timestamp
note_list = self.report.database.get_note_handles()
obj_list = sorted(note_list, key=sort_on_change, reverse=True)
with Html("table", class_="list", id="list") as section:
for handle in obj_list:
show = False
date = obj = None
obj = self.report.database.get_note_from_handle(handle)
if obj:
text = html_escape(obj.get()[:50])
timestamp = obj.get_change_time()
if timestamp - self.maxdays > 0:
handle_list = set(
self.report.database.find_backlink_handles(
handle,
include_classes=['Person', 'Family', 'Event',
'Place', 'Media', 'Source',
'Citation', 'Repository',
]))
tims = localtime(timestamp)
odat = Date(tims.tm_year, tims.tm_mon, tims.tm_mday)
date = self.rlocale.date_displayer.display(odat)
date += strftime(' %X', tims)
if handle_list:
srbd = self.report.database
srbkref = self.report.bkref_dict
for obj_t, r_handle in handle_list:
if obj_t == 'Person':
if r_handle in srbkref[Person]:
name = self.new_person_link(r_handle)
show = True
elif obj_t == 'Family':
if r_handle in srbkref[Family]:
fam = srbd.get_family_from_handle(
r_handle)
fam = self._("Family")
name = self.family_link(r_handle, fam)
if self.inc_families:
show = True
elif obj_t == 'Place':
if r_handle in srbkref[Place]:
plc = srbd.get_place_from_handle(
r_handle)
plcn = _pd.display(self.report.database,
plc)
name = self.place_link(r_handle, plcn)
if self.inc_places:
show = True
elif obj_t == 'Event':
if r_handle in srbkref[Event]:
evt = srbd.get_event_from_handle(
r_handle)
evtn = self._(evt.get_type().xml_str())
name = self.event_link(r_handle, evtn)
if self.inc_events:
show = True
elif obj_t == 'Media':
if r_handle in srbkref[Media]:
media = srbd.get_media_from_handle(
r_handle)
evtn = media.get_description()
name = self.media_link(r_handle, evtn,
evtn,
usedescr=False)
if self.inc_gallery:
show = True
elif obj_t == 'Citation':
if r_handle in srbkref[Citation]:
cit = srbd.get_event_from_handle(
r_handle)
citsrc = cit.source_handle
evtn = self._("Citation")
name = self.source_link(citsrc, evtn)
if self.inc_sources:
show = True
elif obj_t == 'Source':
if r_handle in srbkref[Source]:
src = srbd.get_source_from_handle(
r_handle)
evtn = src.get_title()
name = self.source_link(r_handle, evtn)
if self.inc_sources:
show = True
elif obj_t == 'Repository':
if r_handle in srbkref[Repository]:
rep = srbd.get_repository_from_handle(
r_handle)
evtn = rep.get_name()
name = self.repository_link(r_handle,
evtn)
if self.inc_repository:
show = True
if show:
row = Html("tr")
section += row
row += Html("td", date, class_="date")
row += Html("td", text)
row += Html("td", name)
nb_items += 1
if nb_items > self.nbr:
break
return section
def list_people_changed(self, object_type): def list_people_changed(self, object_type):
""" """
List all records with last change date List all records with last change date
@ -180,8 +309,6 @@ class UpdatesPage(BasePage):
key=sort_on_change, reverse=True) key=sort_on_change, reverse=True)
with Html("table", class_="list", id="list") as section: with Html("table", class_="list", id="list") as section:
for handle in obj_list: for handle in obj_list:
row = Html("tr")
section += row
date = obj = None date = obj = None
name = "" name = ""
obj = fct(handle) obj = fct(handle)
@ -236,6 +363,8 @@ class UpdatesPage(BasePage):
odat = Date(tims.tm_year, tims.tm_mon, tims.tm_mday) odat = Date(tims.tm_year, tims.tm_mon, tims.tm_mday)
date = self.rlocale.date_displayer.display(odat) date = self.rlocale.date_displayer.display(odat)
date += strftime(' %X', tims) date += strftime(' %X', tims)
row = Html("tr")
section += row
row += Html("td", date, class_="date") row += Html("td", date, class_="date")
row += Html("td", name) row += Html("td", name)
return section return section

View File

@ -63,6 +63,7 @@ from gramps.gen.plug.menu import (BooleanOption, NumberOption, StringOption,
from gramps.gen.utils.config import get_researcher from gramps.gen.utils.config import get_researcher
from gramps.gen.utils.alive import probably_alive from gramps.gen.utils.alive import probably_alive
from gramps.gen.utils.db import get_death_or_fallback from gramps.gen.utils.db import get_death_or_fallback
from gramps.gen.utils.symbols import Symbols
from gramps.gen.datehandler import displayer as _dd from gramps.gen.datehandler import displayer as _dd
from gramps.gen.display.name import displayer as _nd from gramps.gen.display.name import displayer as _nd
@ -464,19 +465,13 @@ class WebCalReport(Report):
"if (x.className === \"nav\") { x.className += \"" "if (x.className === \"nav\") { x.className += \""
" responsive\"; } else { x.className = \"nav\"; }" " responsive\"; } else { x.className = \"nav\"; }"
" }</script>") " }</script>")
if self.multiyear:
head += menuscript head += menuscript
# begin header section # begin header section
if self.multiyear:
headerdiv = Html("div", id='header') + ( headerdiv = Html("div", id='header') + (
Html("<a href=\"javascript:void(0);\" class=\"navIcon\"" Html("<button href=\"javascript:void(0);\" class=\"navIcon\""
" onclick=\"navFunction()\">&#8801;</a>")) + ( " onclick=\"navFunction()\">&#8801;</button>")) + (
Html("h1", html_escape(title), Html("h1", self.title_text,
id="SiteTitle", inline=True))
else:
headerdiv = Html("div", id='header') + (
Html("h1", html_escape(title),
id="SiteTitle", inline=True)) id="SiteTitle", inline=True))
body += headerdiv body += headerdiv
@ -2168,12 +2163,14 @@ def get_day_list(event_date, holiday_list, bday_anniv_list, rlocale=glocale):
#age_str.format(precision=1, as_age=False, dlocale=rlocale) #age_str.format(precision=1, as_age=False, dlocale=rlocale)
age_str = age_str.format(precision=1, as_age=False, dlocale=rlocale) age_str = age_str.format(precision=1, as_age=False, dlocale=rlocale)
symbols = Symbols()
death_idx = symbols.DEATH_SYMBOL_SHADOWED_LATIN_CROSS
death_symbol = symbols.get_death_symbol_for_char(death_idx)
# a birthday # a birthday
if event == 'Birthday': if event == 'Birthday':
if age_at_death is not None: if age_at_death is not None:
death_symbol = "&#10014;" # latin cross for html code
trans_date = trans_text("Died %(death_date)s.") trans_date = trans_text("Died %(death_date)s.")
translated_date = rlocale.get_date(dead_event_date) translated_date = rlocale.get_date(dead_event_date)
mess = trans_date % {'death_date' : translated_date} mess = trans_date % {'death_date' : translated_date}
@ -2194,7 +2191,7 @@ def get_day_list(event_date, holiday_list, bday_anniv_list, rlocale=glocale):
# a death # a death
if event == 'Death': if event == 'Death':
txt_str = (text + ', <em>' txt_str = (text + ', ' + death_symbol + ' <em>'
+ (_('%s since death') % str(age_str) if nyears + (_('%s since death') % str(age_str) if nyears
else _('death')) else _('death'))
+ '</em>') + '</em>')