feat: visor da peça com zoom real, ficha NOBRADE e filtros agrupados pela norma

- painel à esquerda (folha no celular) com barra ← mural | filtros, palco com
  roda, pinça, duplo clique, arrastar e modo só a imagem (F)
- ficha arquivística: código, nível, arranjo clicável, data da norma com selo
  de atribuída, produtor ISAAR, suporte, original, reprodução e citação
- filtros em Arranjo, Data, Pontos de acesso e Suporte e uso; autor pela
  autoridade, espécie da 1.5 e condição de reprodução; link pelo código
- datas: ano implausível vira ilegível, atribuição pelo miolo p10–p90 e
  histograma só com datas de até 30 anos de amplitude
This commit is contained in:
2026-09-30 22:30:13 +02:00
parent 23b56e8c87
commit 5c84619e5d
5 changed files with 668 additions and 311 deletions
+29 -2
View File
@@ -8,15 +8,28 @@ Campos novos em meta (curtos: o mapa inteiro desce para o navegador):
ref código de referência (1.1) dt data na forma da NOBRADE (1.3)
ano ano inicial, para o histograma si índice em `series` do mapa (nível 3)
sup espécie e suporte (1.5) rep categoria de reprodução (4.2)
ai índice em `autoridades` (2.1, forma autorizada ISAAR(CPF))
dq 1 quando a data foi atribuída pelo arquivista (proc. 1.3.3.2)
No topo do mapa: `series`, `autoridades`, `instituicoes` (community → nome
autorizado) e `colecao` (código e título do nível 1).
"""
import json
from .config import RAIZ, SAIDA
from .config import COLECAO_TITULO, INSTITUICOES, RAIZ, SAIDA, codigo
MAPA = RAIZ / 'web' / 'atlas' / 'atlas-map.json'
def ano(p: dict):
"""O ano que posiciona a peça no histograma — só quando a data é precisa o
bastante (até 30 anos). "[18--]" ou "[1880-1930?]" ficam na ficha, fora do filtro."""
i, f = p.get('inicio'), p.get('fim')
if i and f and f - i <= 30:
return i
return None
def main():
series, dossies = {}, {}
for linha in (SAIDA / 'unidades.jsonl').open(encoding='utf-8'):
@@ -30,6 +43,11 @@ def main():
titulos = sorted(set(series.values()), key=str.casefold)
idx = {t: i for i, t in enumerate(titulos)}
d['series'] = titulos
formas = sorted({p['forma'] for u in dossies.values() for p in u['2.1'] if p.get('id')}, key=str.casefold)
ai = {f: i for i, f in enumerate(formas)}
d['autoridades'] = formas
d['instituicoes'] = {k: v[1] for k, v in INSTITUICOES.items()}
d['colecao'] = {'codigo': codigo('BF'), 'titulo': COLECAO_TITULO}
feitos = 0
for h, e in d['map'].items():
u = dossies.get(h)
@@ -39,9 +57,18 @@ def main():
dim = u['1.5']
sup = dim['especie'] + (f" {dim['cor']}" if dim.get('cor') else '') + (f", {dim['suporte']}" if dim.get('suporte') else '')
e['meta'].update({
'ref': u['1.1'], 'dt': p.get('forma'), 'ano': p.get('inicio') or p.get('fim'),
'ref': u['1.1'], 'dt': p.get('forma'), 'ano': ano(p),
'si': idx[series[u['pai']]], 'sup': sup, 'rep': u['4.2']['categoria'],
})
aut = next((p['forma'] for p in u['2.1'] if p.get('id')), None)
if e['meta'].get('ano') is None:
e['meta'].pop('ano', None)
e['meta'].pop('ai', None)
e['meta'].pop('dq', None)
if aut:
e['meta']['ai'] = ai[aut]
if (p.get('notas') or [''])[0].startswith('data atribuída pelo arquivista'):
e['meta']['dq'] = 1
feitos += 1
MAPA.write_text(json.dumps(d, ensure_ascii=False, separators=(',', ':')), encoding='utf-8')
print(f'{feitos} de {len(d["map"])} peças com descrição NOBRADE; {len(titulos)} séries')