def get_geom(entity: Entity) -> Union[list[dict[str, Any]], list[Any]]: if entity.class_.view == 'place' or entity.class_.name == 'artifact': return Gis.get_by_id( Link.get_linked_entity_safe(entity.id, 'P53').id) if entity.class_.name == 'object_location': return Gis.get_by_id(entity.id) return []
def get_geom(entity: Entity) -> Union[List[Dict[str, Any]], List[Any]]: if entity.class_.view == 'place' or entity.class_.name in [ 'find', 'artifact' ]: return Gis.get_by_id(Link.get_linked_entity(entity.id, 'P53').id) if entity.class_.name == 'object_location': print("here") return Gis.get_by_id(entity.id) return []
def import_data(project: 'Project', class_: str, data: list[Any]) -> None: from openatlas.models.entity import Entity from openatlas.models.gis import Gis for row in data: entity = Entity.insert( class_, row['name'], row['description'] if 'description' in row else None) Db.import_data( project.id, entity.id, current_user.id, origin_id=row['id'] if 'id' in row and row['id'] else None) # Dates dates = { 'begin_from': None, 'begin_to': None, 'begin_comment': None, 'end_from': None, 'end_to': None, 'end_comment': None } if 'begin_from' in row and row['begin_from']: dates['begin_from'] = row['begin_from'] if 'begin_to' in row and row['begin_to']: dates['begin_to'] = row['begin_to'] if 'begin_comment' in row and row['begin_comment']: dates['begin_comment'] = row['begin_comment'] if 'end_from' in row and row['end_from']: dates['end_from'] = row['end_from'] if 'end_to' in row and row['end_to']: dates['end_to'] = row['end_to'] if 'end_comment' in row and row['end_comment']: dates['end_comment'] = row['end_comment'] entity.update({'attributes': dates}) # Types if 'type_ids' in row and row['type_ids']: # pragma: no cover for type_id in str(row['type_ids']).split(): if not Import.check_type_id(type_id, class_): continue entity.link('P2', g.types[int(type_id)]) # GIS if class_ == 'place': location = Entity.insert('object_location', f"Location of {row['name']}") entity.link('P53', location) if 'easting' in row \ and is_float(row['easting']) \ and 'northing' in row \ and is_float(row['northing']): Gis.insert_import(entity=entity, location=location, project=project, easting=row['easting'], northing=row['northing'])
def get_geometry(entity: Entity) -> Dict[str, None]: if entity.cidoc_class.code != 'E53': # pragma: nocover return {'type': None, 'coordinates': None} geoms = Gis.get_by_id(entity.id) if geoms: return {key: [d[key] for d in geoms] for key in geoms[0]} return {'type': None, 'coordinates': None}
def get_csv_geometry(entity: Entity) -> dict[str, Any]: if entity.cidoc_class.code != 'E53': return {'type': None, 'coordinates': None} # pragma: no cover geoms = Gis.get_by_id(entity.id) if geoms: return {key: [geom[key] for geom in geoms] for key in geoms[0]} return {'type': None, 'coordinates': None}
def update_gis(self, gis_data: dict[str, Any], new: bool) -> None: from openatlas.models.gis import Gis if not self.location: self.location = self.get_linked_entity_safe('P53') if not new: Db.update({ 'id': self.location.id, 'name': f'Location of {str(self.name).strip()}', 'begin_from': None, 'begin_to': None, 'end_from': None, 'end_to': None, 'begin_comment': None, 'end_comment': None, 'description': None}) Gis.delete_by_entity(self.location) Gis.insert(self.location, gis_data)
def get_geometries(parser: dict[str, Any]) -> list[dict[str, Any]]: choices = [ 'gisPointAll', 'gisPointSupers', 'gisPointSubs', 'gisPointSibling', 'gisLineAll', 'gisPolygonAll'] out = [] for item in choices \ if parser['geometry'] == 'gisAll' else parser['geometry']: for geom in json.loads(Gis.get_all()[item]): out.append(geom) return out
def get_place_info_for_insert( class_view: str, origin: Optional[Entity]) -> dict[str, Any]: if class_view not in ['artifact', 'place']: return {'structure': None, 'gis_data': None, 'overlays': None} structure = get_structure(super_=origin) return { 'structure': structure, 'gis_data': Gis.get_all([origin] if origin else None, structure), 'overlays': Overlay.get_by_object(origin) if origin and origin.class_.view == 'place' else None}
def get_place_info_for_update(entity: Entity) -> dict[str, Any]: if entity.class_.view not in ['artifact', 'place']: return { 'structure': None, 'gis_data': None, 'overlays': None, 'location': None} structure = get_structure(entity) return { 'structure': structure, 'gis_data': Gis.get_all([entity], structure), 'overlays': Overlay.get_by_object(entity), 'location': entity.get_linked_entity_safe('P53', types=True)}
def index(view: str, delete_id: Optional[int] = None) -> Union[str, Response]: if delete_id: # Delete before showing index to prevent additional redirects url = delete_entity(delete_id) if url: # e.g. an error occurred and entry is shown again return redirect(url) return render_template( 'entity/index.html', class_=view, table=get_table(view), buttons=get_buttons(view), gis_data=Gis.get_all() if view == 'place' else None, title=_(view.replace('_', ' ')), crumbs=[[_('admin'), url_for('admin_index')], _('file')] if view == 'file' else [_(view).replace('_', ' ')])
def insert(class_: str, origin_id: Optional[int] = None) -> Union[str, Response]: if class_ not in g.classes or not g.classes[class_].view \ or not is_authorized(g.classes[class_].write_access): abort(403) # pragma: no cover origin = Entity.get_by_id(origin_id) if origin_id else None form = build_form(class_, origin=origin) if form.validate_on_submit(): return redirect(save(form, class_=class_, origin=origin)) if hasattr(form, 'alias'): form.alias.append_entry('') view_name = g.classes[class_].view geonames_module = False if origin: populate_insert_form(form, view_name, class_, origin) else: geonames_module = True if ReferenceSystem.get_by_name( 'GeoNames').forms else False # Archaeological sub units structure = None gis_data = None overlays = None if view_name in ['artifact', 'place']: structure = get_structure(super_=origin) gis_data = Gis.get_all([origin] if origin else None, structure) overlays = Overlay.get_by_object(origin) \ if origin and origin.class_.view == 'place' else None return render_template( 'entity/insert.html', form=form, class_=class_, origin=origin, view_name=view_name, structure=structure, gis_data=gis_data, geonames_module=geonames_module, writeable=True if os.access(app.config['UPLOAD_DIR'], os.W_OK) else False, # For files overlays=overlays, title=_(view_name), crumbs=add_crumbs(view_name, class_, origin, structure, insert_=True))
def get_geoms_by_entity(entity_id: int) -> Dict[str, Any]: geoms = Gis.get_by_id(entity_id) if len(geoms) == 1: return geoms[0] return {'type': 'GeometryCollection', 'geometries': geoms}
def update_links(entity: Entity, form: FlaskForm, action: str, origin: Optional[Entity]) -> None: if entity.class_.view in ['actor', 'event', 'place', 'artifact', 'type']: ReferenceSystem.update_links(form, entity) if entity.class_.view == 'actor': if action == 'update': entity.delete_links(['P74', 'OA8', 'OA9']) if form.residence.data: object_ = Entity.get_by_id(form.residence.data) entity.link('P74', object_.get_linked_entity_safe('P53')) if form.begins_in.data: object_ = Entity.get_by_id(form.begins_in.data) entity.link('OA8', object_.get_linked_entity_safe('P53')) if form.ends_in.data: object_ = Entity.get_by_id(form.ends_in.data) entity.link('OA9', object_.get_linked_entity_safe('P53')) if entity.class_.view == 'event': if action == 'update': entity.delete_links(['P7', 'P24', 'P25', 'P26', 'P27', 'P117']) if form.event.data: entity.link_string('P117', form.event.data) if hasattr(form, 'place') and form.place.data: entity.link( 'P7', Link.get_linked_entity_safe(int(form.place.data), 'P53')) if entity.class_.name == 'acquisition' and form.given_place.data: entity.link_string('P24', form.given_place.data) if entity.class_.name == 'move': if form.artifact.data: # Moved objects entity.link_string('P25', form.artifact.data) if form.person.data: # Moved persons entity.link_string('P25', form.person.data) if form.place_from.data: # Link place for move from linked_place = Link.get_linked_entity_safe( int(form.place_from.data), 'P53') entity.link('P27', linked_place) if form.place_to.data: # Link place for move to entity.link( 'P26', Link.get_linked_entity_safe(int(form.place_to.data), 'P53')) elif entity.class_.view in ['artifact', 'place']: location = entity.get_linked_entity_safe('P53') if action == 'update': Gis.delete_by_entity(location) location.update(form) Gis.insert(location, form) elif entity.class_.view == 'source' and not origin: if action == 'update': entity.delete_links(['P128'], inverse=True) if form.artifact.data: entity.link_string('P128', form.artifact.data, inverse=True) elif entity.class_.view == 'type': node = origin if isinstance(origin, Node) else entity root = g.nodes[node.root[-1]] if node.root else node super_id = g.nodes[node.root[0]] if node.root else node new_super_id = getattr(form, str(root.id)).data new_super = g.nodes[int(new_super_id)] if new_super_id else root if super_id != new_super.id: property_code = 'P127' if entity.class_.name == 'type' else 'P89' entity.delete_links([property_code]) entity.link(property_code, new_super)
def update(id_: int) -> Union[str, Response]: entity = Entity.get_by_id(id_, nodes=True, aliases=True) if not entity.class_.view: abort(422) # pragma: no cover elif not is_authorized(entity.class_.write_access): abort(403) # pragma: no cover elif isinstance(entity, Node): root = g.nodes[entity.root[-1]] if entity.root else None if not root and (entity.standard or entity.locked): abort(403) # pragma: no cover # Archaeological sub units geonames_module = False if entity.class_.name == 'place' and ReferenceSystem.get_by_name( 'GeoNames').forms: geonames_module = True structure = None gis_data = None overlays = None location = None if entity.class_.view in ['artifact', 'place']: structure = get_structure(entity) location = entity.get_linked_entity_safe('P53', nodes=True) gis_data = Gis.get_all([entity], structure) overlays = Overlay.get_by_object(entity) form = build_form(entity.class_.name, entity, location=location) if entity.class_.view == 'event': form.event_id.data = entity.id elif isinstance(entity, ReferenceSystem) and entity.system: form.name.render_kw['readonly'] = 'readonly' if form.validate_on_submit(): if isinstance(entity, Node): valid = True root = g.nodes[entity.root[-1]] new_super_id = getattr(form, str(root.id)).data new_super = g.nodes[int(new_super_id)] if new_super_id else None if new_super: if new_super.id == entity.id: flash(_('error node self as super'), 'error') valid = False if new_super.root and entity.id in new_super.root: flash(_('error node sub as super'), 'error') valid = False if not valid: return redirect(url_for('entity_view', id_=entity.id)) if was_modified(form, entity): # pragma: no cover del form.save flash(_('error modified'), 'error') return render_template('entity/update.html', form=form, entity=entity, structure=structure, modifier=link( logger.get_log_for_advanced_view( entity.id)['modifier'])) return redirect(save(form, entity)) populate_update_form(form, entity) return render_template('entity/update.html', form=form, entity=entity, structure=structure, gis_data=gis_data, overlays=overlays, geonames_module=geonames_module, title=entity.name, crumbs=add_crumbs(view_name=entity.class_.view, class_=entity.class_.name, origin=entity, structure=structure))
def test_api(self) -> None: pass with app.app_context(): # type: ignore with app.test_request_context(): app.preprocess_request() # type: ignore place = insert_entity('Nostromos', 'place', description='That is the Nostromos') if not place: return # pragma: no cover # Adding Dates to place place.begin_from = '2018-01-31' place.begin_to = '2018-03-01' place.begin_comment = 'Begin of the Nostromos' place.end_from = '2019-01-31' place.end_to = '2019-03-01' place.end_comment = 'Destruction of the Nostromos' location = place.get_linked_entity_safe('P53') Gis.add_example_geom(location) # Adding Type Settlement place.link('P2', Node.get_hierarchy('Place')) # Adding Alias alias = insert_entity('Cargo hauler', 'appellation') place.link('P1', alias) # Adding External Reference external_reference = insert_entity('https://openatlas.eu', 'external_reference') external_reference.link('P67', place, description='OpenAtlas Website') # Adding feature to place feature = insert_entity('Feature', 'feature', place) # Adding stratigraphic to place strati = insert_entity('Strato', 'stratigraphic_unit', feature) # Adding Administrative Unit Node unit_node = Node.get_hierarchy('Administrative unit') # Adding File to place file = insert_entity('Datei', 'file') file.link('P67', place) file.link('P2', Node.get_hierarchy('License')) # Adding Value Type value_type = Node.get_hierarchy('Dimensions') place.link('P2', Entity.get_by_id(value_type.subs[0]), '23.0') # Adding Geonames geonames = Entity.get_by_id( ReferenceSystem.get_by_name('GeoNames').id) precision_id = Node.get_hierarchy( 'External reference match').subs[0] geonames.link('P67', place, description='2761369', type_id=precision_id) # Path Tests rv = self.app.get(url_for('usage')) assert b'message' in rv.data rv = self.app.get(url_for('latest', latest=10)) assert b'Datei' in rv.data rv = self.app.get(url_for('latest', count=True, latest=1)) assert b'1' in rv.data rv = self.app.get(url_for('entity', id_=place.id)) assert b'Nostromos' in rv.data rv = self.app.get(url_for('code', code='reference')) assert b'openatlas' in rv.data rv = self.app.get( url_for('system_class', system_class='appellation')) assert b'Cargo hauler' in rv.data rv = self.app.get(url_for('class', class_code='E31')) assert b'https://openatlas.eu' in rv.data rv = self.app.get(url_for('node_entities', id_=unit_node.id)) assert b'Austria' in rv.data rv = self.app.get(url_for('node_entities_all', id_=unit_node.id)) assert b'Austria' in rv.data rv = self.app.get( url_for('query', entities=place.id, classes='E18', items='place')) assert b'Nostromos' in rv.data rv = self.app.get(url_for('content', lang='de')) assert b'intro' in rv.data rv = self.app.get(url_for('overview_count')) assert b'systemClass' in rv.data rv = self.app.get(url_for('class_mapping')) assert b'systemClass' in rv.data rv = self.app.get(url_for('node_overview')) assert b'Actor' in rv.data rv = self.app.get(url_for('type_tree')) assert b'type_tree' in rv.data # Path test with download rv = self.app.get(url_for('entity', id_=place.id, download=True)) assert b'Nostromos' in rv.data rv = self.app.get(url_for('latest', latest=1, download=True)) assert b'Datei' in rv.data rv = self.app.get(url_for('code', code='reference', download=True)) assert b'https://openatlas.eu' in rv.data rv = self.app.get( url_for('system_class', system_class='appellation', download=True)) assert b'Cargo hauler' in rv.data rv = self.app.get(url_for('class', class_code='E31', download=True)) assert b'https://openatlas.eu' in rv.data rv = self.app.get( url_for('node_entities', id_=unit_node.id, download=True)) assert b'Austria' in rv.data rv = self.app.get( url_for('node_entities_all', id_=unit_node.id, download=True)) assert b'Austria' in rv.data rv = self.app.get(url_for('query', classes='E31', download=True)) assert b'https://openatlas.eu' in rv.data rv = self.app.get(url_for('content', lang='de', download=True)) assert b'intro' in rv.data rv = self.app.get(url_for('overview_count', download=True)) assert b'systemClass' in rv.data rv = self.app.get(url_for('class_mapping', download=True)) assert b'systemClass' in rv.data rv = self.app.get(url_for('node_overview', download=True)) assert b'Actor' in rv.data # Path with export rv = self.app.get(url_for('entity', id_=place.id, export='csv')) assert b'Nostromos' in rv.data rv = self.app.get(url_for('class', class_code='E18', export='csv')) assert b'Nostromos' in rv.data rv = self.app.get( url_for('system_class', system_class='place', export='csv')) assert b'Nostromos' in rv.data rv = self.app.get(url_for('code', code='reference', export='csv')) assert b'https://openatlas.eu' in rv.data # Testing Subunit rv = self.app.get(url_for('subunit', id_=place.id)) assert b'Feature' in rv.data and b'Strato' not in rv.data rv = self.app.get(url_for('subunit', id_=place.id, download=True)) assert b'Feature' in rv.data and b'Strato' not in rv.data rv = self.app.get(url_for('subunit', id_=place.id, count=True)) assert b'1' in rv.data rv = self.app.get(url_for('subunit_hierarchy', id_=place.id)) assert b'Strato' in rv.data rv = self.app.get( url_for('subunit_hierarchy', id_=place.id, download=True)) assert b'Strato' in rv.data rv = self.app.get( url_for('subunit_hierarchy', id_=place.id, count=True)) assert b'2' in rv.data # Parameter: filter rv = self.app.get( url_for('code', code='place', limit=10, sort='desc', column='name', filter='or|name|like|Nostromos')) assert b'Nostromos' in rv.data rv = self.app.get(url_for('code', code='reference')) assert b'openatlas' in rv.data rv = self.app.get( url_for('class', class_code='E18', filter='or|name|like|Nostr')) assert b'Nostromos' in rv.data rv = self.app.get( url_for('code', code='place', filter='or|id|eq|' + str(place.id))) assert b'Nostromos' in rv.data rv = self.app.get( url_for('code', code='place', filter='or|begin_from|ge|2018-1-1')) assert b'Nostromos' in rv.data # Parameter: last rv = self.app.get(url_for('class', class_code='E18', last=place.id)) assert b'entities' in rv.data # Parameter: first rv = self.app.get( url_for('class', class_code='E18', first=place.id)) assert b'entities' in rv.data # Parameter: show rv = self.app.get(url_for('class', class_code='E31', show='types')) assert b'https://openatlas.eu' in rv.data rv = self.app.get(url_for('class', class_code='E18', show='when')) assert b'Nostromos' in rv.data rv = self.app.get(url_for('class', class_code='E31', show='none')) assert b'https://openatlas.eu' in rv.data # Parameter: count rv = self.app.get(url_for('class', class_code='E31', count=True)) assert b'2' in rv.data rv = self.app.get(url_for('code', code='place', count=True)) assert b'3' in rv.data rv = self.app.get( url_for('system_class', system_class='appellation', count=True)) assert b'1' in rv.data rv = self.app.get( url_for('query', entities=place.id, classes='E18', codes='place')) assert b'Nostromos' in rv.data rv = self.app.get( url_for('query', entities=place.id, classes='E18', codes='place', count=True)) assert b'7' in rv.data rv = self.app.get( url_for('node_entities', id_=unit_node.id, count=True)) assert b'6' in rv.data rv = self.app.get( url_for('node_entities_all', id_=unit_node.id, count=True)) assert b'8' in rv.data
def entity_view(id_: int) -> Union[str, Response]: if id_ in g.nodes: # Nodes have their own view entity = g.nodes[id_] if not entity.root: if entity.class_.name == 'administrative_unit': tab_hash = '#menu-tab-places_collapse-' elif entity.standard: tab_hash = '#menu-tab-standard_collapse-' elif entity.value_type: tab_hash = '#menu-tab-value_collapse-' else: tab_hash = '#menu-tab-custom_collapse-' return redirect(f"{url_for('node_index')}{tab_hash}{id_}") elif id_ in g.reference_systems: entity = g.reference_systems[id_] else: entity = Entity.get_by_id(id_, nodes=True, aliases=True) if not entity.class_.view: flash(_("This entity can't be viewed directly."), 'error') abort(400) event_links = None # Needed for actor overlays = None # Needed for place tabs = {'info': Tab('info')} if isinstance(entity, Node): tabs['subs'] = Tab('subs', entity=entity) tabs['entities'] = Tab('entities', entity=entity) root = g.nodes[entity.root[-1]] if entity.root else None if root and root.value_type: # pragma: no cover tabs['entities'].table.header = [ _('name'), _('value'), _('class'), _('info') ] for item in entity.get_linked_entities(['P2', 'P89'], inverse=True, nodes=True): if item.class_.name in ['location', 'reference_system']: continue # pragma: no cover if item.class_.name == 'object_location': # pragma: no cover item = item.get_linked_entity_safe('P53', inverse=True) data = [link(item)] if root and root.value_type: # pragma: no cover data.append(format_number(item.nodes[entity])) data.append(item.class_.label) data.append(item.description) tabs['entities'].table.rows.append(data) for sub_id in entity.subs: sub = g.nodes[sub_id] tabs['subs'].table.rows.append( [link(sub), sub.count, sub.description]) if not tabs['entities'].table.rows: # If no entities available get links with this type_id tabs['entities'].table.header = [_('domain'), _('range')] for row in Link.get_entities_by_node(entity): tabs['entities'].table.rows.append([ link(Entity.get_by_id(row['domain_id'])), link(Entity.get_by_id(row['range_id'])) ]) elif isinstance(entity, ReferenceSystem): for form_id, form in entity.get_forms().items(): tabs[form['name']] = Tab(form['name'], entity=entity) tabs[form['name']].table = \ Table([_('entity'), 'id', _('precision')]) for link_ in entity.get_links('P67'): name = link_.description if entity.resolver_url: name = \ f'<a href="{entity.resolver_url + name}"' \ f' target="_blank" rel="noopener noreferrer">{name}</a>' tab_name = link_.range.class_.name tabs[tab_name].table.rows.append( [link(link_.range), name, link_.type.name]) for form_id, form in entity.get_forms().items(): tabs[form['name']].buttons = [] if not tabs[form['name']].table.rows and is_authorized('manager'): tabs[form['name']].buttons = [ button( _('remove'), url_for('reference_system_remove_form', system_id=entity.id, form_id=form_id)) ] elif entity.class_.view == 'actor': for name in [ 'source', 'event', 'relation', 'member_of', 'member', 'artifact' ]: tabs[name] = Tab(name, entity=entity) event_links = entity.get_links(['P11', 'P14', 'P22', 'P23', 'P25'], True) for link_ in event_links: event = link_.domain places = event.get_linked_entities(['P7', 'P26', 'P27']) link_.object_ = None # Needed for first/last appearance for place in places: object_ = place.get_linked_entity_safe('P53', True) entity.linked_places.append(object_) link_.object_ = object_ first = link_.first if not link_.first and event.first: first = f'<span class="inactive">{event.first}</span>' last = link_.last if not link_.last and event.last: last = f'<span class="inactive">{event.last}</span>' data = [ link(event), event.class_.label, _('moved') if link_.property.code == 'P25' else link( link_.type), first, last, link_.description ] if link_.property.code == 'P25': data += [''] else: add_edit_link( data, url_for('involvement_update', id_=link_.id, origin_id=entity.id)) add_remove_link(data, link_.domain.name, link_, entity, 'event') tabs['event'].table.rows.append(data) for link_ in entity.get_links('OA7') + entity.get_links('OA7', True): type_ = '' if entity.id == link_.domain.id: related = link_.range if link_.type: type_ = link(link_.type.get_name_directed(), url_for('entity_view', id_=link_.type.id)) else: related = link_.domain if link_.type: type_ = link(link_.type.get_name_directed(True), url_for('entity_view', id_=link_.type.id)) data = [ type_, link(related), link_.first, link_.last, link_.description ] add_edit_link( data, url_for('relation_update', id_=link_.id, origin_id=entity.id)) add_remove_link(data, related.name, link_, entity, 'relation') tabs['relation'].table.rows.append(data) for link_ in entity.get_links('P107', True): data = [ link(link_.domain), link(link_.type), link_.first, link_.last, link_.description ] add_edit_link( data, url_for('member_update', id_=link_.id, origin_id=entity.id)) add_remove_link(data, link_.domain.name, link_, entity, 'member-of') tabs['member_of'].table.rows.append(data) if entity.class_.name != 'group': del tabs['member'] else: for link_ in entity.get_links('P107'): data = [ link(link_.range), link(link_.type), link_.first, link_.last, link_.description ] add_edit_link( data, url_for('member_update', id_=link_.id, origin_id=entity.id)) add_remove_link(data, link_.range.name, link_, entity, 'member') tabs['member'].table.rows.append(data) for link_ in entity.get_links('P52', True): data = [ link(link_.domain), link_.domain.class_.label, link(link_.domain.standard_type), link_.domain.first, link_.domain.last, link_.domain.description ] tabs['artifact'].table.rows.append(data) elif entity.class_.view == 'artifact': tabs['source'] = Tab('source', entity=entity) elif entity.class_.view == 'event': for name in ['subs', 'source', 'actor']: tabs[name] = Tab(name, entity=entity) for sub_event in entity.get_linked_entities('P117', inverse=True, nodes=True): tabs['subs'].table.rows.append(get_base_table_data(sub_event)) tabs['actor'].table.header.insert(5, _('activity')) # Activity column for link_ in entity.get_links(['P11', 'P14', 'P22', 'P23']): first = link_.first if not link_.first and entity.first: first = f'<span class="inactive">{entity.first}</span>' last = link_.last if not link_.last and entity.last: last = f'<span class="inactive">{entity.last}</span>' data = [ link(link_.range), link_.range.class_.label, link_.type.name if link_.type else '', first, last, g.properties[link_.property.code].name_inverse, link_.description ] add_edit_link( data, url_for('involvement_update', id_=link_.id, origin_id=entity.id)) add_remove_link(data, link_.range.name, link_, entity, 'actor') tabs['actor'].table.rows.append(data) entity.linked_places = [ location.get_linked_entity_safe('P53', True) for location in entity.get_linked_entities(['P7', 'P26', 'P27']) ] elif entity.class_.view == 'file': for name in [ 'source', 'event', 'actor', 'place', 'feature', 'stratigraphic_unit', 'artifact', 'human_remains', 'reference', 'type' ]: tabs[name] = Tab(name, entity=entity) entity.image_id = entity.id if get_file_path(entity.id) else None for link_ in entity.get_links('P67'): range_ = link_.range data = get_base_table_data(range_) add_remove_link(data, range_.name, link_, entity, range_.class_.name) tabs[range_.class_.view].table.rows.append(data) for link_ in entity.get_links('P67', True): data = get_base_table_data(link_.domain) data.append(link_.description) add_edit_link( data, url_for('reference_link_update', link_id=link_.id, origin_id=entity.id)) add_remove_link(data, link_.domain.name, link_, entity, 'reference') tabs['reference'].table.rows.append(data) elif entity.class_.view == 'place': tabs['source'] = Tab('source', entity=entity) if entity.class_.name == 'place': tabs['event'] = Tab('event', entity=entity) tabs['reference'] = Tab('reference', entity=entity) if entity.class_.name == 'place': tabs['actor'] = Tab('actor', entity=entity) tabs['feature'] = Tab('feature', entity=entity) elif entity.class_.name == 'feature': tabs['stratigraphic_unit'] = Tab('stratigraphic_unit', entity=entity) elif entity.class_.name == 'stratigraphic_unit': tabs['find'] = Tab('find', entity=entity) tabs['human_remains'] = Tab('human_remains', entity=entity) entity.location = entity.get_linked_entity_safe('P53', nodes=True) event_ids = [] # Keep track of inserted events to prevent doubles for event in entity.location.get_linked_entities(['P7', 'P26', 'P27'], inverse=True): tabs['event'].table.rows.append(get_base_table_data(event)) event_ids.append(event.id) for event in entity.get_linked_entities('P24', inverse=True): if event.id not in event_ids: # Don't add again if already in table tabs['event'].table.rows.append(get_base_table_data(event)) if 'actor' in tabs: for link_ in entity.location.get_links(['P74', 'OA8', 'OA9'], inverse=True): actor = Entity.get_by_id(link_.domain.id) tabs['actor'].table.rows.append([ link(actor), g.properties[link_.property.code].name, actor.class_.name, actor.first, actor.last, actor.description ]) elif entity.class_.view == 'reference': for name in [ 'source', 'event', 'actor', 'place', 'feature', 'stratigraphic_unit', 'human_remains', 'artifact', 'file' ]: tabs[name] = Tab(name, entity=entity) for link_ in entity.get_links('P67'): range_ = link_.range data = get_base_table_data(range_) data.append(link_.description) add_edit_link( data, url_for('reference_link_update', link_id=link_.id, origin_id=entity.id)) add_remove_link(data, range_.name, link_, entity, range_.class_.name) tabs[range_.class_.view].table.rows.append(data) elif entity.class_.view == 'source': for name in [ 'actor', 'artifact', 'feature', 'event', 'human_remains', 'place', 'stratigraphic_unit', 'text' ]: tabs[name] = Tab(name, entity=entity) for text in entity.get_linked_entities('P73', nodes=True): tabs['text'].table.rows.append([ link(text), next(iter(text.nodes)).name if text.nodes else '', text.description ]) for link_ in entity.get_links('P67'): range_ = link_.range data = get_base_table_data(range_) add_remove_link(data, range_.name, link_, entity, range_.class_.name) tabs[range_.class_.view].table.rows.append(data) if entity.class_.view in [ 'actor', 'artifact', 'event', 'place', 'source', 'type' ]: if entity.class_.view != 'reference' and not isinstance(entity, Node): tabs['reference'] = Tab('reference', entity=entity) if entity.class_.view == 'artifact': tabs['event'] = Tab('event', entity=entity) for link_ in entity.get_links('P25', True): data = get_base_table_data(link_.domain) tabs['event'].table.rows.append(data) tabs['file'] = Tab('file', entity=entity) entity.image_id = entity.get_profile_image_id() if entity.class_.view == 'place' and is_authorized('editor') and \ current_user.settings['module_map_overlay']: tabs['file'].table.header.append(uc_first(_('overlay'))) for link_ in entity.get_links('P67', inverse=True): domain = link_.domain data = get_base_table_data(domain) if domain.class_.view == 'file': # pragma: no cover extension = data[3] data.append( get_profile_image_table_link(domain, entity, extension, entity.image_id)) if not entity.image_id \ and extension in app.config['DISPLAY_FILE_EXTENSIONS']: entity.image_id = domain.id if entity.class_.view == 'place' \ and is_authorized('editor') \ and current_user.settings['module_map_overlay']: overlays = Overlay.get_by_object(entity) if extension in app.config['DISPLAY_FILE_EXTENSIONS']: if domain.id in overlays: add_edit_link( data, url_for('overlay_update', id_=overlays[domain.id].id)) else: data.append( link( _('link'), url_for('overlay_insert', image_id=domain.id, place_id=entity.id, link_id=link_.id))) else: # pragma: no cover data.append('') if domain.class_.view not in ['source', 'file']: data.append(link_.description) add_edit_link( data, url_for('reference_link_update', link_id=link_.id, origin_id=entity.id)) if domain.class_.view == 'reference_system': entity.reference_systems.append(link_) continue add_remove_link(data, domain.name, link_, entity, domain.class_.view) tabs[domain.class_.view].table.rows.append(data) structure = None # Needed for place gis_data = None # Needed for place if entity.class_.view in ['artifact', 'place']: structure = get_structure(entity) if structure: for item in structure['subunits']: tabs[item.class_.name].table.rows.append( get_base_table_data(item)) gis_data = Gis.get_all([entity], structure) if gis_data['gisPointSelected'] == '[]' \ and gis_data['gisPolygonSelected'] == '[]' \ and gis_data['gisLineSelected'] == '[]' \ and (not structure or not structure['super_id']): gis_data = {} if not gis_data: gis_data = Gis.get_all(entity.linked_places) \ if entity.linked_places else None entity.info_data = get_entity_data(entity, event_links=event_links) tabs['note'] = Tab('note', entity=entity) for note in current_user.get_notes_by_entity_id(entity.id): data = [ format_date(note['created']), uc_first(_('public')) if note['public'] else uc_first(_('private')), link(User.get_by_id(note['user_id'])), note['text'], f'<a href="{url_for("note_view", id_=note["id"])}">' f'{uc_first(_("view"))}</a>' ] tabs['note'].table.rows.append(data) if 'file' in tabs and current_user.settings['table_show_icons'] and \ session['settings']['image_processing']: tabs['file'].table.header.insert(1, uc_first(_('icon'))) for row in tabs['file'].table.rows: row.insert( 1, file_preview( int(row[0].replace('<a href="/entity/', '').split('"')[0]))) tabs['info'].content = render_template( 'entity/view.html', buttons=add_buttons(entity), entity=entity, gis_data=gis_data, structure=structure, # Needed for place views overlays=overlays, # Needed for place views title=entity.name) return render_template('tabs.html', tabs=tabs, gis_data=gis_data, crumbs=add_crumbs(entity, structure), entity=entity)
def get_geoms_by_entity(entity: Entity) -> Union[str, Dict[str, Any]]: geoms = Gis.get_by_id(entity.id) if len(geoms) == 1: return geoms[0] return {'type': 'GeometryCollection', 'geometries': geoms}
@app.route('/index/<view>/<int:delete_id>') @required_group('readonly') def index(view: str, delete_id: Optional[int] = None) -> Union[str, Response]: if delete_id: # Delete before showing index to prevent additional redirect if current_user.group == 'contributor': # pragma: no cover info = logger.get_log_info(delete_id) if not info['creator'] or info['creator'].id != current_user.id: abort(403) if url := delete_entity(delete_id): return redirect(url) return render_template( 'entity/index.html', class_=view, table=get_table(view), buttons=get_buttons(view), gis_data=Gis.get_all() if view == 'place' else None, title=_(view.replace('_', ' ')), crumbs=[[_('admin'), url_for('admin_index')], _('file')] if view == 'file' else [_(view).replace('_', ' ')]) def get_buttons(view: str) -> list[str]: buttons = [] for name in [view] if view in ['artifact', 'place'] \ else g.view_class_mapping[view]: if is_authorized(g.classes[name].write_access): buttons.append( button(g.classes[name].label, url_for('insert', class_=name))) return buttons
def test_api(self) -> None: with app.app_context(): # type: ignore with app.test_request_context(): app.preprocess_request() # type: ignore place = insert_entity('Nostromos', 'place', description='That is the Nostromos') if not place: # Needed for Mypy return # pragma: no cover # Adding Dates to place place.begin_from = '2018-01-31' place.begin_to = '2018-03-01' place.begin_comment = 'Begin of the Nostromos' place.end_from = '2019-01-31' place.end_to = '2019-03-01' place.end_comment = 'Destruction of the Nostromos' place.update() location = place.get_linked_entity_safe('P53') Gis.add_example_geom(location) # Adding Type Settlement place.link('P2', Node.get_hierarchy('Place')) # Adding Alias alias = insert_entity('Cargo hauler', 'appellation') place.link('P1', alias) # Adding External Reference external_reference = insert_entity('https://openatlas.eu', 'external_reference') external_reference.link('P67', place, description='OpenAtlas Website') # Adding feature to place feature = insert_entity('Feature', 'feature', place) # Adding stratigraphic to place insert_entity('Strato', 'stratigraphic_unit', feature) # Adding Administrative Unit Node unit_node = Node.get_hierarchy('Administrative unit') # Adding File to place file = insert_entity('Datei', 'file') file.link('P67', place) file.link('P2', g.nodes[Node.get_hierarchy('License').subs[0]]) # Adding Value Type value_type = Node.get_hierarchy('Dimensions') place.link('P2', Entity.get_by_id(value_type.subs[0]), '23.0') # Adding Geonames geonames = Entity.get_by_id( ReferenceSystem.get_by_name('GeoNames').id) precision_id = Node.get_hierarchy( 'External reference match').subs[0] geonames.link('P67', place, description='2761369', type_id=precision_id) # Test LinkedPlaces output self.maxDiff = None rv = self.app.get(url_for('api.entity', id_=place.id)) self.assertDictEqual(rv.get_json(), api_data.api_linked_place_template) # Test Geojson output rv = self.app.get( url_for('api.entity', id_=place.id, format='geojson')) self.assertDictEqual(rv.get_json(), api_data.api_geojson_template) # ---Content--- # /api/0.2/classes/ rv = self.app.get(url_for('api.class_mapping')) self.assertAlmostEqual(rv.get_json(), ClassMapping.mapping) # /api/0.2/content/ rv = self.app.get(url_for('api.content', lang='de')) self.assertDictEqual(rv.get_json(), api_data.api_content_de) rv = self.app.get(url_for('api.content', lang='en', download=True)) self.assertDictEqual(rv.get_json(), api_data.api_content_en) # /api/0.2/geometric_entities/ rv = self.app.get(url_for('api.geometric_entities')) self.assertDictEqual(rv.get_json(), api_data.api_geometries_template) rv = self.app.get(url_for('api.geometric_entities', download=True)) self.assertDictEqual(rv.get_json(), api_data.api_geometries_template) rv = self.app.get(url_for('api.geometric_entities', count=True)) assert b'1' in rv.data rv = self.app.get( url_for('api.geometric_entities', geometry='gisLineAll', count=True)) assert b'0' in rv.data # /api/0.2/overview_count/ rv = self.app.get(url_for('api.overview_count')) self.assertAlmostEqual(rv.get_json(), api_data.api_overview_count) # /api/0.2/overview_count/ rv = self.app.get(url_for('api.system_class_count')) self.assertDictEqual(rv.get_json(), api_data.api_system_class_count) # ---Nodes--- # /api/0.2/node_entities/ rv = self.app.get(url_for('api.node_entities', id_=unit_node.id)) self.assertDictEqual(rv.get_json(), api_data.api_node_entities) rv = self.app.get( url_for('api.node_entities', id_=unit_node.id, download=True)) self.assertDictEqual(rv.get_json(), api_data.api_node_entities) rv = self.app.get( url_for('api.node_entities', id_=unit_node.id, count=True)) assert b'6' in rv.data # /api/0.2/node_entities_all/ rv = self.app.get( url_for('api.node_entities_all', id_=unit_node.id)) self.assertDictEqual(rv.get_json(), api_data.api_node_entities_all) rv = self.app.get( url_for('api.node_entities_all', id_=unit_node.id, download=True)) self.assertDictEqual(rv.get_json(), api_data.api_node_entities_all) rv = self.app.get( url_for('api.node_entities_all', id_=unit_node.id, count=True)) assert b'8' in rv.data # # /api/0.2/node_overview/ # rv = self.app.get(url_for('api.node_overview')) # self.assertDictEqual(rv.get_json(), api_data.api_node_overview) # rv = self.app.get(url_for('api.node_overview', download=True)) # self.assertDictEqual(rv.get_json(), api_data.api_node_overview) # /api/0.2/subunit/ rv = self.app.get(url_for('api.subunit', id_=place.id)) self.assertDictEqual(rv.get_json(), api_data.api_subunit) rv = self.app.get( url_for('api.subunit', id_=place.id, download=True)) self.assertDictEqual(rv.get_json(), api_data.api_subunit) rv = self.app.get(url_for('api.subunit', id_=place.id, count=True)) assert b'1' in rv.data # /api/0.2/subunit_hierarchy/ rv = self.app.get(url_for('api.subunit_hierarchy', id_=place.id)) self.assertDictEqual(rv.get_json(), api_data.api_subunit_hierarchy) rv = self.app.get( url_for('api.subunit_hierarchy', id_=place.id, download=True)) self.assertDictEqual(rv.get_json(), api_data.api_subunit_hierarchy) rv = self.app.get( url_for('api.subunit_hierarchy', id_=place.id, count=True)) assert b'2' in rv.data # /api/0.2/type_tree/ # rv = self.app.get(url_for('api.type_tree')) # self.assertDictEqual(rv.get_json(), api_data.api_type_tree) # rv = self.app.get(url_for('api.type_tree', download=True)) # self.assertDictEqual(rv.get_json(), api_data.api_type_tree) # ---Entity--- # /api/0.2/code/ rv = self.app.get(url_for('api.code', code='reference')) self.assertDictEqual(rv.get_json(), api_data.api_code_reference) rv = self.app.get( url_for('api.code', code='reference', format='geojson')) self.assertDictEqual(rv.get_json(), api_data.api_code_reference_geojson) rv = self.app.get( url_for('api.code', code='reference', download=True)) self.assertDictEqual(rv.get_json(), api_data.api_code_reference) rv = self.app.get(url_for('api.code', code='place', count=True)) assert b'3' in rv.data rv = self.app.get( url_for('api.code', code='place', show='geometry', limit=2, sort='desc', first=feature.id)) self.assertDictEqual(rv.get_json(), api_data.api_code_place_first_sort_show_limit) rv = self.app.get( url_for('api.code', code='place', limit=10, sort='desc', column='name', filter='or|name|like|Nostromos')) self.assertDictEqual( rv.get_json(), api_data.api_code_place_limit_sort_column_filter) rv = self.app.get( url_for('api.code', code='place', filter='or|id|eq|' + str(place.id))) self.assertDictEqual(rv.get_json(), api_data.api_code_place_filter_id) rv = self.app.get( url_for('api.code', code='place', filter='or|begin_from|ge|2018-1-1')) self.assertDictEqual(rv.get_json(), api_data.api_code_place_filter_time) rv = self.app.get( url_for('api.code', code='reference', export='csv')) assert b'https://openatlas.eu' in rv.data rv = self.app.get( url_for('api.entities_linked_to_entity', id_=place.id)) self.assertDictEqual(rv.get_json(), api_data.api_entities_linked_entity) # Path Tests rv = self.app.get(url_for('api.class', class_code='E31')) assert b'https://openatlas.eu' in rv.data rv = self.app.get( url_for('api.class', class_code='E31', format='geojson')) assert b'https://openatlas.eu' in rv.data rv = self.app.get( url_for('api.class', class_code='E31', download=True)) assert b'https://openatlas.eu' in rv.data rv = self.app.get( url_for('api.class', class_code='E18', export='csv')) assert b'Nostromos' in rv.data rv = self.app.get(url_for('api.latest', latest=10)) assert b'Datei' in rv.data rv = self.app.get(url_for('api.latest', count=True, latest=2)) assert b'2' in rv.data rv = self.app.get( url_for('api.system_class', system_class='appellation')) assert b'Cargo hauler' in rv.data rv = self.app.get( url_for('api.system_class', system_class='appellation', format='geojson')) assert b'Cargo hauler' in rv.data rv = self.app.get(url_for('api.type_entities', id_=unit_node.id)) assert b'Austria' in rv.data rv = self.app.get( url_for('api.type_entities_all', id_=unit_node.id)) assert b'Austria' in rv.data rv = self.app.get( url_for('api.query', entities=place.id, classes='E18', items='place')) assert b'Nostromos' in rv.data rv = self.app.get( url_for('api.query', entities=place.id, classes='E18', items='place', format='geojson')) assert b'Nostromos' in rv.data # Path test with download rv = self.app.get( url_for('api.entity', id_=place.id, download=True)) assert b'Nostromos' in rv.data rv = self.app.get(url_for('api.latest', latest=1, download=True)) assert b'Datei' in rv.data rv = self.app.get( url_for('api.system_class', system_class='appellation', download=True)) assert b'Cargo hauler' in rv.data rv = self.app.get( url_for('api.query', classes='E31', download=True)) assert b'https://openatlas.eu' in rv.data rv = self.app.get(url_for('api.overview_count', download=True)) assert b'systemClass' in rv.data rv = self.app.get(url_for('api.class_mapping', download=True)) assert b'systemClass' in rv.data # Path with export rv = self.app.get(url_for('api.entity', id_=place.id, export='csv')) assert b'Nostromos' in rv.data rv = self.app.get( url_for('api.system_class', system_class='place', export='csv')) assert b'Nostromos' in rv.data # Testing Subunit # Parameter: filter rv = self.app.get( url_for('api.class', class_code='E18', filter='or|name|like|Nostr')) assert b'Nostromos' in rv.data # Parameter: last rv = self.app.get( url_for('api.class', class_code='E18', last=place.id)) assert b'entities' in rv.data # Parameter: first rv = self.app.get( url_for('api.class', class_code='E18', first=place.id)) assert b'entities' in rv.data # Parameter: show rv = self.app.get( url_for('api.class', class_code='E31', show='types')) assert b'https://openatlas.eu' in rv.data rv = self.app.get( url_for('api.class', class_code='E18', show='when')) assert b'Nostromos' in rv.data rv = self.app.get( url_for('api.class', class_code='E31', show='none')) assert b'https://openatlas.eu' in rv.data # Parameter: count rv = self.app.get( url_for('api.class', class_code='E31', count=True)) assert b'2' in rv.data rv = self.app.get( url_for('api.system_class', system_class='appellation', count=True)) assert b'1' in rv.data rv = self.app.get( url_for('api.query', entities=place.id, classes='E18', codes='place')) assert b'Nostromos' in rv.data rv = self.app.get( url_for('api.query', entities=place.id, classes='E18', codes='place', count=True)) assert b'7' in rv.data
def view(id_: int) -> Union[str, Response]: if id_ in g.types: # Types have their own view entity = g.types[id_] if not entity.root: return redirect( f"{url_for('type_index')}" f"#menu-tab-{entity.category}_collapse-{id_}") elif id_ in g.reference_systems: entity = g.reference_systems[id_] else: entity = Entity.get_by_id(id_, types=True, aliases=True) if not entity.class_.view: flash(_("This entity can't be viewed directly."), 'error') abort(400) event_links = None # Needed for actor and info data tabs = {'info': Tab('info')} if isinstance(entity, Type): tabs |= add_tabs_for_type(entity) elif isinstance(entity, ReferenceSystem): tabs |= add_tabs_for_reference_system(entity) elif entity.class_.view == 'actor': event_links = entity.get_links( ['P11', 'P14', 'P22', 'P23', 'P25'], True) tabs |= add_tabs_for_actor(entity, event_links) elif entity.class_.view == 'artifact': tabs['source'] = Tab('source', entity=entity) elif entity.class_.view == 'event': tabs |= add_tabs_for_event(entity) elif entity.class_.view == 'file': tabs |= add_tabs_for_file(entity) elif entity.class_.view == 'place': tabs |= add_tabs_for_place(entity) elif entity.class_.view == 'reference': tabs |= add_tabs_for_reference(entity) elif entity.class_.view == 'source': tabs |= add_tabs_for_source(entity) overlays = None # Needed for place if entity.class_.view in [ 'actor', 'artifact', 'event', 'place', 'source', 'type']: if not isinstance(entity, Type): tabs['reference'] = Tab('reference', entity=entity) if entity.class_.view == 'artifact': tabs['event'] = Tab('event', entity=entity) for link_ in entity.get_links(['P25', 'P108'], True): data = get_base_table_data(link_.domain) tabs['event'].table.rows.append(data) tabs['file'] = Tab('file', entity=entity) entity.image_id = entity.get_profile_image_id() if entity.class_.view == 'place' \ and is_authorized('editor') \ and current_user.settings['module_map_overlay']: tabs['file'].table.header.append(uc_first(_('overlay'))) for link_ in entity.get_links('P67', inverse=True): domain = link_.domain data = get_base_table_data(domain) if domain.class_.view == 'file': # pragma: no cover extension = data[3] data.append( get_profile_image_table_link( domain, entity, extension, entity.image_id)) if not entity.image_id \ and extension in app.config['DISPLAY_FILE_EXTENSIONS']: entity.image_id = domain.id if entity.class_.view == 'place' \ and is_authorized('editor') \ and current_user.settings['module_map_overlay']: overlays = Overlay.get_by_object(entity) if extension in app.config['DISPLAY_FILE_EXTENSIONS']: if domain.id in overlays: data.append(edit_link( url_for( 'overlay_update', id_=overlays[domain.id].id))) else: data.append(link(_('link'), url_for( 'overlay_insert', image_id=domain.id, place_id=entity.id, link_id=link_.id))) else: # pragma: no cover data.append('') if domain.class_.view not in ['source', 'file']: data.append(link_.description) data.append(edit_link( url_for('link_update', id_=link_.id, origin_id=entity.id))) if domain.class_.view == 'reference_system': entity.reference_systems.append(link_) continue data.append( remove_link(domain.name, link_, entity, domain.class_.view)) tabs[domain.class_.view].table.rows.append(data) if 'file' in tabs \ and current_user.settings['table_show_icons'] \ and g.settings['image_processing']: tabs['file'].table.header.insert(1, uc_first(_('icon'))) for row in tabs['file'].table.rows: row.insert( 1, file_preview( int(row[0].replace('<a href="/entity/', '').split('"')[0])) ) place_structure = None gis_data = None if entity.class_.view in ['artifact', 'place']: place_structure = get_structure(entity) if place_structure: for item in place_structure['subunits']: tabs[item.class_.name].table.rows.append( get_base_table_data(item)) gis_data = Gis.get_all([entity], place_structure) if gis_data['gisPointSelected'] == '[]' \ and gis_data['gisPolygonSelected'] == '[]' \ and gis_data['gisLineSelected'] == '[]' \ and (not place_structure or not place_structure['super_id']): gis_data = {} entity.info_data = get_entity_data(entity, event_links=event_links) if not gis_data: # Has to be after get_entity_data() gis_data = Gis.get_all(entity.linked_places) \ if entity.linked_places else None problematic_type_id = entity.check_for_too_many_links_for_single_type() tabs['note'] = add_note_tab(entity) tabs['info'].content = render_template( 'entity/view.html', buttons=add_buttons(entity, bool(problematic_type_id)), entity=entity, gis_data=gis_data, structure=place_structure, overlays=overlays, title=entity.name, problematic_type_id=problematic_type_id) return render_template( 'tabs.html', tabs=tabs, gis_data=gis_data, crumbs=add_crumbs(entity, place_structure), entity=entity)