def test_node(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_node = NodeMapper.get_hierarchy_by_name('Actor Actor Relation')
                sex_node = NodeMapper.get_hierarchy_by_name('Sex')
            rv = self.app.get(url_for('node_index'))
            assert b'Actor Actor Relation' in rv.data
            rv = self.app.get(url_for('node_insert', root_id=actor_node.id, super_id=actor_node.id))
            assert b'Actor Actor Relation' in rv.data
            rv = self.app.post(
                url_for('node_insert', root_id=actor_node.id), data={'name_search': 'new'})
            assert b'Inverse' in rv.data
            data = {
                'name': 'My secret node',
                'name_inverse': 'Do I look inverse?',
                'description': 'Very important!'}
            rv = self.app.post(url_for('node_insert', root_id=actor_node.id), data=data)
            node_id = rv.location.split('/')[-1].replace('node#tab-', '')
            rv = self.app.get(url_for('node_update', id_=node_id))
            assert b'My secret node' in rv.data and b'Super' in rv.data
            self.app.post(url_for('node_insert', root_id=sex_node.id), data=data)
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'Changes have been saved.' in rv.data

            # Test insert an continue
            data['continue_'] = 'yes'
            rv = self.app.post(
                url_for('node_insert', root_id=actor_node.id), data=data, follow_redirects=True)
            assert b'An entry has been created' in rv.data
            data['continue_'] = ''

            # Test forbidden system node
            rv = self.app.post(
                url_for('node_update', id_=actor_node.id), data=data, follow_redirects=True)
            assert b'Forbidden' in rv.data

            # Test update with self as root
            data[str(actor_node.id)] = node_id
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'Type can't have itself as super.' in rv.data

            # Test update with a child as root
            rv = self.app.post(url_for('node_insert', root_id=actor_node.id), data=data)
            child_node_id = rv.location.split('/')[-1].replace('node#tab-', '')
            data[str(actor_node.id)] = child_node_id
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'Type can't have a sub as super.' in rv.data

            # Test delete system node
            rv = self.app.get(url_for('node_delete', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.get(url_for('node_delete', id_=child_node_id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
Ejemplo n.º 2
0
    def test_hierarchy(self):
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('hierarchy_insert', param='custom'))
            assert b'+ Custom' in rv.data
            data = {'name': 'Geronimo', 'multiple': True, 'description': 'Very important!'}
            rv = self.app.post(url_for('hierarchy_insert', param='custom'), data=data)
            hierarchy_id = rv.location.split('/')[-1].replace('types#tab-', '')
            rv = self.app.get(url_for('hierarchy_update', id_=hierarchy_id))
            assert b'Geronimo' in rv.data
            rv = self.app.post(
                url_for('hierarchy_update', id_=hierarchy_id), data=data, follow_redirects=True)
            assert b'Changes have been saved.' in rv.data
            data['name'] = 'Actor Actor Relation'
            rv = self.app.post(
                url_for('hierarchy_update', id_=hierarchy_id), data=data, follow_redirects=True)
            assert b'The name is already in use' in rv.data
            rv = self.app.post(url_for('hierarchy_delete', id_=hierarchy_id), follow_redirects=True)
            assert b'deleted' in rv.data

            # Test checks
            actor_node = NodeMapper.get_hierarchy_by_name('Actor Actor Relation')
            rv = self.app.get(url_for('hierarchy_update', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.get(url_for('hierarchy_delete', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.post(url_for('hierarchy_insert', param='custom'), data=data)
            assert b'The name is already in use' in rv.data
Ejemplo n.º 3
0
    def test_hierarchy(self):
        with app.app_context():
            self.login()

            # Custom types
            data = {
                'name': 'Geronimo',
                'forms': [1, 2, 4, 5, 6],
                'multiple': True,
                'description': 'Very important!'}
            rv = self.app.post(url_for('hierarchy_insert', param='custom'), data=data)
            hierarchy_id = rv.location.split('/')[-1].replace('types#tab-', '')
            rv = self.app.get(url_for('hierarchy_update', id_=hierarchy_id))
            assert b'Geronimo' in rv.data
            data['forms'] = [3]
            rv = self.app.post(
                url_for('hierarchy_update', id_=hierarchy_id), data=data, follow_redirects=True)
            assert b'Changes have been saved.' in rv.data

            rv = self.app.get(url_for('hierarchy_insert', param='custom'))
            assert b'+ Custom' in rv.data

            data = {'name': 'My secret node', 'description': 'Very important!'}
            rv = self.app.post(url_for('node_insert', root_id=hierarchy_id), data=data)
            node_id = rv.location.split('/')[-1].replace('types#tab-', '')
            rv = self.app.get(url_for('hierarchy_remove_form', id_=hierarchy_id, remove_id=2),
                              follow_redirects=True)
            assert b'Changes have been saved.' in rv.data
            self.app.get(url_for('node_delete', id_=node_id))

            data['name'] = 'Actor Actor Relation'
            rv = self.app.post(
                url_for('hierarchy_update', id_=hierarchy_id), data=data, follow_redirects=True)
            assert b'The name is already in use' in rv.data
            rv = self.app.post(url_for('hierarchy_delete', id_=hierarchy_id), follow_redirects=True)
            assert b'deleted' in rv.data

            # Value types
            rv = self.app.get(url_for('hierarchy_insert', param='value'))
            assert b'+ Value' in rv.data
            data2 = {'name': 'A valued value type', 'forms': [1], 'description': ''}
            rv = self.app.post(url_for('hierarchy_insert', param='value'), data=data2)
            custom_hierarchy_id = rv.location.split('/')[-1].replace('types#tab-', '')
            rv = self.app.get(url_for('hierarchy_update', id_=custom_hierarchy_id))
            assert b'valued' in rv.data

            # Test checks
            actor_node = NodeMapper.get_hierarchy_by_name('Actor Actor Relation')
            rv = self.app.get(url_for('hierarchy_update', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.get(url_for('hierarchy_delete', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.post(url_for('hierarchy_insert', param='custom'), data=data)
            assert b'The name is already in use' in rv.data
Ejemplo n.º 4
0
    def test_involvement(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_id = EntityMapper.insert('E21', 'Captain Miller').id
                event_id = EntityMapper.insert('E8', 'Event Horizon').id
                involvement_id = NodeMapper.get_hierarchy_by_name(
                    'Involvement').id

            # add involvement
            rv = self.app.get(url_for('involvement_insert',
                                      origin_id=actor_id))
            assert b'Involvement' in rv.data
            data = {
                'event': '[' + str(event_id) + ']',
                'activity': 'P11',
                involvement_id: involvement_id
            }
            rv = self.app.post(url_for('involvement_insert',
                                       origin_id=actor_id),
                               data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            data = {
                'actor': '[' + str(actor_id) + ']',
                'continue_': 'yes',
                'activity': 'P22'
            }
            rv = self.app.post(url_for('involvement_insert',
                                       origin_id=event_id),
                               data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            self.app.get(url_for('event_view', id_=event_id))

            # update involvement
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(event_id, 'P22')[0].id
            rv = self.app.get(
                url_for('involvement_update', id_=link_id, origin_id=event_id))
            assert b'Captain' in rv.data
            rv = self.app.post(url_for('involvement_update',
                                       id_=link_id,
                                       origin_id=actor_id),
                               data={
                                   'description':
                                   'Infinite Space - Infinite Terror',
                                   'activity': 'P23'
                               },
                               follow_redirects=True)
            assert b'Infinite Space - Infinite Terror' in rv.data
            self.app.get(url_for('event_view', id_=event_id))
Ejemplo n.º 5
0
    def test_node(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_node = NodeMapper.get_hierarchy_by_name('Actor Actor Relation')
                sex_node = NodeMapper.get_hierarchy_by_name('Sex')
            rv = self.app.get(url_for('node_index'))
            assert b'Actor Actor Relation' in rv.data
            rv = self.app.post(
                url_for('node_insert', root_id=actor_node.id), data={'name_search': 'new'})
            assert b'Inverse' in rv.data
            data = {
                'name': 'My secret node',
                'name_inverse': 'Do I look inverse?',
                'description': 'Very important!'}
            rv = self.app.post(url_for('node_insert', root_id=actor_node.id), data=data)
            node_id = rv.location.split('/')[-1].replace('node#tab-', '')
            rv = self.app.get(url_for('node_update', id_=node_id))
            assert b'My secret node' in rv.data and b'Super' in rv.data
            self.app.post(url_for('node_insert', root_id=sex_node.id), data=data)
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'Changes have been saved.' in rv.data

            # Test forbidden system node
            rv = self.app.post(
                url_for('node_update', id_=actor_node.id), data=data, follow_redirects=True)
            assert b'Forbidden' in rv.data

            # Test update with self as root
            data[str(actor_node.id)] = node_id
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'super' in rv.data

            # Test delete system node
            rv = self.app.get(url_for('node_delete', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.get(url_for('node_delete', id_=node_id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
Ejemplo n.º 6
0
 def __call__(self, field, **kwargs):
     from openatlas.models.node import NodeMapper
     selection = ''
     selected_ids = []
     if field.data:
         field.data = field.data[0] if isinstance(field.data, list) else field.data
         selection = g.nodes[int(field.data)].name
         selected_ids.append(g.nodes[int(field.data)].id)
     try:
         hierarchy_id = int(field.id)
     except ValueError:
         hierarchy_id = NodeMapper.get_hierarchy_by_name(uc_first(field.id)).id
     root = g.nodes[hierarchy_id]
     html = """
         <input id="{name}-button" name="{name}-button" type="text"
             class="table-select {required}" onfocus="this.blur()"
             readonly="readonly" value="{selection}" placeholder="{change_label}" />
         <a id="{name}-clear" {clear_style} class="button"
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
             <div id="{name}-dialog" class="overlay-container">
                 <input class="tree-filter" id="{name}-tree-search" placeholder="Filter" />
                 <div id="{name}-tree"></div>
             </div>
         </div>
         <script>
             $(document).ready(function () {{
                 createOverlay("{name}","{title}",false,);
                 $("#{name}-tree").jstree({{
                     "core" : {{"check_callback" : true, 'data':[{tree_data}]}},
                     "search": {{"case_insensitive": true, "show_only_matches": true}},
                     "plugins" : ["search"],
                 }});
                 $("#{name}-tree").on("select_node.jstree", function (e, data) {{
                     selectFromTree("{name}", data.node.id, data.node.text);
                 }});
                 $("#{name}-tree-search").keyup(function() {{
                     $("#{name}-tree").jstree("search", $(this).val());
                 }});
             }});
         </script>""".format(
         name=field.id,
         title=root.name,
         change_label=uc_first(_('change')),
         clear_label=uc_first(_('clear')),
         selection=selection,
         tree_data=NodeMapper.get_tree_data(hierarchy_id, selected_ids),
         clear_style='' if selection else ' style="display: none;" ',
         required=' required' if field.flags.required else '')
     return super(TreeSelect, self).__call__(field, **kwargs) + html
Ejemplo n.º 7
0
 def print_base_type(self):
     from openatlas.models.node import NodeMapper
     if not self.view_name or self.view_name == 'actor':  # actors have no base type
         return ''
     root_name = self.view_name.title()
     if self.view_name == 'reference':
         root_name = self.system_type.title()
     elif self.view_name == 'file':
         root_name = 'License'
     elif self.view_name == 'place':
         root_name = uc_first(self.system_type)
         if self.system_type == 'stratigraphic unit':
             root_name = 'Stratigraphic Unit'
     root_id = NodeMapper.get_hierarchy_by_name(root_name).id
     for node in self.nodes:
         if node.root and node.root[-1] == root_id:
             return node.name
     return ''
Ejemplo n.º 8
0
 def print_base_type(self):
     from openatlas.models.node import NodeMapper
     view_name = get_view_name(self)
     if not view_name or view_name == 'actor':  # actors have no base type
         return ''
     root_name = view_name.title()
     if view_name == 'reference':
         root_name = self.system_type.title()
     elif view_name == 'file':
         root_name = 'License'
     elif view_name == 'place':
         root_name = uc_first(self.system_type)
         if self.system_type == 'stratigraphic unit':
             root_name = 'Stratigraphic Unit'
     root_id = NodeMapper.get_hierarchy_by_name(root_name).id
     for node in self.nodes:
         if node.root and node.root[-1] == root_id:
             return node.name
     return ''
    def test_involvement(self):
        with app.app_context():
            self.login()
            rv = self.app.post(url_for('event_insert', code='E8'),
                               data={
                                    'name': 'Event Horizon',
                                    'date_begin_year': '1949',
                                    'date_begin_month': '10',
                                    'date_begin_day': '8',
                                    'date_end_year': '1951'})
            event_id = int(rv.location.split('/')[-1])
            with app.test_request_context():
                app.preprocess_request()
                actor_id = EntityMapper.insert('E21', 'Captain Miller').id
                involvement_id = NodeMapper.get_hierarchy_by_name('Involvement').id

            # Add involvement
            rv = self.app.get(url_for('involvement_insert', origin_id=actor_id))
            assert b'Involvement' in rv.data
            data = {'event': '[' + str(event_id) + ']', 'activity': 'P11',
                    involvement_id: involvement_id}
            rv = self.app.post(url_for('involvement_insert', origin_id=actor_id), data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            data = {'actor': '[' + str(actor_id) + ']', 'continue_': 'yes', 'activity': 'P22'}
            rv = self.app.post(url_for('involvement_insert', origin_id=event_id), data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            self.app.get(url_for('event_view', id_=event_id))

            # Update involvement
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(event_id, 'P22')[0].id
            rv = self.app.get(url_for('involvement_update', id_=link_id, origin_id=event_id))
            assert b'Captain' in rv.data
            rv = self.app.post(
                url_for('involvement_update', id_=link_id, origin_id=actor_id),
                data={'description': 'Infinite Space - Infinite Terror', 'activity': 'P23'},
                follow_redirects=True)
            assert b'Infinite Space - Infinite Terror' in rv.data
            self.app.get(url_for('event_view', id_=event_id))
Ejemplo n.º 10
0
 def print_base_type(self) -> str:
     from openatlas.models.node import NodeMapper
     if not self.view_name or self.view_name == 'actor':  # actors have no base type
         return ''
     root_name = self.view_name.title()
     if self.view_name == 'reference':
         root_name = self.system_type.title()
         if root_name == 'External Reference Geonames':
             root_name = 'External Reference'
     elif self.view_name == 'file':
         root_name = 'License'
     elif self.view_name == 'place':
         root_name = uc_first(self.system_type)
         if self.system_type == 'stratigraphic unit':
             root_name = 'Stratigraphic Unit'
     elif self.class_.code == 'E84':
         root_name = 'Information Carrier'
     root_id = NodeMapper.get_hierarchy_by_name(root_name).id
     for node in self.nodes:
         if node.root and node.root[-1] == root_id:
             return node.name
     return ''
Ejemplo n.º 11
0
 def get_all(object_ids=None):
     all_ = {'point': [], 'polygon': []}
     selected = {'point': [], 'polygon': [], 'polygon_point': []}
     object_ids = object_ids if object_ids else []
     object_ids = object_ids if isinstance(object_ids, list) else [object_ids]
     polygon_point_sql = """
         (SELECT public.ST_AsGeoJSON(public.ST_PointOnSurface(p.geom))
         FROM gis.polygon p WHERE id = polygon.id) AS polygon_point, """
     for shape in ['point', 'polygon']:
         sql = """
             SELECT
                 object.id AS object_id,
                 {shape}.id,
                 {shape}.name,
                 {shape}.description,
                 {shape}.type,
                 public.ST_AsGeoJSON({shape}.geom) AS geojson, {polygon_point_sql}
                 object.name AS object_name,
                 object.description AS object_desc,
                 object.system_type AS object_system_type,
                 string_agg(CAST(t.range_id AS text), ',') AS types,
                 (SELECT COUNT(*) FROM gis.point point2
                     WHERE {shape}.entity_id = point2.entity_id) AS point_count,
                 (SELECT COUNT(*) FROM gis.polygon polygon2
                     WHERE {shape}.entity_id = polygon2.entity_id) AS polygon_count
             FROM model.entity place
             JOIN model.link l ON place.id = l.range_id
             JOIN model.entity object ON l.domain_id = object.id
             JOIN gis.{shape} {shape} ON place.id = {shape}.entity_id
             LEFT JOIN model.link t ON object.id = t.domain_id AND t.property_code = 'P2'
             WHERE place.class_code = 'E53'
                 AND l.property_code = 'P53'
                 AND object.system_type = 'place'
             GROUP BY object.id, {shape}.id;""".format(
                     shape=shape,
                     polygon_point_sql=polygon_point_sql if shape == 'polygon' else '')
         g.cursor.execute(sql)
         place_type_root_id = NodeMapper.get_hierarchy_by_name('Place').id
         for row in g.cursor.fetchall():
             description = row.description.replace('"', '\"') if row.description else ''
             object_desc = row.object_desc.replace('"', '\"') if row.object_desc else ''
             item = {
                 'type': 'Feature',
                 'geometry': json.loads(row.geojson),
                 'properties': {
                     'title': row.object_name.replace('"', '\"'),
                     'objectId': row.object_id,
                     'objectDescription': object_desc,
                     'id': row.id,
                     'name': row.name.replace('"', '\"'),
                     'description': description,
                     'siteType': '',
                     'shapeType': uc_first(row.type),
                     'count': row.point_count + row.polygon_count}}
             if hasattr(row, 'types') and row.types:
                 nodes_list = ast.literal_eval('[' + row.types + ']')
                 for node_id in list(set(nodes_list)):
                     node = g.nodes[node_id]
                     if node.root and node.root[-1] == place_type_root_id:
                         item['properties']['siteType'] = node.name
                         break
             if row.object_id in object_ids:
                 selected[shape].append(item)
             elif row.object_system_type != 'place':
                 continue
             else:
                 all_[shape].append(item)
             if hasattr(row, 'polygon_point'):
                 polygon_point_item = dict(item)  # make a copy to prevent overriding geometry
                 polygon_point_item['geometry'] = json.loads(row.polygon_point)
                 if row.object_id in object_ids:
                     selected['polygon_point'].append(polygon_point_item)
                 elif row.object_system_type != 'place':
                     continue
                 else:
                     all_['point'].append(polygon_point_item)
     gis = {
         'gisPointAll': json.dumps(all_['point']),
         'gisPointSelected': json.dumps(selected['point']),
         'gisPolygonAll': json.dumps(all_['polygon']),
         'gisPolygonSelected': json.dumps(selected['polygon']),
         'gisPolygonPointSelected': json.dumps(selected['polygon_point'])}
     return gis
Ejemplo n.º 12
0
    def test_place(self):
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('place_insert'))
            assert b'+ Place' in rv.data
            data = {'name': 'Asgard', 'alias-0': 'Valhöll'}
            with app.test_request_context():
                app.preprocess_request()
                reference_id = EntityMapper.insert('E31', 'Ancient Books', 'edition').id
                place_node = NodeMapper.get_hierarchy_by_name('Place')
                source_id = EntityMapper.insert('E33', 'Tha source').id
            rv = self.app.post(url_for('place_insert', origin_id=reference_id), data=data,
                               follow_redirects=True)
            assert b'Asgard' in rv.data
            gis_points = """[{"type":"Feature", "geometry":{"type":"Point", "coordinates":[9,17]},
                    "properties":{"name":"Valhalla","description":"","shapeType":"centerpoint"}}]"""
            data['gis_points'] = gis_points
            gis_polygons = """[{"geometry":{
                "coordinates":[[[9.75307425847859,17.8111792731339],
                [9.75315472474904,17.8110005175436],[9.75333711496205,17.8110873417098],
                [9.75307425847859,17.8111792731339]]],"type":"Polygon"},
                "properties":{"count":4,"description":"","id":8,"name":"",
                "objectDescription":"","objectId":185,"shapeType":"Shape",
                "siteType":"Settlement","title":""},"type":"Feature"}]"""
            data['gis_polygons'] = gis_polygons
            data[place_node.id] = place_node.subs
            data['continue_'] = 'yes'
            rv = self.app.post(
                url_for('place_insert', origin_id=source_id), data=data, follow_redirects=True)
            assert b'Tha source' in rv.data
            with app.test_request_context():
                app.preprocess_request()
                places = EntityMapper.get_by_codes('place')
                place_id = places[0].id
                second_place_id = places[1].id
                location = LinkMapper.get_linked_entity(second_place_id, 'P53')
                actor_id = EntityMapper.insert('E21', 'Milla Jovovich').id
                LinkMapper.insert(actor_id, 'P74', location.id)
            assert b'Tha source' in rv.data
            rv = self.app.get(url_for('place_index'))
            assert b'Asgard' in rv.data
            rv = self.app.get(url_for('place_update', id_=place_id))
            assert b'Valhalla' in rv.data
            data['continue_'] = ''
            data['alias-1'] = 'Val-hall'
            rv = self.app.post(
                url_for('place_update', id_=place_id), data=data, follow_redirects=True)
            assert b'Val-hall' in rv.data
            with app.test_request_context():
                app.preprocess_request()
                event = EntityMapper.insert('E8', 'Valhalla rising')
                event.link('P7', location)
                event.link('P24', location)
            rv = self.app.get(
                url_for(
                    'place_view', id_=second_place_id, unlink_id=place_id), follow_redirects=True)
            assert b'Link removed' in rv.data and b'Milla Jovovich' in rv.data

            # Subunits
            with app.app_context():
                self.app.get(url_for('place_insert', origin_id=place_id))
                name = "It's not a bug, it's a feature!"
                rv = self.app.post(url_for('place_insert', origin_id=place_id), data={'name': name})
                feat_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_insert', origin_id=feat_id))
                self.app.get(url_for('place_update', id_=feat_id))
                self.app.post(url_for('place_update', id_=feat_id), data={'name': name})
                name = "I'm a stratigraphic unit"
                rv = self.app.post(url_for('place_insert', origin_id=feat_id), data={'name': name})
                strat_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_insert', origin_id=strat_id))
                self.app.get(url_for('place_update', id_=strat_id))
                self.app.post(url_for('place_update', id_=strat_id), data={'name': name})
                name = "You never find me"
                rv = self.app.post(url_for('place_insert', origin_id=strat_id), data={'name': name})
                find_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_update', id_=find_id))
                self.app.post(url_for('place_update', id_=find_id), data={'name': name})
            rv = self.app.get(url_for('place_view', id_=feat_id))
            assert b'not a bug' in rv.data
            rv = self.app.get(url_for('place_view', id_=strat_id))
            assert b'a stratigraphic unit' in rv.data
            rv = self.app.get(url_for('place_view', id_=find_id))
            assert b'You never' in rv.data
            rv = self.app.get(url_for('place_delete', id_=place_id), follow_redirects=True)
            assert b'not possible if subunits' in rv.data
            rv = self.app.get(url_for('place_delete', id_=find_id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
Ejemplo n.º 13
0
    def update_geonames(form: FlaskForm, object_: Entity) -> None:
        new_geonames_id = form.geonames_id.data
        geonames_link = GeonamesMapper.get_geonames_link(object_)
        geonames_entity = geonames_link.domain if geonames_link else None

        if not new_geonames_id:
            if geonames_entity:
                if len(geonames_entity.get_links(['P67'
                                                  ])) > 1:  # pragma: no cover
                    if geonames_link:
                        geonames_link.delete(
                        )  # There are more linked so only remove this link
                else:
                    geonames_entity.delete(
                    )  # Nothing else is linked to the reference so delete it
            return

        # Get id of the match type
        match_id = None
        for node_id in NodeMapper.get_hierarchy_by_name(
                'External Reference Match').subs:
            if g.nodes[
                    node_id].name == 'exact match' and form.geonames_precision.data:
                match_id = node_id
                break
            if g.nodes[
                    node_id].name == 'close match' and not form.geonames_precision.data:
                match_id = node_id
                break

        # There wasn't one linked before
        if not geonames_entity:
            reference = EntityMapper.get_by_name_and_system_type(
                new_geonames_id, 'external reference geonames')
            if not reference:  # The selected reference doesn't exist so create it
                reference = EntityMapper.insert('E31',
                                                new_geonames_id,
                                                'external reference geonames',
                                                description='GeoNames ID')
            object_.link('P67', reference, inverse=True, type_id=match_id)
            return

        if geonames_link and int(new_geonames_id) == int(geonames_entity.name) \
                and match_id == geonames_link.type.id:
            return  # It's the same link so do nothing

        # Only the match type change so delete and recreate the link
        if geonames_link and int(new_geonames_id) == int(geonames_entity.name):
            geonames_link.delete()
            object_.link('P67',
                         geonames_entity,
                         inverse=True,
                         type_id=match_id)
            return

        # Its linked to a different geonames reference
        if geonames_link and len(geonames_entity.get_links(['P67'])) > 1:
            geonames_link.delete(
            )  # There are more linked so only remove this link
        else:  # pragma: no cover
            geonames_entity.delete(
            )  # Nothing else is linked to the reference so delete it
        reference = EntityMapper.get_by_name_and_system_type(
            new_geonames_id, 'external reference geonames')

        if not reference:  # The selected reference doesn't exist so create it
            reference = EntityMapper.insert('E31',
                                            new_geonames_id,
                                            'external reference geonames',
                                            description='GeoNames ID')
        object_.link('P67', reference, inverse=True, type_id=match_id)
    def test_relation(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_id = EntityMapper.insert('E21', 'Connor MacLeod').id
                related_id = EntityMapper.insert('E21', 'The Kurgan').id

            # Add relationship
            rv = self.app.get(url_for('relation_insert', origin_id=actor_id))
            assert b'Actor Actor Relation' in rv.data
            relation_id = NodeMapper.get_hierarchy_by_name('Actor Actor Relation').id
            relation_sub_id = g.nodes[relation_id].subs[0]
            data = {
                'actor': '[' + str(related_id) + ']',
                relation_id: relation_sub_id,
                'inverse': None,
                'date_begin_year': '-1949',
                'date_begin_month': '10',
                'date_begin_day': '8',
                'date_begin_year2': '-1948',
                'date_end_year': '2049',
                'date_end_year2': '2050'}
            rv = self.app.post(
                url_for('relation_insert', origin_id=actor_id), data=data, follow_redirects=True)
            assert b'The Kurgan' in rv.data
            rv = self.app.get(url_for('node_view', id_=relation_sub_id))
            assert b'Connor' in rv.data
            data['continue_'] = 'yes'
            data['inverse'] = True
            rv = self.app.post(
                url_for('relation_insert', origin_id=actor_id), data=data, follow_redirects=True)
            assert b'The Kurgan' in rv.data
            rv = self.app.get(url_for('actor_view', id_=actor_id))
            assert b'The Kurgan' in rv.data

            rv = self.app.post(
                url_for('relation_insert', origin_id=related_id), data=data, follow_redirects=True)
            assert b"Can't link to itself." in rv.data

            # Relation types
            rv = self.app.get(url_for('node_move_entities', id_=relation_sub_id))
            assert b'The Kurgan' in rv.data

            # Update relationship
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(actor_id, 'OA7')[0].id
                link_id2 = LinkMapper.get_links(actor_id, 'OA7', True)[0].id
            rv = self.app.get(url_for('relation_update', id_=link_id, origin_id=related_id))
            assert b'Connor' in rv.data
            rv = self.app.post(
                url_for('relation_update', id_=link_id, origin_id=actor_id),
                data={'description': 'There can be only one!', 'inverse': True},
                follow_redirects=True)
            assert b'only one' in rv.data
            rv = self.app.post(
                url_for('relation_update', id_=link_id2, origin_id=actor_id),
                data={'description': 'There can be only one!', 'inverse': None},
                follow_redirects=True)
            assert b'only one' in rv.data
Ejemplo n.º 15
0
 def get_all(objects=None):
     all_ = {'point': [], 'linestring': [], 'polygon': []}
     selected = {'point': [], 'linestring': [], 'polygon': [], 'polygon_point': []}
     # Workaround to include GIS features of a subunit which would be otherwise omitted
     subunit_selected_id = 0
     if objects:
         if type(objects) is not list:
             if objects.system_type in ['feature', 'finds', 'stratigraphic unit']:
                 subunit_selected_id = objects.id
             objects = [objects]
     else:
         objects = []
     object_ids = [x.id for x in objects]
     polygon_point_sql = \
         'public.ST_AsGeoJSON(public.ST_PointOnSurface(polygon.geom)) AS polygon_point, '
     for shape in ['point', 'polygon', 'linestring']:
         sql = """
             SELECT
                 object.id AS object_id,
                 {shape}.id,
                 {shape}.name,
                 {shape}.description,
                 {shape}.type,
                 public.ST_AsGeoJSON({shape}.geom) AS geojson, {polygon_point_sql}
                 object.name AS object_name,
                 object.description AS object_desc,
                 string_agg(CAST(t.range_id AS text), ',') AS types
             FROM model.entity place
             JOIN model.link l ON place.id = l.range_id
             JOIN model.entity object ON l.domain_id = object.id
             JOIN gis.{shape} {shape} ON place.id = {shape}.entity_id
             LEFT JOIN model.link t ON object.id = t.domain_id AND t.property_code = 'P2'
             WHERE place.class_code = 'E53'
                 AND l.property_code = 'P53'
                 AND (object.system_type = 'place' OR object.id = {subunit_selected_id})
             GROUP BY object.id, {shape}.id;""".format(
             shape=shape, subunit_selected_id=subunit_selected_id,
             polygon_point_sql=polygon_point_sql if shape == 'polygon' else '')
         g.cursor.execute(sql)
         debug_model['div sql'] += 1
         place_type_root_id = NodeMapper.get_hierarchy_by_name('Place').id
         for row in g.cursor.fetchall():
             description = row.description.replace('"', '\"') if row.description else ''
             object_desc = row.object_desc.replace('"', '\"') if row.object_desc else ''
             item = {'type': 'Feature',
                     'geometry': json.loads(row.geojson),
                     'properties': {
                         'objectId': row.object_id,
                         'objectName': row.object_name.replace('"', '\"'),
                         'objectDescription': object_desc,
                         'id': row.id,
                         'name': row.name.replace('"', '\"') if row.name else '',
                         'description': description,
                         'shapeType': row.type}}
             if hasattr(row, 'types') and row.types:
                 nodes_list = ast.literal_eval('[' + row.types + ']')
                 for node_id in list(set(nodes_list)):
                     node = g.nodes[node_id]
                     if node.root and node.root[-1] == place_type_root_id:
                         item['properties']['objectType'] = node.name.replace('"', '\"')
                         break
             if row.object_id in object_ids:
                 selected[shape].append(item)
             else:
                 all_[shape].append(item)
             if hasattr(row, 'polygon_point'):
                 polygon_point_item = dict(item)  # make a copy to prevent overriding geometry
                 polygon_point_item['geometry'] = json.loads(row.polygon_point)
                 if row.object_id in object_ids:
                     selected['polygon_point'].append(polygon_point_item)
                 else:
                     all_['point'].append(polygon_point_item)
     return {'gisPointAll': json.dumps(all_['point']),
             'gisPointSelected': json.dumps(selected['point']),
             'gisLineAll': json.dumps(all_['linestring']),
             'gisLineSelected': json.dumps(selected['linestring']),
             'gisPolygonAll': json.dumps(all_['polygon']),
             'gisPolygonSelected': json.dumps(selected['polygon']),
             'gisPolygonPointSelected': json.dumps(selected['polygon_point'])}
Ejemplo n.º 16
0
    def test_place(self):
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('place_insert'))
            assert b'+ Place' in rv.data
            with app.test_request_context():
                app.preprocess_request()
                unit_node = NodeMapper.get_hierarchy_by_name(
                    'Administrative Unit')
                unit_sub1 = g.nodes[unit_node.subs[0]]
                unit_sub2 = g.nodes[unit_node.subs[1]]
                reference = EntityMapper.insert('E31', 'https://openatlas.eu',
                                                'external reference')
                place_node = NodeMapper.get_hierarchy_by_name('Place')
                source = EntityMapper.insert('E33', 'Necronomicon')
            data = {
                'name': 'Asgard',
                'alias-0': 'Valhöll',
                'geonames_id': '123',
                'geonames_precision': True,
                unit_node.id: str([unit_sub1.id, unit_sub2.id])
            }
            rv = self.app.post(url_for('place_insert', origin_id=reference.id),
                               data=data,
                               follow_redirects=True)
            assert b'Asgard' in rv.data
            data['gis_points'] = """[{
                "type":"Feature",
                "geometry":{"type":"Point","coordinates":[9,17]},
                "properties":{"name":"Valhalla","description":"","shapeType":"centerpoint"}}]"""
            data['gis_lines'] = """[{
                "type":"Feature",
                "geometry":{
                    "type":"LineString",
                    "coordinates":[[9.75307425847859,17.8111792731339],
                    [9.75315472474904,17.8110005175436],[9.75333711496205,17.8110873417098]]},
                "properties":{"name":"","description":"","shapeType":"line"}}]"""
            data['gis_polygons'] = """[{
                "type":"Feature",
                "geometry":{
                    "type":"Polygon",
                    "coordinates":[[[9.75307425847859,17.8111792731339],
                    [9.75315472474904,17.8110005175436],[9.75333711496205,17.8110873417098],
                    [9.75307425847859,17.8111792731339]]]},
                "properties":{"name":"","description":"","shapeType":"shape"}}]"""
            data[place_node.id] = place_node.subs
            data['continue_'] = 'yes'
            rv = self.app.post(url_for('place_insert', origin_id=source.id),
                               data=data,
                               follow_redirects=True)
            assert b'Necronomicon' in rv.data
            with app.test_request_context():
                app.preprocess_request()
                places = EntityMapper.get_by_system_type('place')
                place = places[0]
                place2 = places[1]
                location = place2.get_linked_entity('P53')
                actor = EntityMapper.insert('E21', 'Milla Jovovich')
                actor.link('P74', location)
            assert b'Necronomicon' in rv.data
            rv = self.app.get(url_for('place_index'))
            assert b'Asgard' in rv.data
            rv = self.app.get(url_for('place_update', id_=place.id))
            assert b'Valhalla' in rv.data
            data['continue_'] = ''
            data['alias-1'] = 'Val-hall'
            data['geonames_id'] = '321'
            rv = self.app.post(url_for('place_update', id_=place.id),
                               data=data,
                               follow_redirects=True)
            assert b'Val-hall' in rv.data

            # Test with same GeoNames id
            rv = self.app.post(url_for('place_update', id_=place.id),
                               data=data,
                               follow_redirects=True)
            assert b'Val-hall' in rv.data

            # Test with same GeoNames id but different precision
            data['geonames_precision'] = ''
            rv = self.app.post(url_for('place_update', id_=place.id),
                               data=data,
                               follow_redirects=True)
            assert b'Val-hall' in rv.data

            # Test update without the previous GeoNames id
            data['geonames_id'] = ''
            rv = self.app.post(url_for('place_update', id_=place.id),
                               data=data,
                               follow_redirects=True)
            assert b'Val-hall' in rv.data

            with app.test_request_context():
                app.preprocess_request()
                event = EntityMapper.insert('E8', 'Valhalla rising')
                event.link('P7', location)
                event.link('P24', location)
            rv = self.app.get(url_for('place_view', id_=place2.id))
            assert rv.data and b'Valhalla rising' in rv.data

            # Test invalid geom
            data['gis_polygons'] = """[{"type": "Feature", "geometry":
                {"type": "Polygon", "coordinates": [
                [[298.9893436362036, -5.888919049309554], [299.00444983737543, -5.9138487869408545],
                 [299.00650977389887, -5.893358673645309], [298.9848804404028, -5.9070188333813585],
                 [298.9893436362036, -5.888919049309554]]]},
                "properties": {"name": "", "description": "", "shapeType": "shape"}}]"""
            rv = self.app.post(url_for('place_insert', origin_id=source.id),
                               data=data,
                               follow_redirects=True)
            assert b'An invalid geometry was entered' in rv.data

            # Test Overlays
            with open(
                    os.path.dirname(__file__) +
                    '/../static/images/layout/logo.png', 'rb') as img:
                rv = self.app.post(url_for('file_insert', origin_id=place.id),
                                   data={
                                       'name': 'X-Files',
                                       'file': img
                                   },
                                   follow_redirects=True)
            assert b'An entry has been created' in rv.data
            with app.test_request_context():
                app.preprocess_request()
                file = EntityMapper.get_by_system_type('file')[0]
                link_id = LinkMapper.insert(file, 'P67', place.id)
            rv = self.app.get(
                url_for('overlay_insert',
                        image_id=file.id,
                        place_id=place.id,
                        link_id=link_id))
            assert b'X-Files' in rv.data
            data = {
                'top_left_easting': 42,
                'top_left_northing': 12,
                'bottom_right_easting': 43,
                'bottom_right_northing': 13
            }
            rv = self.app.post(url_for('overlay_insert',
                                       image_id=file.id,
                                       place_id=place.id,
                                       link_id=link_id),
                               data=data,
                               follow_redirects=True)
            assert b'Edit' in rv.data

            with app.test_request_context():
                app.preprocess_request()
                overlay = OverlayMapper.get_by_object(place)
                overlay_id = overlay[list(overlay.keys())[0]].id
            rv = self.app.get(
                url_for('overlay_update',
                        id_=overlay_id,
                        place_id=place.id,
                        link_id=link_id))
            assert b'42' in rv.data
            rv = self.app.post(url_for('overlay_update',
                                       id_=overlay_id,
                                       place_id=place.id,
                                       link_id=link_id),
                               data=data,
                               follow_redirects=True)
            assert b'Changes have been saved' in rv.data
            self.app.get(url_for('overlay_remove',
                                 id_=overlay_id,
                                 place_id=place.id),
                         follow_redirects=True)

            # Add to place
            rv = self.app.get(url_for('place_add_file', id_=place.id))
            assert b'Add File' in rv.data

            rv = self.app.post(url_for('place_add_file', id_=place.id),
                               data={'checkbox_values': str([file.id])},
                               follow_redirects=True)
            assert b'X-Files' in rv.data

            rv = self.app.get(url_for('place_add_source', id_=place.id))
            assert b'Add Source' in rv.data
            rv = self.app.post(url_for('place_add_source', id_=place.id),
                               data={'checkbox_values': str([source.id])},
                               follow_redirects=True)
            assert b'Necronomicon' in rv.data

            rv = self.app.get(url_for('place_add_reference', id_=place.id))
            assert b'Add Reference' in rv.data
            rv = self.app.post(url_for('place_add_reference', id_=place.id),
                               data={
                                   'reference': reference.id,
                                   'page': '777'
                               },
                               follow_redirects=True)
            assert b'777' in rv.data

            # Place types
            rv = self.app.get(url_for('node_move_entities', id_=unit_sub1.id))
            assert b'Asgard' in rv.data

            # Test move entities of multiple node if link to new node exists
            rv = self.app.post(url_for('node_move_entities', id_=unit_sub1.id),
                               data={
                                   unit_node.id: unit_sub2.id,
                                   'selection': location.id,
                                   'checkbox_values': str([location.id])
                               },
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data

            # Test move entities of multiple node if link to new node doesn't exists
            rv = self.app.post(url_for('node_move_entities', id_=unit_sub2.id),
                               data={
                                   unit_node.id: unit_sub1.id,
                                   'selection': location.id,
                                   'checkbox_values': str([location.id])
                               },
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data

            # Subunits
            with app.app_context():
                self.app.get(url_for('place_insert', origin_id=place.id))
                rv = self.app.post(
                    url_for('place_insert', origin_id=place.id),
                    data={'name': "It's not a bug, it's a feature!"})
                feat_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_insert', origin_id=feat_id))
                self.app.get(url_for('place_update', id_=feat_id))
                self.app.post(url_for('place_update', id_=feat_id),
                              data={'name': "It's not a bug, it's a feature!"})
                rv = self.app.post(url_for('place_insert', origin_id=feat_id),
                                   data={'name': "I'm a stratigraphic unit"})
                stratigraphic_id = rv.location.split('/')[-1]
                self.app.get(
                    url_for('place_insert', origin_id=stratigraphic_id))
                self.app.get(url_for('place_update', id_=stratigraphic_id))
                self.app.post(url_for('place_update', id_=stratigraphic_id),
                              data={'name': "I'm a stratigraphic unit"})
                dimension_node_id = NodeMapper.get_hierarchy_by_name(
                    'Dimensions').subs[0]
                data = {
                    'name': 'You never find me',
                    str(dimension_node_id): '50'
                }
                rv = self.app.post(url_for('place_insert',
                                           origin_id=stratigraphic_id),
                                   data=data)
                find_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_update', id_=find_id))
                self.app.post(url_for('place_update', id_=find_id), data=data)
            rv = self.app.get(url_for('place_view', id_=feat_id))
            assert b'not a bug' in rv.data
            rv = self.app.get(url_for('place_view', id_=stratigraphic_id))
            assert b'a stratigraphic unit' in rv.data
            rv = self.app.get(url_for('place_view', id_=find_id))
            assert b'You never' in rv.data
            rv = self.app.get(url_for('place_delete', id_=place.id),
                              follow_redirects=True)
            assert b'not possible if subunits' in rv.data
            rv = self.app.get(url_for('place_delete', id_=find_id),
                              follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
            rv = self.app.get(url_for('place_delete', id_=place2.id),
                              follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
    def test_place(self):
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('place_insert'))
            assert b'+ Place' in rv.data
            with app.test_request_context():
                app.preprocess_request()
                unit_node = NodeMapper.get_hierarchy_by_name('Administrative Unit')
                unit_sub1 = g.nodes[unit_node.subs[0]]
                unit_sub2 = g.nodes[unit_node.subs[1]]
                reference_id = EntityMapper.insert('E31', 'Ancient Books', 'edition').id
                place_node = NodeMapper.get_hierarchy_by_name('Place')
                source_id = EntityMapper.insert('E33', 'Tha source').id
            data = {'name': 'Asgard', 'alias-0': 'Valhöll',
                    unit_node.id: '[' + str(unit_sub1.id) + ',' + str(unit_sub2.id) + ']'}
            rv = self.app.post(url_for('place_insert', origin_id=reference_id), data=data,
                               follow_redirects=True)
            assert b'Asgard' in rv.data
            gis_points = """[{"type":"Feature", "geometry":{"type":"Point", "coordinates":[9,17]},
                    "properties":{"name":"Valhalla","description":"","shapeType":"centerpoint"}}]"""
            data['gis_points'] = gis_points
            data['gis_polygons'] = """[{"geometry":{
                "coordinates":[[[9.75307425847859,17.8111792731339],
                [9.75315472474904,17.8110005175436],[9.75333711496205,17.8110873417098],
                [9.75307425847859,17.8111792731339]]],"type":"Polygon"},
                "properties":{"count":4,"description":"","id":8,"name":"",
                "objectDescription":"","objectId":185,"shapeType":"Shape",
                "siteType":"Settlement","title":""},"type":"Feature"}]"""
            data[place_node.id] = place_node.subs
            data['continue_'] = 'yes'
            rv = self.app.post(
                url_for('place_insert', origin_id=source_id), data=data, follow_redirects=True)
            assert b'Tha source' in rv.data

            with app.test_request_context():
                app.preprocess_request()
                places = EntityMapper.get_by_codes('place')
                place_id = places[0].id
                place2 = places[1]
                location = place2.get_linked_entity('P53')
                actor = EntityMapper.insert('E21', 'Milla Jovovich')
                actor.link('P74', location)
            assert b'Tha source' in rv.data
            rv = self.app.get(url_for('place_index'))
            assert b'Asgard' in rv.data
            rv = self.app.get(url_for('place_update', id_=place_id))
            assert b'Valhalla' in rv.data
            data['continue_'] = ''
            data['alias-1'] = 'Val-hall'
            rv = self.app.post(
                url_for('place_update', id_=place_id), data=data, follow_redirects=True)
            assert b'Val-hall' in rv.data
            with app.test_request_context():
                app.preprocess_request()
                event = EntityMapper.insert('E8', 'Valhalla rising')
                event.link('P7', location)
                event.link('P24', location)
            rv = self.app.get(url_for('place_view', id_=place2.id))
            assert rv.data and b'Valhalla rising' in rv.data

            # Test invalid geom
            data['gis_polygons'] = """[{"type": "Feature", "geometry":
                {"type": "Polygon", "coordinates": [
                [[298.9893436362036, -5.888919049309554], [299.00444983737543, -5.9138487869408545],
                 [299.00650977389887, -5.893358673645309], [298.9848804404028, -5.9070188333813585],
                 [298.9893436362036, -5.888919049309554]]]},
                "properties": {"name": "", "description": "", "shapeType": "shape"}}]"""
            rv = self.app.post(
                url_for('place_insert', origin_id=source_id), data=data, follow_redirects=True)
            assert b'An invalid geometry was entered' in rv.data

            # Place types
            rv = self.app.get(url_for('node_move_entities', id_=unit_sub1.id))
            assert b'Asgard' in rv.data

            # Test move entities of multiple node if link to new node exists
            rv = self.app.post(url_for('node_move_entities', id_=unit_sub1.id),
                               data={unit_node.id: unit_sub2.id, 'selection': location.id},
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data

            # Test move entities of multiple node if link to new node doesn't exists
            rv = self.app.post(url_for('node_move_entities', id_=unit_sub2.id),
                               data={unit_node.id: unit_sub1.id, 'selection': location.id},
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data

            # Subunits
            with app.app_context():
                self.app.get(url_for('place_insert', origin_id=place_id))
                rv = self.app.post(url_for('place_insert', origin_id=place_id),
                                   data={'name': "It's not a bug, it's a feature!"})
                feat_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_insert', origin_id=feat_id))
                self.app.get(url_for('place_update', id_=feat_id))
                self.app.post(url_for('place_update', id_=feat_id),
                              data={'name': "It's not a bug, it's a feature!"})
                rv = self.app.post(url_for('place_insert', origin_id=feat_id),
                                   data={'name':  "I'm a stratigraphic unit"})
                stratigraphic_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_insert', origin_id=stratigraphic_id))
                self.app.get(url_for('place_update', id_=stratigraphic_id))
                self.app.post(url_for('place_update', id_=stratigraphic_id),
                              data={'name': "I'm a stratigraphic unit"})
                dimension_node_id = NodeMapper.get_hierarchy_by_name('Dimensions').subs[0]
                data = {'name': 'You never find me', str(dimension_node_id): '50'}
                rv = self.app.post(url_for('place_insert', origin_id=stratigraphic_id), data=data)
                find_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_update', id_=find_id))
                self.app.post(url_for('place_update', id_=find_id), data=data)
            rv = self.app.get(url_for('place_view', id_=feat_id))
            assert b'not a bug' in rv.data
            rv = self.app.get(url_for('place_view', id_=stratigraphic_id))
            assert b'a stratigraphic unit' in rv.data
            rv = self.app.get(url_for('place_view', id_=find_id))
            assert b'You never' in rv.data
            rv = self.app.get(url_for('place_delete', id_=place_id), follow_redirects=True)
            assert b'not possible if subunits' in rv.data
            rv = self.app.get(url_for('place_delete', id_=find_id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
            rv = self.app.get(url_for('place_delete', id_=place2.id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
    def test_actor(self):
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('actor_index'))
            assert b'No entries' in rv.data

            # Create entities for actor
            rv = self.app.post(url_for('place_insert'), data={'name': 'Nostromos'})
            residence_id = rv.location.split('/')[-1]
            with app.test_request_context():
                app.preprocess_request()
                sex_node = NodeMapper.get_hierarchy_by_name('Sex')
                sex_node_sub_1 = g.nodes[sex_node.subs[0]]
                sex_node_sub_2 = g.nodes[sex_node.subs[1]]
                event_id = EntityMapper.insert('E8', 'Event Horizon').id
                source_id = EntityMapper.insert('E33', 'Tha source').id

            # Actor insert
            rv = self.app.get(url_for('actor_insert', code='E21'))
            assert b'+ Person' in rv.data
            self.app.get(url_for('actor_insert', code='E21', origin_id=residence_id))
            data = {
                sex_node.id: sex_node_sub_1.id,
                'name': 'Sigourney Weaver',
                'alias-1': 'Ripley',
                'residence': residence_id,
                'appears_first': residence_id,
                'appears_last': residence_id,
                'description': 'Susan Alexandra Weaver is an American actress.',
                'date_begin_year': '-1949',
                'date_begin_month': '10',
                'date_begin_day': '8',
                'date_begin_year2': '-1948',
                'date_end_year': '2049',
                'date_end_year2': '2050',
                'date_birth': True,
                'date_death': True}
            rv = self.app.post(
                url_for('actor_insert', code='E21', origin_id=residence_id), data=data)
            actor_id = rv.location.split('/')[-1]

            # Test actor nodes
            rv = self.app.get(url_for('node_view', id_=sex_node_sub_1.id))
            assert b'Susan' in rv.data
            rv = self.app.get(url_for('node_move_entities', id_=sex_node_sub_1.id))
            assert b'Sigourney' in rv.data
            rv = self.app.post(url_for('node_move_entities', id_=sex_node_sub_1.id),
                               data={sex_node.id: sex_node_sub_2.id, 'selection': [actor_id]},
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data
            rv = self.app.post(url_for('node_move_entities', id_=sex_node_sub_2.id),
                               data={sex_node.id: '', 'selection': [actor_id]},
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data
            self.app.post(url_for('actor_insert', code='E21', origin_id=actor_id), data=data)
            self.app.post(url_for('actor_insert', code='E21', origin_id=event_id), data=data)
            self.app.post(url_for('actor_insert', code='E21', origin_id=source_id), data=data)
            rv = self.app.post(url_for('reference_insert', code='reference'), data={'name': 'Book'})
            reference_id = rv.location.split('/')[-1]
            rv = self.app.post(
                url_for('actor_insert', code='E21', origin_id=reference_id),
                data=data, follow_redirects=True)
            assert b'An entry has been created' in rv.data
            data['continue_'] = 'yes'
            rv = self.app.post(
                url_for('actor_insert', code='E21'), data=data, follow_redirects=True)
            assert b'An entry has been created' in rv.data
            rv = self.app.get(url_for('actor_index'))
            assert b'Sigourney Weaver' in rv.data

            # Actor update
            rv = self.app.get(url_for('actor_update', id_=actor_id))
            assert b'American actress' in rv.data
            data['name'] = 'Susan Alexandra Weaver'
            data['date_end_year'] = ''
            data['date_begin_year2'] = '1950'
            data['date_begin_day'] = ''
            rv = self.app.post(
                url_for('actor_update', id_=actor_id), data=data, follow_redirects=True)
            assert b'Susan Alexandra Weaver' in rv.data
            rv = self.app.post(
                url_for('ajax_bookmark'), data={'entity_id': actor_id}, follow_redirects=True)
            assert b'Remove bookmark' in rv.data
            rv = self.app.get('/')
            assert b'Weaver' in rv.data
            rv = self.app.post(
                url_for('ajax_bookmark'), data={'entity_id': actor_id}, follow_redirects=True)
            assert b'Bookmark' in rv.data
            rv = self.app.get(url_for('link_delete', origin_id=actor_id, id_=666),
                              follow_redirects=True)
            assert b'removed'in rv.data

            # Actor delete
            rv = self.app.get(url_for('actor_delete', id_=actor_id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
Ejemplo n.º 19
0
 def get_all(
         objects: Optional[List[Entity]] = None) -> Dict[str, List[Any]]:
     if objects is None:
         objects = []
     all_: Dict[str, List[Any]] = {
         'point': [],
         'linestring': [],
         'polygon': []
     }
     selected: Dict[str, List[Any]] = {
         'point': [],
         'linestring': [],
         'polygon': [],
         'polygon_point': []
     }
     # Workaround to include GIS features of a subunit which would be otherwise omitted
     subunit_selected_id = 0
     if objects and objects[0].system_type in [
             'feature', 'find', 'stratigraphic unit'
     ]:
         subunit_selected_id = objects[0].id
     object_ids = [x.id for x in objects]
     polygon_point_sql = \
         'public.ST_AsGeoJSON(public.ST_PointOnSurface(polygon.geom)) AS polygon_point, '
     for shape in ['point', 'polygon', 'linestring']:
         sql = """
             SELECT
                 object.id AS object_id,
                 {shape}.id,
                 {shape}.name,
                 {shape}.description,
                 {shape}.type,
                 public.ST_AsGeoJSON({shape}.geom) AS geojson, {polygon_point_sql}
                 object.name AS object_name,
                 object.description AS object_desc,
                 string_agg(CAST(t.range_id AS text), ',') AS types
             FROM model.entity place
             JOIN model.link l ON place.id = l.range_id
             JOIN model.entity object ON l.domain_id = object.id
             JOIN gis.{shape} {shape} ON place.id = {shape}.entity_id
             LEFT JOIN model.link t ON object.id = t.domain_id AND t.property_code = 'P2'
             WHERE place.class_code = 'E53'
                 AND l.property_code = 'P53'
                 AND (object.system_type = 'place' OR object.id = {subunit_selected_id})
             GROUP BY object.id, {shape}.id;""".format(
             shape=shape,
             subunit_selected_id=subunit_selected_id,
             polygon_point_sql=polygon_point_sql
             if shape == 'polygon' else '')
         g.execute(sql)
         place_type_root_id = NodeMapper.get_hierarchy_by_name('Place').id
         for row in g.cursor.fetchall():
             description = row.description.replace(
                 '"', '\"') if row.description else ''
             object_desc = row.object_desc.replace(
                 '"', '\"') if row.object_desc else ''
             item = {
                 'type': 'Feature',
                 'geometry': json.loads(row.geojson),
                 'properties': {
                     'objectId': row.object_id,
                     'objectName': row.object_name.replace('"', '\"'),
                     'objectDescription': object_desc,
                     'id': row.id,
                     'name':
                     row.name.replace('"', '\"') if row.name else '',
                     'description': description,
                     'shapeType': row.type
                 }
             }
             if hasattr(row, 'types') and row.types:
                 nodes_list = ast.literal_eval('[' + row.types + ']')
                 for node_id in list(set(nodes_list)):
                     node = g.nodes[node_id]
                     if node.root and node.root[-1] == place_type_root_id:
                         item['properties'][
                             'objectType'] = node.name.replace('"', '\"')
                         break
             if row.object_id in object_ids:
                 selected[shape].append(item)
             else:
                 all_[shape].append(item)
             if hasattr(row, 'polygon_point'):
                 polygon_point_item = dict(
                     item)  # make a copy to prevent overriding geometry
                 polygon_point_item['geometry'] = json.loads(
                     row.polygon_point)
                 if row.object_id in object_ids:
                     selected['polygon_point'].append(polygon_point_item)
                 else:
                     all_['point'].append(polygon_point_item)
     return {
         'gisPointAll':
         json.dumps(all_['point']),
         'gisPointSelected':
         json.dumps(selected['point']),
         'gisLineAll':
         json.dumps(all_['linestring']),
         'gisLineSelected':
         json.dumps(selected['linestring']),
         'gisPolygonAll':
         json.dumps(all_['polygon']),
         'gisPolygonSelected':
         json.dumps(selected['polygon']),
         'gisPolygonPointSelected':
         json.dumps(selected['polygon_point']),
         'gisAllSelected':
         json.dumps(selected['polygon'] + selected['linestring'] +
                    selected['point'])
     }
Ejemplo n.º 20
0
    def test_actor(self):
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('actor_index'))
            assert b'No entries' in rv.data

            # Create entities for actor
            rv = self.app.post(url_for('place_insert'),
                               data={'name': 'Nostromos'})
            residence_id = rv.location.split('/')[-1]
            with app.test_request_context():
                app.preprocess_request()
                sex_node = NodeMapper.get_hierarchy_by_name('Sex')
                sex_node_sub_1 = g.nodes[sex_node.subs[0]]
                sex_node_sub_2 = g.nodes[sex_node.subs[1]]
                event = EntityMapper.insert('E8', 'Event Horizon')
                source = EntityMapper.insert('E33', 'Necronomicon')
                file = EntityMapper.insert('E31', 'X-Files', 'file')

            # Actor insert
            rv = self.app.get(url_for('actor_insert', code='E21'))
            assert b'+ Person' in rv.data
            self.app.get(
                url_for('actor_insert', code='E21', origin_id=residence_id))
            data = {
                sex_node.id: sex_node_sub_1.id,
                'name': 'Sigourney Weaver',
                'alias-1': 'Ripley',
                'residence': residence_id,
                'begins_in': residence_id,
                'ends_in': residence_id,
                'description':
                'Susan Alexandra Weaver is an American actress.',
                'begin_year_from': '-1949',
                'begin_month_from': '10',
                'begin_day_from': '8',
                'begin_year_to': '-1948',
                'end_year_from': '2049',
                'end_year_to': '2050'
            }
            rv = self.app.post(url_for('actor_insert',
                                       code='E21',
                                       origin_id=residence_id),
                               data=data)
            actor_id = rv.location.split('/')[-1]

            # Test actor nodes
            rv = self.app.get(url_for('node_view', id_=sex_node_sub_1.id))
            assert b'Susan' in rv.data
            rv = self.app.get(
                url_for('node_move_entities', id_=sex_node_sub_1.id))
            assert b'Sigourney' in rv.data
            rv = self.app.post(url_for('node_move_entities',
                                       id_=sex_node_sub_1.id),
                               data={
                                   sex_node.id: sex_node_sub_2.id,
                                   'selection': [actor_id],
                                   'checkbox_values': str([actor_id])
                               },
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data
            rv = self.app.post(url_for('node_move_entities',
                                       id_=sex_node_sub_2.id),
                               data={
                                   sex_node.id: '',
                                   'selection': [actor_id],
                                   'checkbox_values': str([actor_id])
                               },
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data
            self.app.post(url_for('actor_insert',
                                  code='E21',
                                  origin_id=actor_id),
                          data=data)
            self.app.post(url_for('actor_insert',
                                  code='E21',
                                  origin_id=event.id),
                          data=data)
            self.app.post(url_for('actor_insert',
                                  code='E21',
                                  origin_id=source.id),
                          data=data)
            rv = self.app.post(url_for('reference_insert',
                                       code='external_reference'),
                               data={'name': 'https://openatlas.eu'})
            reference_id = rv.location.split('/')[-1]
            rv = self.app.post(url_for('actor_insert',
                                       code='E21',
                                       origin_id=reference_id),
                               data=data,
                               follow_redirects=True)
            assert b'An entry has been created' in rv.data
            data['continue_'] = 'yes'
            rv = self.app.post(url_for('actor_insert', code='E21'),
                               data=data,
                               follow_redirects=True)
            assert b'An entry has been created' in rv.data
            rv = self.app.get(url_for('actor_index'))
            assert b'Sigourney Weaver' in rv.data

            # Add to actor
            rv = self.app.get(url_for('actor_add_file', id_=actor_id))
            assert b'Add File' in rv.data
            rv = self.app.post(url_for('actor_add_file', id_=actor_id),
                               data={'checkbox_values': str([file.id])},
                               follow_redirects=True)
            assert b'X-Files' in rv.data

            rv = self.app.get(url_for('actor_add_source', id_=actor_id))
            assert b'Add Source' in rv.data
            rv = self.app.post(url_for('actor_add_source', id_=actor_id),
                               data={'checkbox_values': str([source.id])},
                               follow_redirects=True)
            assert b'Necronomicon' in rv.data

            rv = self.app.get(url_for('actor_add_reference', id_=actor_id))
            assert b'Add Reference' in rv.data
            rv = self.app.post(url_for('actor_add_reference', id_=actor_id),
                               data={
                                   'reference': reference_id,
                                   'page': '777'
                               },
                               follow_redirects=True)
            assert b'777' in rv.data

            # Actor update
            rv = self.app.get(url_for('actor_update', id_=actor_id))
            assert b'American actress' in rv.data
            data['name'] = 'Susan Alexandra Weaver'
            data['alias-1'] = 'Ripley1'
            data['end_year_from'] = ''
            data['begin_year_to'] = '1950'
            data['begin_day_from'] = ''
            rv = self.app.post(url_for('actor_update', id_=actor_id),
                               data=data,
                               follow_redirects=True)
            assert b'Susan Alexandra Weaver' in rv.data
            rv = self.app.post(url_for('ajax_bookmark'),
                               data={'entity_id': actor_id},
                               follow_redirects=True)
            assert b'Remove bookmark' in rv.data
            rv = self.app.get('/')
            assert b'Weaver' in rv.data
            rv = self.app.post(url_for('ajax_bookmark'),
                               data={'entity_id': actor_id},
                               follow_redirects=True)
            assert b'Bookmark' in rv.data
            rv = self.app.get(url_for('link_delete',
                                      origin_id=actor_id,
                                      id_=666),
                              follow_redirects=True)
            assert b'removed' in rv.data

            # Actor delete
            rv = self.app.get(url_for('actor_delete', id_=actor_id),
                              follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
Ejemplo n.º 21
0
    def test_relation(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_id = EntityMapper.insert('E21', 'Connor MacLeod').id
                related_id = EntityMapper.insert('E21', 'The Kurgan').id

            # Add relationship
            rv = self.app.get(url_for('relation_insert', origin_id=actor_id))
            assert b'Actor Actor Relation' in rv.data
            relation_id = NodeMapper.get_hierarchy_by_name(
                'Actor Actor Relation').id
            data = {
                'actor': '[' + str(related_id) + ']',
                relation_id: relation_id,
                'inverse': None,
                'date_begin_year': '-1949',
                'date_begin_month': '10',
                'date_begin_day': '8',
                'date_begin_year2': '-1948',
                'date_end_year': '2049',
                'date_end_year2': '2050'
            }
            rv = self.app.post(url_for('relation_insert', origin_id=actor_id),
                               data=data,
                               follow_redirects=True)
            assert b'The Kurgan' in rv.data
            data['continue_'] = 'yes'
            data['inverse'] = True
            rv = self.app.post(url_for('relation_insert', origin_id=actor_id),
                               data=data,
                               follow_redirects=True)
            assert b'The Kurgan' in rv.data
            rv = self.app.get(url_for('actor_view', id_=actor_id))
            assert b'The Kurgan' in rv.data

            rv = self.app.post(url_for('relation_insert',
                                       origin_id=related_id),
                               data=data,
                               follow_redirects=True)
            assert b"Can't link to itself." in rv.data

            # Update relationship
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(actor_id, 'OA7')[0].id
                link_id2 = LinkMapper.get_links(actor_id, 'OA7', True)[0].id
            rv = self.app.get(
                url_for('relation_update', id_=link_id, origin_id=related_id))
            assert b'Connor' in rv.data
            rv = self.app.post(url_for('relation_update',
                                       id_=link_id,
                                       origin_id=actor_id),
                               data={
                                   'description': 'There can be only one!',
                                   'inverse': True
                               },
                               follow_redirects=True)
            assert b'only one' in rv.data
            rv = self.app.post(url_for('relation_update',
                                       id_=link_id2,
                                       origin_id=actor_id),
                               data={
                                   'description': 'There can be only one!',
                                   'inverse': None
                               },
                               follow_redirects=True)
            assert b'only one' in rv.data
Ejemplo n.º 22
0
    def test_involvement(self):
        with app.app_context():
            self.login()
            rv = self.app.post(url_for('event_insert', code='E8'),
                               data={
                                   'name': 'Event Horizon',
                                   'begin_year_from': '949',
                                   'begin_month_from': '10',
                                   'begin_day_from': '8',
                                   'end_year_from': '1951'
                               })
            event_id = int(rv.location.split('/')[-1])
            with app.test_request_context():
                app.preprocess_request()
                actor = EntityMapper.insert('E21', 'Captain Miller')
                involvement = NodeMapper.get_hierarchy_by_name('Involvement')

            # Add involvement
            rv = self.app.get(url_for('involvement_insert',
                                      origin_id=actor.id))
            assert b'Involvement' in rv.data
            data = {
                'event': str([event_id]),
                'activity': 'P11',
                'begin_year_from': '950',
                'end_year_from': '1950',
                involvement.id: involvement.id
            }
            rv = self.app.post(url_for('involvement_insert',
                                       origin_id=actor.id),
                               data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            data = {
                'actor': str([actor.id]),
                'continue_': 'yes',
                'activity': 'P22'
            }
            rv = self.app.post(url_for('involvement_insert',
                                       origin_id=event_id),
                               data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            rv = self.app.get(url_for('event_view', id_=event_id))
            assert b'Event Horizon' in rv.data
            rv = self.app.get(url_for('actor_view', id_=actor.id))
            assert b'Appears first' in rv.data

            # Update involvement
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(event_id, 'P22')[0].id
            rv = self.app.get(
                url_for('involvement_update', id_=link_id, origin_id=event_id))
            assert b'Captain' in rv.data
            rv = self.app.post(url_for('involvement_update',
                                       id_=link_id,
                                       origin_id=actor.id),
                               data={
                                   'description':
                                   'Infinite Space - Infinite Terror',
                                   'activity': 'P23'
                               },
                               follow_redirects=True)
            assert b'Infinite Space - Infinite Terror' in rv.data
            rv = self.app.get(url_for('actor_view', id_=actor.id))
            assert b'Appears first' in rv.data
            rv = self.app.get(url_for('event_view', id_=event_id))
            assert b'Infinite Space - Infinite Terror' in rv.data
Ejemplo n.º 23
0
    def test_admin(self) -> None:
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('admin_mail'))
            assert b'Email from' in rv.data
            rv = self.app.get(url_for('admin_index'))
            assert b'User' in rv.data
            rv = self.app.get(url_for('admin_general'))
            assert b'Edit' in rv.data
            rv = self.app.get(url_for('admin_general_update'))
            assert b'Save' in rv.data
            rv = self.app.get(url_for('admin_map'))
            assert b'MaxClusterRadius' in rv.data
            rv = self.app.post(url_for('admin_map'),
                               follow_redirects=True,
                               data={
                                   'map_cluster_enabled': True,
                                   'map_cluster_max_radius': 2,
                                   'map_cluster_disable_at_zoom': 5
                               })
            assert b'Changes have been saved.' in rv.data

            # Check link duplicates and multi use of single nodes
            with app.test_request_context():
                app.preprocess_request()
                event = EntityMapper.insert('E8', 'Event Horizon')
                source = EntityMapper.insert('E33', 'Tha source')
                source.link('P67', event)
                source.link('P67', event)
                source_node = NodeMapper.get_hierarchy_by_name('Source')
                source.link('P2', source_node.subs[0])
                source.link('P2', source_node.subs[1])
            rv = self.app.get(url_for('admin_check_link_duplicates'))
            assert b'Event Horizon' in rv.data
            rv = self.app.get(url_for('admin_check_link_duplicates',
                                      delete='delete'),
                              follow_redirects=True)
            assert b'Remove' in rv.data
            rv = self.app.get(url_for('admin_delete_single_type_duplicate',
                                      entity_id=source.id,
                                      node_id=source_node.subs[0]),
                              follow_redirects=True)
            assert b'Congratulations, everything looks fine!' in rv.data

            # Check similar names
            with app.test_request_context():
                app.preprocess_request()
                EntityMapper.insert('E21', 'I have the same name!')
                EntityMapper.insert('E21', 'I have the same name!')
            rv = self.app.post(url_for('admin_check_similar'),
                               follow_redirects=True,
                               data={
                                   'classes': 'actor',
                                   'ratio': 100
                               })
            assert b'I have the same name!' in rv.data
            rv = self.app.post(url_for('admin_check_similar'),
                               follow_redirects=True,
                               data={
                                   'classes': 'file',
                                   'ratio': 100
                               })
            assert b'No entries' in rv.data

            data = {name: ''
                    for name in SettingsMapper.fields
                    }  # type: Dict[str, Union[str, int]]
            data['default_language'] = 'en'
            data['default_table_rows'] = '10'
            data['failed_login_forget_minutes'] = '10'
            data['failed_login_tries'] = '10'
            data['minimum_password_length'] = '10'
            data['random_password_length'] = '10'
            data['reset_confirm_hours'] = '10'
            data['log_level'] = '0'
            data['site_name'] = 'Nostromo'
            data['minimum_jstree_search'] = 3
            data['minimum_tablesorter_search'] = 4
            rv = self.app.post(url_for('admin_general_update'),
                               data=data,
                               follow_redirects=True)
            assert b'Nostromo' in rv.data
            rv = self.app.get(url_for('admin_mail_update'))
            assert b'Mail transport port' in rv.data
            data = {
                'mail': True,
                'mail_transport_username': '******',
                'mail_transport_host': 'localhost',
                'mail_transport_port': '23',
                'mail_from_email': '*****@*****.**',
                'mail_from_name': 'Max Headroom',
                'mail_recipients_feedback': '*****@*****.**'
            }
            rv = self.app.post(url_for('admin_mail_update'),
                               data=data,
                               follow_redirects=True)
            assert b'Max Headroom' in rv.data
            rv = self.app.get(url_for('admin_file'))
            assert b'jpg' in rv.data
            rv = self.app.post(url_for('admin_file'),
                               data={
                                   'file_upload_max_size': 20,
                                   'profile_image_width': 20
                               },
                               follow_redirects=True)
            assert b'Changes have been saved.' in rv.data
Ejemplo n.º 24
0
    def test_relation(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor = EntityMapper.insert('E21', 'Connor MacLeod')
                related = EntityMapper.insert('E21', 'The Kurgan')

            # Add relationship
            rv = self.app.get(url_for('relation_insert', origin_id=actor.id))
            assert b'Actor Actor Relation' in rv.data
            relation_id = NodeMapper.get_hierarchy_by_name(
                'Actor Actor Relation').id
            relation_sub_id = g.nodes[relation_id].subs[0]
            relation_sub_id2 = g.nodes[relation_id].subs[1]
            data = {
                'actor': str([related.id]),
                relation_id: relation_sub_id,
                'inverse': None,
                'begin_year_from': '-1949',
                'begin_month_from': '10',
                'begin_day_from': '8',
                'begin_year_to': '-1948',
                'end_year_from': '2049',
                'end_year_to': '2050'
            }
            rv = self.app.post(url_for('relation_insert', origin_id=actor.id),
                               data=data,
                               follow_redirects=True)
            assert b'The Kurgan' in rv.data
            rv = self.app.get(url_for('node_view', id_=relation_sub_id))
            assert b'Connor' in rv.data
            data['continue_'] = 'yes'
            data['inverse'] = True
            rv = self.app.post(url_for('relation_insert', origin_id=actor.id),
                               data=data,
                               follow_redirects=True)
            assert b'The Kurgan' in rv.data
            rv = self.app.get(url_for('actor_view', id_=actor.id))
            assert b'The Kurgan' in rv.data

            rv = self.app.post(url_for('relation_insert',
                                       origin_id=related.id),
                               data=data,
                               follow_redirects=True)
            assert b"Can't link to itself." in rv.data

            # Relation types
            rv = self.app.get(
                url_for('node_move_entities', id_=relation_sub_id))
            assert b'The Kurgan' in rv.data

            # Update relationship
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(actor.id, 'OA7')[0].id
                link_id2 = LinkMapper.get_links(actor.id, 'OA7', True)[0].id

            rv = self.app.post(url_for('node_move_entities',
                                       id_=relation_sub_id),
                               data={
                                   relation_id: relation_sub_id2,
                                   'selection': [link_id],
                                   'checkbox_values': str([link_id])
                               },
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data
            rv = self.app.post(url_for('node_move_entities',
                                       id_=relation_sub_id2),
                               data={
                                   relation_id: '',
                                   'selection': [link_id],
                                   'checkbox_values': str([link_id])
                               },
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data

            rv = self.app.get(
                url_for('relation_update', id_=link_id, origin_id=related.id))
            assert b'Connor' in rv.data
            rv = self.app.post(url_for('relation_update',
                                       id_=link_id,
                                       origin_id=actor.id),
                               data={
                                   'description': 'There can be only one!',
                                   'inverse': True
                               },
                               follow_redirects=True)
            assert b'only one' in rv.data
            rv = self.app.post(url_for('relation_update',
                                       id_=link_id2,
                                       origin_id=actor.id),
                               data={
                                   'description': 'There can be only one!',
                                   'inverse': None
                               },
                               follow_redirects=True)
            assert b'only one' in rv.data