Example #1
0
def relation_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    domain = EntityMapper.get_by_id(link_.domain.id)
    range_ = EntityMapper.get_by_id(link_.range.id)
    origin = range_ if origin_id == range_.id else domain
    related = range_ if origin_id == domain.id else domain
    form = build_form(RelationForm, 'Actor Actor Relation', link_, request)
    del form.actor, form.insert_and_continue, form.origin_id
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            if form.inverse.data:
                link_id = related.link('OA7', origin, form.description.data)
            else:
                link_id = origin.link('OA7', related, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
            flash(_('info update'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        return redirect(url_for('actor_view', id_=origin.id) + '#tab-relation')
    if origin.id == range_.id:
        form.inverse.data = True
    form.save.label.text = _('save')
    link_.set_dates()
    form.populate_dates(link_)
    return render_template('relation/update.html',
                           origin=origin,
                           form=form,
                           related=related)
def member_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    domain = EntityMapper.get_by_id(link_.domain.id)
    range_ = EntityMapper.get_by_id(link_.range.id)
    origin = range_ if origin_id == range_.id else domain
    form = build_form(MemberForm, 'Member', link_, request)
    del form.actor, form.group, form.insert_and_continue
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            link_id = domain.link('P107', range_, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        tab = '#tab-member-of' if origin.id == range_.id else '#tab-member'
        return redirect(url_for('actor_view', id_=origin.id) + tab)
    form.save.label.text = _('save')
    link_.set_dates()
    form.populate_dates(link_)
    related = range_ if origin_id == domain.id else domain
    return render_template('member/update.html', origin=origin, form=form, related=related)
def hierarchy_delete(id_):
    node = g.nodes[id_]
    if node.system or node.subs or node.count:
        abort(403)
    EntityMapper.delete(node.id)
    flash(_('entity deleted'), 'info')
    return redirect(url_for('node_index'))
def involvement_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    event = EntityMapper.get_by_id(link_.domain.id)
    actor = EntityMapper.get_by_id(link_.range.id)
    origin = event if origin_id == event.id else actor
    form = build_form(ActorForm, 'Involvement', link_, request)
    form.save.label.text = _('save')
    del form.actor, form.event, form.insert_and_continue
    form.activity.choices = [('P11', g.properties['P11'].name)]
    if event.class_.code in ['E7', 'E8', 'E12']:
        form.activity.choices.append(('P14', g.properties['P14'].name))
    if event.class_.code == 'E8':
        form.activity.choices.append(('P22', g.properties['P22'].name))
        form.activity.choices.append(('P23', g.properties['P23'].name))
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            link_id = event.link(form.activity.data, actor, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        tab = 'actor' if origin.view_name == 'event' else 'event'
        return redirect(url_for(origin.view_name + '_view', id_=origin.id) + '#tab-' + tab)
    form.activity.data = link_.property.code
    form.description.data = link_.description
    link_.set_dates()
    form.populate_dates(link_)
    return render_template('involvement/update.html', origin=origin, form=form,
                           linked_object=event if origin_id != event.id else actor)
Example #5
0
def index() -> str:
    tables = {'overview': Table(paging=False, defs='[{className: "dt-body-right", targets: 1}]'),
              'bookmarks': Table(['name', 'class', 'first', 'last'],
                                 defs='[{className: "dt-body-right", targets: [2,3]}]'),
              'notes': Table(['name', 'class', 'first', 'last', _('note')],
                             defs='[{className: "dt-body-right", targets: [2,3]}]'),
              'latest': Table(['name', 'class', 'first', 'last', 'date', 'user'],
                              order='[[4, "desc"]]',
                              defs='[{className: "dt-body-right", targets: [2,3]}]')}
    if current_user.is_authenticated and hasattr(current_user, 'bookmarks'):
        for entity_id in current_user.bookmarks:
            entity = EntityMapper.get_by_id(entity_id)
            tables['bookmarks'].rows.append([link(entity), g.classes[entity.class_.code].name,
                                             entity.first, entity.last,
                                             bookmark_toggle(entity.id, True)])
        for entity_id, text in UserMapper.get_notes().items():
            entity = EntityMapper.get_by_id(entity_id)
            tables['notes'].rows.append([link(entity), g.classes[entity.class_.code].name,
                                        entity.first, entity.last, truncate_string(text)])
        for name, count in EntityMapper.get_overview_counts().items():
            if count:
                count = format_number(count) if count else ''
                url = url_for(name + '_index') if name != 'find' else url_for('place_index')
                tables['overview'].rows.append([
                    '<a href="' + url + '">' + uc_first(_(name)) + '</a>', count])
        for entity in EntityMapper.get_latest(8):
            tables['latest'].rows.append([
                link(entity), g.classes[entity.class_.code].name,
                entity.first, entity.last, format_date(entity.created),
                link(logger.get_log_for_advanced_view(entity.id)['creator'])])
    intro = ContentMapper.get_translation('intro')
    return render_template('index/index.html', intro=intro, tables=tables)
def node_view(id_):
    from openatlas.models.linkProperty import LinkPropertyMapper
    node = g.nodes[id_]
    root = g.nodes[node.root[-1]] if node.root else None
    super_ = g.nodes[node.root[0]] if node.root else None
    header = [_('name'), _('class'), _('info')]
    if root and root.value_type:  # pragma: no cover
        header = [_('name'), _('value'), _('class'), _('info')]
    tables = {'entities': {'id': 'entities', 'header': header, 'data': []},
              'info': get_entity_data(node)}

    for entity in node.get_linked_entities(['P2', 'P89'], True):
        # If it is a place location get the corresponding object
        entity = entity if node.class_.code == 'E55' else entity.get_linked_entity('P53', True)
        if entity:  # If not entity it is a place node, so do not add
            data = [link(entity)]
            if root and root.value_type:  # pragma: no cover
                data.append(format_number(entity.nodes[node]))
            data.append(g.classes[entity.class_.code].name)
            data.append(truncate_string(entity.description))
            tables['entities']['data'].append(data)
    tables['link_entities'] = {'id': 'link_items', 'header': [_('domain'), _('range')], 'data': []}
    for row in LinkPropertyMapper.get_entities_by_node(node):
        tables['link_entities']['data'].append([link(EntityMapper.get_by_id(row.domain_id)),
                                                link(EntityMapper.get_by_id(row.range_id))])
    tables['subs'] = {'id': 'subs', 'header': [_('name'), _('count'), _('info')], 'data': []}
    for sub_id in node.subs:
        sub = g.nodes[sub_id]
        tables['subs']['data'].append([link(sub), sub.count, truncate_string(sub.description)])
    return render_template('types/view.html', node=node, super_=super_, tables=tables, root=root)
def index():
    tables = {
        'counts': {'id': 'overview', 'header': [], 'data': [], 'show_pager': False},
        'bookmarks': {'id': 'bookmarks', 'data': [], 'show_pager': False,
                      'header': ['name', 'class', 'first', 'last']},
        'latest': {'id': 'latest', 'data': [], 'show_pager': False,
                   'header': ['name', 'class', 'first', 'last', 'date', 'user']}}
    if current_user.is_authenticated and hasattr(current_user, 'bookmarks'):
        for entity_id in current_user.bookmarks:
            entity = EntityMapper.get_by_id(entity_id)
            tables['bookmarks']['data'].append([
                link(entity),
                g.classes[entity.class_.code].name,
                entity.first,
                entity.last,
                bookmark_toggle(entity.id, True)])
        for name, count in EntityMapper.get_overview_counts().items():
            count = format_number(count) if count else ''
            tables['counts']['data'].append([
                '<a href="' + url_for(name + '_index') + '">' + uc_first(_(name)) + '</a>', count])
        for entity in EntityMapper.get_latest(8):
            tables['latest']['data'].append([
                link(entity),
                g.classes[entity.class_.code].name,
                entity.first,
                entity.last,
                format_date(entity.created),
                link(logger.get_log_for_advanced_view(entity.id)['creator'])])
    intro = ContentMapper.get_translation('intro')
    return render_template('index/index.html', intro=intro, tables=tables)
Example #8
0
def hierarchy_delete(id_: int) -> str:
    node = g.nodes[id_]
    if node.system or node.subs or node.count:
        abort(403)
    EntityMapper.delete(node.id)
    flash(_('entity deleted'), 'info')
    return redirect(url_for('node_index'))
Example #9
0
def build_table_form(class_name, linked_entities):
    """ Returns a form with a list of entities with checkboxes"""
    from openatlas.models.entity import EntityMapper
    # Todo: add CSRF token
    form = '<form class="table" method="post">'
    header = app.config['TABLE_HEADERS'][class_name] + ['']
    table = {'id': class_name, 'header': header, 'data': []}
    linked_ids = [entity.id for entity in linked_entities]
    if class_name == 'file':
        entities = EntityMapper.get_by_system_type('file')
    elif class_name == 'place':
        entities = EntityMapper.get_by_system_type('place')
    else:
        entities = EntityMapper.get_by_codes(class_name)
    for entity in entities:
        if entity.id in linked_ids:
            continue  # don't show already linked entries
        input_ = '<input id="{id}" name="values" type="checkbox" value="{id}">'.format(
            id=entity.id)
        table['data'].append(get_base_table_data(entity) + [input_])
    if not table['data']:
        return uc_first(_('no entries'))
    form += pager(table)
    form += '<button name="form-submit" id="form-submit" type="submit">'
    form += uc_first(_('add')) + '</button></form>'
    return form
Example #10
0
 def __init__(self, row, domain: bool = None, range_: bool = None) -> None:
     from openatlas.models.entity import EntityMapper
     self.id = row.id
     self.description = row.description
     self.property = g.properties[row.property_code]
     self.domain = domain if domain else EntityMapper.get_by_id(
         row.domain_id)
     self.range = range_ if range_ else EntityMapper.get_by_id(row.range_id)
     self.type = g.nodes[row.type_id] if row.type_id else None
     self.nodes = dict()  # type: Dict
     if hasattr(row, 'type_id') and row.type_id:
         self.nodes[g.nodes[row.type_id]] = None
     if hasattr(row, 'begin_from'):
         self.begin_from = DateMapper.timestamp_to_datetime64(
             row.begin_from)
         self.begin_to = DateMapper.timestamp_to_datetime64(row.begin_to)
         self.begin_comment = row.begin_comment
         self.end_from = DateMapper.timestamp_to_datetime64(row.end_from)
         self.end_to = DateMapper.timestamp_to_datetime64(row.end_to)
         self.end_comment = row.end_comment
         self.first = DateForm.format_date(
             self.begin_from, 'year') if self.begin_from else None
         self.last = DateForm.format_date(self.end_from,
                                          'year') if self.end_from else None
         self.last = DateForm.format_date(
             self.end_to, 'year') if self.end_to else self.last
    def save_date(id_, form, name, code, link_mapper):
        """ Saves a date taken from a form and creates links to the entity

        :param id_: id of an entity of link
        :param form: a form with date fields
        :param name: can be a string with the values "begin" or "end"
        :param code: an OpenAtlas shortcut code e.g. 'OA5'
        :param link_mapper: whether to use LinkMapper (for entity) or LinkPropertyMapper (for link)
        :return:
        """
        from openatlas.models.entity import EntityMapper

        if not getattr(form, 'date_' + name + '_year').data:
            return  # return because no year given
        description = getattr(form, 'date_' + name + '_info').data

        date = {}  # put date form values in a dictionary
        for item in ['year', 'month', 'day', 'year2', 'month2', 'day2']:
            value = getattr(form, 'date_' + name + '_' + item).data
            date[item] = int(value) if value else ''

        if date['year2']:  # Time span
            date_from = DateMapper.form_to_datetime64(date['year'], date['month'], date['day'])
            date_from = EntityMapper.insert('E61', DateMapper.datetime64_to_timestamp(date_from),
                                            'from date value', description, date_from)
            link_mapper.insert(id_, code, date_from)
            date_to = DateMapper.form_to_datetime64(date['year2'], date['month2'], date['day2'])
            date_to = EntityMapper.insert('E61', DateMapper.datetime64_to_timestamp(date_to),
                                          system_type='to date value', date=date_to)
            link_mapper.insert(id_, code, date_to)
        else:  # Exact date
            date = DateMapper.form_to_datetime64(date['year'], date['month'], date['day'])
            exact_date = EntityMapper.insert('E61', DateMapper.datetime64_to_timestamp(date),
                                             'exact date value', description, date)
            link_mapper.insert(id_, code, exact_date)
Example #12
0
def build_move_form(form, node) -> Form:
    root = g.nodes[node.root[-1]]
    setattr(form, str(root.id), TreeField(str(root.id)))
    form_instance = form(obj=node)

    # Delete custom fields except the ones specified for the form
    delete_list = [
    ]  # Can't delete fields in the loop so creating a list for later deletion
    for field in form_instance:
        if type(field) is TreeField and int(field.id) != root.id:
            delete_list.append(field.id)
    for item in delete_list:
        delattr(form_instance, item)

    choices = []
    if root.class_.code == 'E53':
        for entity in node.get_linked_entities('P89', True):
            place = entity.get_linked_entity('P53', True)
            if place:
                choices.append((entity.id, place.name))
    elif root.name in app.config['PROPERTY_TYPES']:
        for row in LinkMapper.get_entities_by_node(node):
            domain = EntityMapper.get_by_id(row.domain_id)
            range_ = EntityMapper.get_by_id(row.range_id)
            choices.append((row.id, domain.name + ' - ' + range_.name))
    else:
        for entity in node.get_linked_entities('P2', True):
            choices.append((entity.id, entity.name))

    form_instance.selection.choices = choices
    return form_instance
Example #13
0
def member_insert(origin_id: int) -> str:
    origin = EntityMapper.get_by_id(origin_id)
    form = build_form(MemberForm, 'Member')
    del form.group
    form.origin_id.data = origin.id
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            for actor in EntityMapper.get_by_ids(
                    ast.literal_eval(form.actor.data)):
                link_ = LinkMapper.get_by_id(
                    origin.link('P107', actor, form.description.data))
                link_.set_dates(form)
                link_.type = get_link_type(form)
                link_.update()
            g.cursor.execute('COMMIT')
            flash(_('entity created'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        if form.continue_.data == 'yes':
            return redirect(url_for('member_insert', origin_id=origin_id))
        return redirect(url_for('actor_view', id_=origin.id) + '#tab-member')
    return render_template('member/insert.html', origin=origin, form=form)
Example #14
0
 def import_data(project, class_code, data):
     from openatlas.models.entity import EntityMapper
     for row in data:
         system_type = None
         if class_code == 'E33':  # pragma: no cover
             system_type = 'source content'
         elif class_code == 'E18':
             system_type = 'place'
         desc = row['description'] if 'description' in row and row['description'] else None
         entity = EntityMapper.insert(code=class_code,
                                      name=row['name'],
                                      description=desc,
                                      system_type=system_type)
         sql = """
             INSERT INTO import.entity (project_id, origin_id, entity_id, user_id)
             VALUES (%(project_id)s, %(origin_id)s, %(entity_id)s, %(user_id)s);"""
         g.cursor.execute(sql, {
             'project_id': project.id,
             'origin_id': row['id'] if 'id' in row and row['id'] else None,
             'entity_id': entity.id,
             'user_id': current_user.id})
         if class_code == 'E18':
             location = EntityMapper.insert(
                 'E53', 'Location of ' + row['name'], 'place location')
             entity.link('P53', location)
Example #15
0
def admin_check_link_duplicates(delete: Optional[str] = None) -> str:
    if delete:
        delete_count = str(LinkMapper.delete_link_duplicates())
        logger.log('info', 'admin', 'Deleted duplicate links: ' + delete_count)
        flash(_('deleted links') + ': ' + delete_count, 'info')
        return redirect(url_for('admin_check_link_duplicates'))
    table = Table(['domain', 'range', 'property_code', 'description', 'type_id', 'begin_from',
                   'begin_to', 'begin_comment', 'end_from', 'end_to', 'end_comment', 'count'])

    for result in LinkMapper.check_link_duplicates():
        table.rows.append([link(EntityMapper.get_by_id(result.domain_id)),
                           link(EntityMapper.get_by_id(result.range_id)),
                           link(g.properties[result.property_code]),
                           truncate_string(result.description),
                           link(g.nodes[result.type_id]) if result.type_id else '',
                           format_date(result.begin_from),
                           format_date(result.begin_to),
                           truncate_string(result.begin_comment),
                           format_date(result.end_from),
                           format_date(result.end_to),
                           truncate_string(result.end_comment),
                           result.count])
    duplicates = False
    if table.rows:
        duplicates = True
    else:  # If no exact duplicates where found check if single types are used multiple times
        table = Table(['entity', 'class', 'base type', 'incorrect multiple types'],
                      rows=LinkMapper.check_single_type_duplicates())
    return render_template('admin/check_link_duplicates.html', table=table, duplicates=duplicates)
def relation_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    domain = EntityMapper.get_by_id(link_.domain.id)
    range_ = EntityMapper.get_by_id(link_.range.id)
    origin = range_ if origin_id == range_.id else domain
    related = range_ if origin_id == domain.id else domain
    form = build_form(RelationForm, 'Actor Actor Relation', link_, request)
    del form.actor, form.insert_and_continue, form.origin_id
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            if form.inverse.data:
                link_id = related.link('OA7', origin, form.description.data)
            else:
                link_id = origin.link('OA7', related, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
            flash(_('info update'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        return redirect(url_for('actor_view', id_=origin.id) + '#tab-relation')
    if origin.id == range_.id:
        form.inverse.data = True
    form.save.label.text = _('save')
    link_.set_dates()
    form.populate_dates(link_)
    return render_template('relation/update.html', origin=origin, form=form, related=related)
Example #17
0
def member_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    domain = EntityMapper.get_by_id(link_.domain.id)
    range_ = EntityMapper.get_by_id(link_.range.id)
    origin = range_ if origin_id == range_.id else domain
    related = range_ if origin_id == domain.id else domain
    form = build_form(MemberForm, 'Member', link_, request)
    del form.actor, form.group, form.insert_and_continue
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            link_id = domain.link('P107', range_, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        tab = '#tab-member-of' if origin.id == range_.id else '#tab-member'
        return redirect(url_for('actor_view', id_=origin.id) + tab)
    form.save.label.text = _('save')
    link_.set_dates()
    form.populate_dates(link_)
    return render_template('member/update.html',
                           origin=origin,
                           form=form,
                           related=related)
Example #18
0
def build_move_form(form, node) -> Form:
    root = g.nodes[node.root[-1]]
    setattr(form, str(root.id), TreeField(str(root.id)))
    form_instance = form(obj=node)

    # Delete custom fields except the ones specified for the form
    delete_list = []  # Can't delete fields in the loop so creating a list for later deletion
    for field in form_instance:
        if type(field) is TreeField and int(field.id) != root.id:
            delete_list.append(field.id)
    for item in delete_list:
        delattr(form_instance, item)
    choices = []
    if root.class_.code == 'E53':
        for entity in node.get_linked_entities('P89', True):
            place = entity.get_linked_entity('P53', True)
            if place:
                choices.append((entity.id, place.name))
    elif root.name in app.config['PROPERTY_TYPES']:
        for row in LinkMapper.get_entities_by_node(node):
            domain = EntityMapper.get_by_id(row.domain_id)
            range_ = EntityMapper.get_by_id(row.range_id)
            choices.append((row.id, domain.name + ' - ' + range_.name))
    else:
        for entity in node.get_linked_entities('P2', True):
            choices.append((entity.id, entity.name))

    form_instance.selection.choices = choices
    return form_instance
Example #19
0
 def import_data(project, class_code: str, data) -> None:
     from openatlas.models.entity import EntityMapper
     for row in data:
         system_type = None
         if class_code == 'E33':  # pragma: no cover
             system_type = 'source content'
         elif class_code == 'E18':
             system_type = 'place'
         desc = row['description'] if 'description' in row and row[
             'description'] else None
         entity = EntityMapper.insert(code=class_code,
                                      name=row['name'],
                                      description=desc,
                                      system_type=system_type)
         sql = """
             INSERT INTO import.entity (project_id, origin_id, entity_id, user_id)
             VALUES (%(project_id)s, %(origin_id)s, %(entity_id)s, %(user_id)s);"""
         g.execute(
             sql, {
                 'project_id': project.id,
                 'origin_id':
                 row['id'] if 'id' in row and row['id'] else None,
                 'entity_id': entity.id,
                 'user_id': current_user.id
             })
         if class_code == 'E18':
             location = EntityMapper.insert('E53',
                                            'Location of ' + row['name'],
                                            'place location')
             entity.link('P53', location)
Example #20
0
def build_table_form(class_name: str, linked_entities: Iterator) -> str:
    """ Returns a form with a list of entities with checkboxes"""
    from openatlas.models.entity import EntityMapper
    table = Table(Table.HEADERS[class_name] + [''])
    linked_ids = [entity.id for entity in linked_entities]
    file_stats = get_file_stats() if class_name == 'file' else None
    if class_name == 'file':
        entities = EntityMapper.get_by_system_type('file', nodes=True)
    elif class_name == 'place':
        entities = EntityMapper.get_by_system_type('place',
                                                   nodes=True,
                                                   aliases=True)
    else:
        entities = EntityMapper.get_by_codes(class_name)
    for entity in entities:
        if entity.id in linked_ids:
            continue  # Don't show already linked entries
        input_ = '<input id="selection-{id}" name="values" type="checkbox" value="{id}">'.format(
            id=entity.id)
        table.rows.append(get_base_table_data(entity, file_stats) + [input_])
    if not table.rows:
        return uc_first(_('no entries'))
    return """
        <form class="table" id="checkbox-form" method="post">
            <input id="csrf_token" name="csrf_token" type="hidden" value="{token}">
            <input id="checkbox_values" name="checkbox_values" type="hidden">
            {table} <button name="form-submit" id="form-submit" type="submit">{add}</button>
        </form>""".format(add=uc_first(_('add')),
                          token=generate_csrf(),
                          table=table.display(class_name))
def build_table_form(class_name, linked_entities):
    """ Returns a form with a list of entities with checkboxes"""
    from flask_wtf.csrf import generate_csrf
    from openatlas.models.entity import EntityMapper
    header = app.config['TABLE_HEADERS'][class_name] + ['']
    table = {'id': class_name, 'header': header, 'data': []}
    linked_ids = [entity.id for entity in linked_entities]
    file_stats = get_file_stats() if class_name == 'file' else None
    if class_name == 'file':
        entities = EntityMapper.get_by_system_type('file')
    elif class_name == 'place':
        entities = EntityMapper.get_by_system_type('place')
    else:
        entities = EntityMapper.get_by_codes(class_name)
    for entity in entities:
        if entity.id in linked_ids:
            continue  # Don't show already linked entries
        input_ = '<input id="{id}" name="values" type="checkbox" value="{id}">'.format(id=entity.id)
        table['data'].append(get_base_table_data(entity, file_stats) + [input_])
    if not table['data']:
        return uc_first(_('no entries'))
    return """<form class="table" method="post">
                <input id="csrf_token" name="csrf_token" type="hidden" value="{token}">
                {pager} <button name="form-submit" id="form-submit" type="submit">{add}</button>
              </form>""".format(add=uc_first(_('add')), pager=pager(table), token=generate_csrf())
def node_delete(id_):
    node = g.nodes[id_]
    if node.system or node.subs or node.count:
        abort(403)
    EntityMapper.delete(node.id)
    flash(_('entity deleted'), 'info')
    root = g.nodes[node.root[-1]] if node.root else None
    return redirect(url_for('node_view', id_=root.id) if root else url_for('node_index'))
def reference_add(origin_id):
    """ Link an entity to reference coming from the entity."""
    origin = EntityMapper.get_by_id(origin_id)
    form = AddReferenceForm()
    if form.validate_on_submit():
        EntityMapper.get_by_id(form.reference.data).link('P67', origin, form.page.data)
        return redirect(url_for(origin.view_name + '_view', id_=origin.id) + '#tab-reference')
    return render_template('reference/add.html', origin=origin, form=form)
Example #24
0
def save(form, actor=None, code: Optional[str] = None, origin=None) -> str:
    g.cursor.execute('BEGIN')
    try:
        log_action = 'update'
        if actor:
            actor.delete_links(['P74', 'OA8', 'OA9'])
        else:
            actor = EntityMapper.insert(code, form.name.data)
            log_action = 'insert'
        actor.name = form.name.data
        actor.description = form.description.data
        actor.set_dates(form)
        actor.update()
        actor.update_aliases(form)
        actor.save_nodes(form)
        url = url_for('actor_view', id_=actor.id)
        if form.residence.data:
            object_ = EntityMapper.get_by_id(form.residence.data)
            actor.link('P74', object_.get_linked_entity('P53'))
        if form.begins_in.data:
            object_ = EntityMapper.get_by_id(form.begins_in.data)
            actor.link('OA8', object_.get_linked_entity('P53'))
        if form.ends_in.data:
            object_ = EntityMapper.get_by_id(form.ends_in.data)
            actor.link('OA9', object_.get_linked_entity('P53'))

        if origin:
            if origin.view_name == 'reference':
                link_id = origin.link('P67', actor)
                url = url_for('reference_link_update',
                              link_id=link_id,
                              origin_id=origin.id)
            elif origin.view_name == 'source':
                origin.link('P67', actor)
                url = url_for('source_view', id_=origin.id) + '#tab-actor'
            elif origin.view_name == 'event':
                link_id = origin.link('P11', actor)
                url = url_for('involvement_update',
                              id_=link_id,
                              origin_id=origin.id)
            elif origin.view_name == 'actor':
                link_id = origin.link('OA7', actor)
                url = url_for('relation_update',
                              id_=link_id,
                              origin_id=origin.id)
        if form.continue_.data == 'yes' and code:
            url = url_for('actor_insert', code=code)
        logger.log_user(actor.id, log_action)
        g.cursor.execute('COMMIT')
        flash(
            _('entity created')
            if log_action == 'insert' else _('info update'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        return redirect(url_for('actor_index'))
    return url
Example #25
0
    def test_member(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor = EntityMapper.insert('E21', 'Ripley')
                group = EntityMapper.insert('E74', 'Space Marines')

            # Add membership
            rv = self.app.get(url_for('member_insert', origin_id=group.id))
            assert b'Actor Function' in rv.data
            data = {'group': str([group.id])}
            rv = self.app.post(url_for('membership_insert',
                                       origin_id=actor.id),
                               data=data,
                               follow_redirects=True)
            assert b'Space Marines' in rv.data
            data = {'group': str([group.id]), 'continue_': 'yes'}
            rv = self.app.post(url_for('membership_insert',
                                       origin_id=actor.id),
                               data=data,
                               follow_redirects=True)
            assert b'Space Marines' in rv.data

            rv = self.app.post(url_for('membership_insert',
                                       origin_id=group.id),
                               data=data,
                               follow_redirects=True)
            assert b"Can't link to itself" in rv.data
            rv = self.app.post(url_for('member_insert', origin_id=actor.id),
                               data={'actor': str([actor.id])},
                               follow_redirects=True)
            assert b"Can't link to itself" in rv.data

            # Add member to group
            data = {'actor': str([actor.id])}
            rv = self.app.post(url_for('member_insert', origin_id=group.id),
                               data=data,
                               follow_redirects=True)
            assert b'Ripley' in rv.data
            data['continue_'] = 'yes'
            rv = self.app.post(url_for('member_insert', origin_id=group.id),
                               data=data,
                               follow_redirects=True)
            assert b'Ripley' in rv.data

            # Update
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(group.id, 'P107')[0].id
            rv = self.app.get(
                url_for('member_update', id_=link_id, origin_id=group.id))
            assert b'Ripley' in rv.data
            rv = self.app.post(
                url_for('member_update', id_=link_id, origin_id=group.id),
                data={'description': 'We are here to help you.'},
                follow_redirects=True)
            assert b'here to help' in rv.data
Example #26
0
def overlay_insert(image_id: int, place_id: int, link_id: int) -> str:
    form = OverlayForm()
    if form.validate_on_submit():
        OverlayMapper.insert(form=form, image_id=image_id, place_id=place_id, link_id=link_id)
        return redirect(url_for('place_view', id_=place_id) + '#tab-file')
    form.save.label.text = uc_first(_('insert'))
    place = EntityMapper.get_by_id(place_id)
    image = EntityMapper.get_by_id(image_id)
    return render_template('overlay/insert.html', form=form, place=place, image=image)
def source_add2(id_, class_name):
    """ Link an entity to source coming from the source"""
    source = EntityMapper.get_by_id(id_)
    if request.method == 'POST':
        for entity in EntityMapper.get_by_ids(request.form.getlist('values')):
            source.link('P67', entity)
        return redirect(url_for('source_view', id_=source.id) + '#tab-' + class_name)
    form = build_table_form(class_name, source.get_linked_entities('P67'))
    return render_template('source/add2.html', source=source, class_name=class_name, form=form)
Example #28
0
def node_delete(id_: int) -> str:
    node = g.nodes[id_]
    root = g.nodes[node.root[-1]] if node.root else None
    if node.system or node.subs or node.count or (root and root.locked):
        abort(403)
    EntityMapper.delete(node.id)
    flash(_('entity deleted'), 'info')
    return redirect(
        url_for('node_view', id_=root.id) if root else url_for('node_index'))
Example #29
0
def save(form, object_=None, location=None, origin=None):
    g.cursor.execute('BEGIN')
    try:
        log_action = 'update'
        if object_:
            for alias in object_.get_linked_entities('P1'):
                alias.delete()
            GisMapper.delete_by_entity(location)
        else:
            log_action = 'insert'
            if origin and origin.system_type == 'stratigraphic unit':
                object_ = EntityMapper.insert('E22', form.name.data, 'find')
            else:
                system_type = 'place'
                if origin and origin.system_type == 'place':
                    system_type = 'feature'
                elif origin and origin.system_type == 'feature':
                    system_type = 'stratigraphic unit'
                object_ = EntityMapper.insert('E18', form.name.data, system_type)
            location = EntityMapper.insert('E53', 'Location of ' + form.name.data, 'place location')
            object_.link('P53', location)
        object_.name = form.name.data
        object_.description = form.description.data
        object_.update()
        object_.save_dates(form)
        object_.save_nodes(form)
        location.name = 'Location of ' + form.name.data
        location.update()
        location.save_nodes(form)
        if hasattr(form, 'alias'):
            for alias in form.alias.data:
                if alias.strip():  # check if it isn't empty
                    object_.link('P1', EntityMapper.insert('E41', alias))
        url = url_for('place_view', id_=object_.id)
        if origin:
            url = url_for(get_view_name(origin) + '_view', id_=origin.id) + '#tab-place'
            if get_view_name(origin) == 'reference':
                link_id = origin.link('P67', object_)
                url = url_for('reference_link_update', link_id=link_id, origin_id=origin.id)
            elif origin.system_type in ['place', 'feature', 'stratigraphic unit']:
                url = url_for('place_view', id_=object_.id)
                origin.link('P46', object_)
            else:
                origin.link('P67', object_)
        GisMapper.insert(location, form)
        g.cursor.execute('COMMIT')
        if form.continue_.data == 'yes':
            url = url_for('place_insert', origin_id=origin.id if origin else None)
        logger.log_user(object_.id, log_action)
        flash(_('entity created') if log_action == 'insert' else _('info update'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        url = url_for('place_index')
    return url
Example #30
0
def translation_delete(id_, source_id):
    g.cursor.execute('BEGIN')
    try:
        EntityMapper.delete(id_)
        g.cursor.execute('COMMIT')
        flash(_('entity deleted'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
    return redirect(url_for('source_view', id_=source_id))
    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))
def reference_add2(reference_id, class_name):
    """ Link an entity to reference coming from the reference."""
    reference_ = EntityMapper.get_by_id(reference_id)
    form = getattr(openatlas.views.reference, 'Add' + uc_first(class_name) + 'Form')()
    if form.validate_on_submit():
        property_code = 'P128' if reference_.class_.code == 'E84' else 'P67'
        entity = EntityMapper.get_by_id(getattr(form, class_name).data)
        reference_.link(property_code, entity, form.page.data)
        return redirect(url_for('reference_view', id_=reference_.id) + '#tab-' + class_name)
    return render_template('reference/add2.html', reference=reference_, form=form,
                           class_name=class_name)
Example #33
0
 def check_links():
     """ Check all existing links for CIDOC CRM validity and return the invalid ones."""
     from openatlas.util.util import link
     from openatlas.models.entity import EntityMapper
     sql = """
         SELECT DISTINCT l.property_code AS property, d.class_code AS domain,
             r.class_code AS range
         FROM model.link l
         JOIN model.entity d ON l.domain_id = d.id
         JOIN model.entity r ON l.range_id = r.id;"""
     g.cursor.execute(sql)
     invalid_links = []
     for row in g.cursor.fetchall():
         property_ = g.properties[row.property]
         domain_is_valid = property_.find_object('domain_class_code',
                                                 row.domain)
         range_is_valid = property_.find_object('range_class_code',
                                                row.range)
         invalid_linking = []
         if not domain_is_valid or not range_is_valid:
             invalid_linking.append({
                 'property': row.property,
                 'domain': row.domain,
                 'range': row.range
             })
         for item in invalid_linking:
             sql = """
                 SELECT l.id, l.property_code, l.domain_id, l.range_id, l.description,
                     l.created, l.modified
                 FROM model.link l
                 JOIN model.entity d ON l.domain_id = d.id
                 JOIN model.entity r ON l.range_id = r.id
                 WHERE
                     l.property_code = %(property)s AND
                     d.class_code = %(domain)s AND
                     r.class_code = %(range)s;"""
             g.cursor.execute(
                 sql, {
                     'property': item['property'],
                     'domain': item['domain'],
                     'range': item['range']
                 })
             for row2 in g.cursor.fetchall():
                 domain = EntityMapper.get_by_id(row2.domain_id)
                 range_ = EntityMapper.get_by_id(row2.range_id)
                 invalid_links.append({
                     'domain':
                     link(domain) + ' (' + domain.class_.code + ')',
                     'property':
                     link(g.properties[row2.property_code]),
                     'range':
                     link(range_) + ' (' + range_.class_.code + ')'
                 })
     return invalid_links
def save(form, actor=None, code=None, origin=None):
    g.cursor.execute('BEGIN')
    try:
        log_action = 'update'
        if actor:
            actor.delete_links(['P74', 'OA8', 'OA9'])
            for alias in actor.get_linked_entities('P131'):
                alias.delete()
        else:
            actor = EntityMapper.insert(code, form.name.data)
            log_action = 'insert'
        actor.name = form.name.data
        actor.description = form.description.data
        actor.update()
        actor.save_dates(form)
        actor.save_nodes(form)
        url = url_for('actor_view', id_=actor.id)
        if form.residence.data:
            object_ = EntityMapper.get_by_id(form.residence.data)
            actor.link('P74', object_.get_linked_entity('P53'))
        if form.appears_first.data:
            object_ = EntityMapper.get_by_id(form.appears_first.data)
            actor.link('OA8', object_.get_linked_entity('P53'))
        if form.appears_last.data:
            object_ = EntityMapper.get_by_id(form.appears_last.data)
            actor.link('OA9', object_.get_linked_entity('P53'))
        for alias in form.alias.data:
            if alias.strip():  # Check if it isn't empty
                actor.link('P131', EntityMapper.insert('E82', alias))
        if origin:
            if origin.view_name == 'reference':
                link_id = origin.link('P67', actor)
                url = url_for('reference_link_update', link_id=link_id, origin_id=origin.id)
            elif origin.view_name == 'source':
                origin.link('P67', actor)
                url = url_for('source_view', id_=origin.id) + '#tab-actor'
            elif origin.view_name == 'event':
                link_id = origin.link('P11', actor)
                url = url_for('involvement_update', id_=link_id, origin_id=origin.id)
            elif origin.view_name == 'actor':
                link_id = origin.link('OA7', actor)
                url = url_for('relation_update', id_=link_id, origin_id=origin.id)
        if form.continue_.data == 'yes' and code:
            url = url_for('actor_insert', code=code)
        logger.log_user(actor.id, log_action)
        g.cursor.execute('COMMIT')
        flash(_('entity created') if log_action == 'insert' else _('info update'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        return redirect(url_for('actor_index'))
    return url
Example #35
0
def actor_delete(id_):
    g.cursor.execute('BEGIN')
    try:
        EntityMapper.delete(id_)
        logger.log_user(id_, 'delete')
        g.cursor.execute('COMMIT')
        flash(_('entity deleted'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
    return redirect(url_for('actor_index'))
Example #36
0
 def test_search(self):
     self.login()
     with app.test_request_context():
         app.preprocess_request()
         EntityMapper.insert('E21', 'Waldo')
     with app.app_context():
         rv = self.app.post(url_for('index_search'), data={'global-term': 'wal'})
         assert b'Waldo' in rv.data
         rv = self.app.post(url_for('index_search'), data={'global-term': 'wal', 'own': True})
         assert b'Waldo' not in rv.data
         data = {'term': 'do', 'classes': 'actor'}
         rv = self.app.post(url_for('index_search'), data=data)
         assert b'Waldo' in rv.data
Example #37
0
    def __call__(self, field, **kwargs):
        if field.data and type(field.data) is str:
            field.data = ast.literal_eval(field.data)
        selection = ''
        class_ = field.id if field.id != 'given_place' else 'place'
        headers_len = str(len(Table.HEADERS[class_]))

        # Make checkbox column sortable and show selected on top
        table = Table(Table.HEADERS[class_],
                      order='[[' + headers_len + ', "desc"], [0, "asc"]]')

        # Table definitions (ordering and aligning)
        defs = '{"orderDataType": "dom-checkbox", "targets":' + headers_len + '}'
        if class_ == 'event':
            defs += ',{className: "dt-body-right", targets: [3,4]}'
        elif class_ in ['actor', 'group', 'feature', 'place']:
            defs += ',{className: "dt-body-right", targets: [2,3]}'
        table.defs = '[' + defs + ']'

        if class_ == 'place':
            aliases = current_user.settings['table_show_aliases']
            entities = EntityMapper.get_by_system_type('place',
                                                       nodes=True,
                                                       aliases=aliases)
        else:
            entities = EntityMapper.get_by_codes(class_)
        for entity in entities:
            selection += entity.name + '<br/>' if field.data and entity.id in field.data else ''
            data = get_base_table_data(entity)
            data[0] = re.sub(re.compile('<a.*?>'), '', data[0])  # Remove links
            data.append(
                """<input type="checkbox" id="{id}" {checked} value="{name}"
                class="multi-table-select">""".format(
                    id=str(entity.id),
                    name=entity.name,
                    checked='checked = "checked"'
                    if field.data and entity.id in field.data else ''))
            table.rows.append(data)
        html = """
            <span id="{name}-button" class="button">{change_label}</span><br />
            <div id="{name}-selection" class="selection" style="text-align:left;">{selection}</div>
            <div id="{name}-overlay" class="overlay">
            <div id="{name}-dialog" class="overlay-container">{table}</div></div>
            <script>
                $(document).ready(function () {{createOverlay("{name}", "{title}", true);}});
            </script>""".format(name=field.id,
                                change_label=uc_first(_('change')),
                                title=_(field.id.replace('_', ' ')),
                                selection=selection,
                                table=table.display(field.id))
        return super(TableMultiSelect, self).__call__(field, **kwargs) + html
Example #38
0
def reference_add(origin_id):
    """ Link an entity to reference coming from the entity."""
    origin = EntityMapper.get_by_id(origin_id)
    view_name = get_view_name(origin)
    form = AddReferenceForm()
    if form.validate_on_submit():
        reference = EntityMapper.get_by_id(form.reference.data)
        reference.link('P67', origin.id, form.page.data)
        return redirect(
            url_for(view_name + '_view', id_=origin.id) + '#tab-reference')
    return render_template('reference/add.html',
                           origin=origin,
                           form=form,
                           class_name=view_name)
Example #39
0
def hierarchy_delete(id_):
    node = g.nodes[id_]
    if node.system or node.subs or node.count:
        abort(403)
    g.cursor.execute('BEGIN')
    try:
        EntityMapper.delete(node.id)
        g.cursor.execute('COMMIT')
        flash(_('entity deleted'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
    return redirect(url_for('node_index'))
Example #40
0
def admin_orphans() -> str:
    header = ['name', 'class', 'type', 'system type', 'created', 'updated', 'description']
    tables = {'orphans': Table(header),
              'unlinked': Table(header),
              'missing_files': Table(header),
              'circular': Table(['entity']),
              'nodes': Table(['name', 'root']),
              'orphaned_files': Table(['name', 'size', 'date', 'ext'])}
    tables['circular'].rows = [[link(entity)] for entity in EntityMapper.get_circular()]
    for entity in EntityMapper.get_orphans():
        name = 'unlinked' if entity.class_.code in app.config['CODE_CLASS'].keys() else 'orphans'
        tables[name].rows.append([link(entity),
                                  link(entity.class_),
                                  entity.print_base_type(),
                                  entity.system_type,
                                  format_date(entity.created),
                                  format_date(entity.modified),
                                  truncate_string(entity.description)])
    for node in NodeMapper.get_orphans():
        tables['nodes'].rows.append([link(node), link(g.nodes[node.root[-1]])])

    # Get orphaned file entities (no corresponding file)
    file_ids = []
    for entity in EntityMapper.get_by_system_type('file', nodes=True):
        file_ids.append(str(entity.id))
        if not get_file_path(entity):
            tables['missing_files'].rows.append([link(entity),
                                                 link(entity.class_),
                                                 entity.print_base_type(),
                                                 entity.system_type,
                                                 format_date(entity.created),
                                                 format_date(entity.modified),
                                                 truncate_string(entity.description)])

    # Get orphaned files (no corresponding entity)
    for file in os.scandir(app.config['UPLOAD_FOLDER_PATH']):
        name = file.name
        if name != '.gitignore' and splitext(file.name)[0] not in file_ids:
            confirm = ' onclick="return confirm(\'' + _('Delete %(name)s?', name=name) + '\')"'
            tables['orphaned_files'].rows.append([
                name,
                convert_size(file.stat().st_size),
                format_date(datetime.datetime.utcfromtimestamp(file.stat().st_ctime)),
                splitext(name)[1],
                '<a href="' + url_for('download_file', filename=name) + '">' + uc_first(
                    _('download')) + '</a>',
                '<a href="' + url_for('admin_file_delete', filename=name) + '" ' +
                confirm + '>' + uc_first(_('delete')) + '</a>'])
    return render_template('admin/orphans.html', tables=tables)
Example #41
0
def overlay_update(id_: int) -> str:
    overlay = OverlayMapper.get_by_id(id_)
    form = OverlayForm()
    if form.validate_on_submit():
        OverlayMapper.update(form=form, image_id=overlay.image_id, place_id=overlay.place_id)
        flash(_('info update'), 'info')
        return redirect(url_for('place_view', id_=overlay.place_id) + '#tab-file')
    bounding = ast.literal_eval(overlay.bounding_box)
    form.top_left_easting.data = bounding[0][1]
    form.top_left_northing.data = bounding[0][0]
    form.bottom_right_easting.data = bounding[1][1]
    form.bottom_right_northing.data = bounding[1][0]
    return render_template('overlay/update.html', form=form, overlay=overlay,
                           place=EntityMapper.get_by_id(overlay.place_id),
                           image=EntityMapper.get_by_id(overlay.image_id))
    def test_member(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_id = EntityMapper.insert('E21', 'Ripley').id
                group_id = EntityMapper.insert('E74', 'Space Marines').id

            # Add membership
            rv = self.app.get(url_for('member_insert', origin_id=group_id))
            assert b'Actor Function' in rv.data
            data = {'group': '[' + str(group_id) + ']'}
            rv = self.app.post(
                url_for('membership_insert', origin_id=actor_id), data=data, follow_redirects=True)
            assert b'Space Marines' in rv.data
            data = {'group': '[' + str(group_id) + ']', 'continue_': 'yes'}
            rv = self.app.post(
                url_for('membership_insert', origin_id=actor_id), data=data, follow_redirects=True)
            assert b'Space Marines' in rv.data

            rv = self.app.post(
                url_for('membership_insert', origin_id=group_id), data=data, follow_redirects=True)
            assert b"Can't link to itself" in rv.data
            rv = self.app.post(url_for('member_insert', origin_id=actor_id),
                               data={'actor': '[' + str(actor_id) + ']'}, follow_redirects=True)
            assert b"Can't link to itself" in rv.data

            # Add member to group
            data = {'actor': '[' + str(actor_id) + ']'}
            rv = self.app.post(
                url_for('member_insert', origin_id=group_id), data=data, follow_redirects=True)
            assert b'Ripley' in rv.data
            data['continue_'] = 'yes'
            rv = self.app.post(
                url_for('member_insert', origin_id=group_id), data=data, follow_redirects=True)
            assert b'Ripley' in rv.data

            # Update
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(group_id, 'P107')[0].id
            rv = self.app.get(url_for('member_update', id_=link_id, origin_id=group_id))
            assert b'Ripley' in rv.data
            rv = self.app.post(
                url_for('member_update', id_=link_id, origin_id=group_id),
                data={'description': 'We are here to help you.'},
                follow_redirects=True)
            assert b'here to help' in rv.data
Example #43
0
    def import_data(project: 'Project', class_code: str, data: List[Any]) -> None:
        from openatlas.models.entity import EntityMapper
        from openatlas.models.gis import GisMapper
        for row in data:
            system_type = None
            if class_code == 'E33':  # pragma: no cover
                system_type = 'source content'
            elif class_code == 'E18':
                system_type = 'place'
            desc = row['description'] if 'description' in row and row['description'] else None
            entity = EntityMapper.insert(code=class_code, name=row['name'], description=desc,
                                         system_type=system_type)
            sql = """
                INSERT INTO import.entity (project_id, origin_id, entity_id, user_id)
                VALUES (%(project_id)s, %(origin_id)s, %(entity_id)s, %(user_id)s);"""
            g.execute(sql, {'project_id': project.id,
                            'entity_id': entity.id,
                            'user_id': current_user.id,
                            'origin_id': row['id'] if 'id' in row and row['id'] else None})

            # Dates
            if 'begin_from' in row and row['begin_from']:
                entity.begin_from = row['begin_from']
                if 'begin_to' in row and row['begin_to']:
                    entity.begin_to = row['begin_to']
                if 'begin_comment' in row and row['begin_comment']:
                    entity.begin_comment = row['begin_comment']

            if 'end_from' in row and row['end_from']:
                entity.end_from = row['end_from']
                if 'end_to' in row and row['end_to']:
                    entity.end_to = row['end_to']
                if 'end_comment' in row and row['end_comment']:
                    entity.end_comment = row['end_comment']
            entity.update()

            # GIS
            if class_code == 'E18':
                location = EntityMapper.insert('E53', 'Location of ' + row['name'],
                                               'place location')
                entity.link('P53', location)
                if 'easting' in row and is_float(row['easting']):
                    if 'northing' in row and is_float(row['northing']):
                        GisMapper.insert_import(entity=entity,
                                                location=location,
                                                project=project,
                                                easting=row['easting'],
                                                northing=row['northing'])
 def test_source(self):
     with app.app_context():
         self.login()
         with app.test_request_context():
             app.preprocess_request()
             source_id = EntityMapper.insert('E33', 'Necronomicon', 'source content').id
         rv = self.app.get(url_for('translation_insert', source_id=source_id))
         assert b'+ Text' in rv.data
         data = {'name': 'Test translation'}
         rv = self.app.post(url_for('translation_insert', source_id=source_id), data=data)
         with app.test_request_context():
             app.preprocess_request()
             translation_id = rv.location.split('/')[-1]
         rv = self.app.get(url_for('source_view', id_=source_id))
         assert b'Test translation' in rv.data
         self.app.get(url_for('translation_update', id_=translation_id, source_id=source_id))
         rv = self.app.post(
             url_for('translation_update', id_=translation_id, source_id=source_id),
             data={'name': 'Translation updated'},
             follow_redirects=True)
         assert b'Translation updated' in rv.data
         rv = self.app.get(
             url_for('translation_delete', id_=translation_id, source_id=source_id),
             follow_redirects=True)
         assert b'The entry has been deleted.' in rv.data
         data = {'name': 'Translation continued', 'continue_': 'yes'}
         self.app.post(url_for('translation_insert', source_id=source_id), data=data)
def save(form, reference=None, code=None, origin=None):
    g.cursor.execute('BEGIN')
    log_action = 'update'
    try:
        if not reference:
            log_action = 'insert'
            class_code = 'E84' if code == 'carrier' else 'E31'
            system_type = 'information carrier' if code == 'carrier' else code
            reference = EntityMapper.insert(class_code, form.name.data, system_type)
        reference.name = form.name.data
        reference.description = form.description.data
        reference.update()
        reference.save_nodes(form)
        url = url_for('reference_view', id_=reference.id)
        if origin:
            link_id = reference.link('P67', origin)
            url = url_for('reference_link_update', link_id=link_id, origin_id=origin.id)
        if form.continue_.data == 'yes' and code:
            url = url_for('reference_insert', code=code)
        g.cursor.execute('COMMIT')
        logger.log_user(reference.id, log_action)
        flash(_('entity created') if log_action == 'insert' else _('info update'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        url = url_for('reference_index')
    return url
def save(form, source=None, origin=None):
    g.cursor.execute('BEGIN')
    log_action = 'update'
    try:
        if not source:
            source = EntityMapper.insert('E33', form.name.data, 'source content')
            log_action = 'insert'
        source.name = form.name.data
        source.description = form.description.data
        source.update()
        source.save_nodes(form)
        url = url_for('source_view', id_=source.id)
        if origin:
            url = url_for(origin.view_name + '_view', id_=origin.id) + '#tab-source'
            if origin.view_name == 'reference':
                link_ = origin.link('P67', source)
                url = url_for('reference_link_update', link_id=link_, origin_id=origin)
            elif origin.view_name == 'file':
                origin.link('P67', source)
            else:
                source.link('P67', origin)
        g.cursor.execute('COMMIT')
        if form.continue_.data == 'yes':
            url = url_for('source_insert', origin_id=origin.id if origin else None)
        logger.log_user(source.id, log_action)
        flash(_('entity created') if log_action == 'insert' else _('info update'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        url = url_for('source_insert', origin_id=origin.id if origin else None)
    return url
def source_add(origin_id):
    """ Link an entity to source coming from the entity."""
    origin = EntityMapper.get_by_id(origin_id)
    if request.method == 'POST':
        g.cursor.execute('BEGIN')
        try:
            for entity in EntityMapper.get_by_ids(request.form.getlist('values')):
                entity.link('P67', origin)
            g.cursor.execute('COMMIT')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        return redirect(url_for(origin.view_name + '_view', id_=origin.id) + '#tab-source')
    form = build_table_form('source', origin.get_linked_entities('P67', True))
    return render_template('source/add.html', origin=origin, form=form)
Example #48
0
 def check_single_type_duplicates() -> list:
     # Find entities with multiple types attached which should be single
     from openatlas.models.node import NodeMapper
     from openatlas.models.entity import EntityMapper
     data = []
     for id_, node in g.nodes.items():
         if not node.root and not node.multiple and not node.value_type:
             node_ids = NodeMapper.get_all_sub_ids(node)
             if node_ids:
                 sql = """
                     SELECT domain_id FROM model.link
                     WHERE property_code = 'P2' AND range_id IN %(node_ids)s
                     GROUP BY domain_id HAVING COUNT(*) > 1;"""
                 g.cursor.execute(sql, {'node_ids': tuple(node_ids)})
                 debug_model['link sql'] += 1
                 for row in g.cursor.fetchall():
                     offending_nodes = []
                     entity = EntityMapper.get_by_id(row.domain_id, nodes=True)
                     for entity_node in entity.nodes:
                         if g.nodes[entity_node.root[-1]].id == node.id:
                             url = url_for('admin_delete_single_type_duplicate',
                                           entity_id=entity.id, node_id=entity_node.id)
                             offending_nodes.append(
                                 '<a href="' + url + '">' + uc_first(_('remove')) + '</a> ' +
                                 entity_node.name)
                     data.append([link(entity), entity.class_.name,
                                  link(g.nodes[id_]), '<br />'.join(offending_nodes)])
     return data
    def move_entities(old_node, new_type_id, entity_ids):
        root = g.nodes[old_node.root[-1]]
        delete_ids = []
        if new_type_id:  # A new type was selected
            if root.multiple:
                cleaned_entity_ids = []
                for entity in EntityMapper.get_by_ids(entity_ids):
                    if any(node.id == int(new_type_id) for node in entity.nodes):
                        delete_ids.append(entity.id)  # If already linked add to delete ids
                    else:
                        cleaned_entity_ids.append(entity.id)
                entity_ids = cleaned_entity_ids
            if entity_ids:
                sql = """
                    UPDATE model.{table} SET range_id = %(new_type_id)s
                    WHERE range_id = %(old_type_id)s AND domain_id IN %(entity_ids)s;""".format(
                    table='link_property' if root.name in app.config['PROPERTY_TYPES'] else 'link')
                params = {
                    'old_type_id': old_node.id,
                    'new_type_id': new_type_id,
                    'entity_ids': tuple(entity_ids)}
                g.cursor.execute(sql, params)
                debug_model['div sql'] += 1
        else:
            delete_ids = entity_ids  # No new type was selected so delete all links

        if delete_ids:
            sql = """
                DELETE FROM model.{table}
                WHERE range_id = %(old_type_id)s AND domain_id IN %(delete_ids)s;""".format(
                table='link_property' if root.name in app.config['PROPERTY_TYPES'] else 'link')
            g.cursor.execute(sql, {'old_type_id': old_node.id, 'delete_ids': tuple(delete_ids)})
            debug_model['div sql'] += 1
Example #50
0
 def get_links(entity, codes, inverse=False):
     from openatlas.models.entity import EntityMapper
     sql = """
         SELECT l.id, l.property_code, l.domain_id, l.range_id, l.description, l.created,
             l.modified, e.name, l.type_id,
             COALESCE(to_char(l.begin_from, 'yyyy-mm-dd BC'), '') AS begin_from, l.begin_comment,
             COALESCE(to_char(l.begin_to, 'yyyy-mm-dd BC'), '') AS begin_to,
             COALESCE(to_char(l.end_from, 'yyyy-mm-dd BC'), '') AS end_from, l.end_comment,
             COALESCE(to_char(l.end_to, 'yyyy-mm-dd BC'), '') AS end_to
         FROM model.link l
         JOIN model.entity e ON l.{second}_id = e.id AND l.property_code IN %(codes)s
         WHERE l.{first}_id = %(entity_id)s GROUP BY l.id, e.name ORDER BY e.name;""".format(
         first='range' if inverse else 'domain', second='domain' if inverse else 'range')
     g.cursor.execute(sql, {
         'entity_id': entity if type(entity) is int else entity.id,
         'codes': tuple(codes if type(codes) is list else [codes])})
     debug_model['link sql'] += 1
     entity_ids = set()
     result = g.cursor.fetchall()
     for row in result:
         entity_ids.add(row.domain_id)
         entity_ids.add(row.range_id)
     entities = {entity.id: entity for entity in EntityMapper.get_by_ids(entity_ids)}
     links = []
     for row in result:
         links.append(Link(row, domain=entities[row.domain_id], range_=entities[row.range_id]))
     return links
    def get_invalid_dates():
        """ Search for entities with invalid date combinations, e.g. begin after end"""
        from openatlas.models.entity import EntityMapper
        sql = """
        SELECT e.id FROM model.entity e

        LEFT JOIN model.link bl1 ON e.id = bl1.domain_id
            AND bl1.property_code IN ('OA1', 'OA3', 'OA5')
        LEFT JOIN model.entity b1 ON bl1.range_id = b1.id
            AND b1.system_type IN ('from date value', 'exact date value')

        LEFT JOIN model.link bl2 ON e.id = bl2.domain_id
            AND bl2.property_code IN ('OA1', 'OA3', 'OA5')
        LEFT JOIN model.entity b2 ON bl2.range_id = b2.id AND b2.system_type = 'to date value'

        LEFT JOIN model.link el1 ON e.id = el1.domain_id
            AND el1.property_code IN ('OA2', 'OA4', 'OA6')
        LEFT JOIN model.entity e1 ON el1.range_id = e1.id
            AND e1.system_type IN ('from date value', 'exact date value')

        LEFT JOIN model.link el2 ON e.id = el2.domain_id
            AND el2.property_code IN ('OA2', 'OA4', 'OA6')
        LEFT JOIN model.entity e2 ON el2.range_id = e2.id AND e2.system_type = 'to date value'

        GROUP BY e.id
        HAVING e.class_code IN ('E6', 'E7', 'E8', 'E12', 'E18', 'E21', 'E22', 'E40', 'E74')
            AND (max(b1.value_timestamp) > max(b2.value_timestamp)
                OR max(e1.value_timestamp) > max(e2.value_timestamp)
                OR (max(b1.value_timestamp) IS NOT NULL AND max(e1.value_timestamp) IS NOT NULL
                    AND max(b1.value_timestamp) > max(e1.value_timestamp))
                OR (max(b2.value_timestamp) IS NOT NULL AND max(e2.value_timestamp) IS NOT NULL
                    AND max(b2.value_timestamp) > max(e2.value_timestamp)));"""
        g.cursor.execute(sql)
        debug_model['div sql'] += 1
        return [EntityMapper.get_by_id(row.id)for row in g.cursor.fetchall()]
Example #52
0
def relation_insert(origin_id):
    origin = EntityMapper.get_by_id(origin_id)
    form = build_form(RelationForm, 'Actor Actor Relation')
    form.origin_id.data = origin.id
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            for actor_id in ast.literal_eval(form.actor.data):
                if form.inverse.data:
                    link_id = LinkMapper.insert(actor_id, 'OA7', origin.id,
                                                form.description.data)
                else:
                    link_id = origin.link('OA7', actor_id,
                                          form.description.data)
                DateMapper.save_link_dates(link_id, form)
                NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
            flash(_('entity created'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        if form.continue_.data == 'yes':
            return redirect(url_for('relation_insert', origin_id=origin_id))
        return redirect(url_for('actor_view', id_=origin.id) + '#tab-relation')
    return render_template('relation/insert.html', origin=origin, form=form)
def reference_view(id_):
    reference = EntityMapper.get_by_id(id_)
    tables = {
        'info': get_entity_data(reference),
        'file': {'id': 'files', 'data': [],
                 'header': app.config['TABLE_HEADERS']['file'] + ['page'] + [_('main image')]}}
    for name in ['source', 'event', 'actor', 'place', 'feature', 'stratigraphic-unit', 'find']:
        header = app.config['TABLE_HEADERS'][name] + ['page']
        tables[name] = {'id': name, 'header': header, 'data': []}
    for link_ in reference.get_links('P67', True):
        domain = link_.domain
        data = get_base_table_data(domain)
        if is_authorized('editor'):
            url = url_for('link_delete', id_=link_.id, origin_id=reference.id) + '#tab-file'
            data.append(display_remove_link(url, domain.name))
        tables['file']['data'].append(data)
    profile_image_id = reference.get_profile_image_id()
    for link_ in reference.get_links(['P67', 'P128']):
        range_ = link_.range
        data = get_base_table_data(range_)
        data.append(truncate_string(link_.description))
        if range_.view_name == 'file':  # pragma: no cover
            ext = data[3].replace('.', '')
            data.append(get_profile_image_table_link(range_, reference, ext, profile_image_id))
            if not profile_image_id and ext in app.config['DISPLAY_FILE_EXTENSIONS']:
                profile_image_id = range_.id
        if is_authorized('editor'):
            url = url_for('reference_link_update', link_id=link_.id, origin_id=reference.id)
            data.append('<a href="' + url + '">' + uc_first(_('edit')) + '</a>')
            url = url_for('link_delete', id_=link_.id, origin_id=reference.id)
            data.append(display_remove_link(url + '#tab-' + range_.table_name, range_.name))
        tables[range_.table_name]['data'].append(data)
    return render_template('reference/view.html', reference=reference, tables=tables,
                           profile_image_id=profile_image_id)
Example #54
0
def object_view(id_: int) -> str:
    object_ = EntityMapper.get_by_id(id_, nodes=True)
    object_.note = UserMapper.get_note(object_)
    tables = {
        'info': get_entity_data(object_),
        'source': Table(Table.HEADERS['source']),
        'event': Table(Table.HEADERS['event'])
    }
    for link_ in object_.get_links('P128'):
        data = get_base_table_data(link_.range)
        if is_authorized('contributor'):
            url = url_for('link_delete', id_=link_.id, origin_id=object_.id)
            data.append(
                display_remove_link(url + '#tab-' + link_.range.table_name,
                                    link_.range.name))
        tables['source'].rows.append(data)
    for link_ in object_.get_links('P25', inverse=True):
        data = get_base_table_data(link_.domain)
        if is_authorized('contributor'):
            url = url_for('link_delete', id_=link_.id, origin_id=object_.id)
            data.append(
                display_remove_link(url + '#tab-' + link_.range.table_name,
                                    link_.range.name))
        tables['event'].rows.append(data)
    return render_template('object/view.html', object_=object_, tables=tables)
Example #55
0
def object_index() -> str:
    table = Table(Table.HEADERS['object'] + ['description'])
    for object_ in EntityMapper.get_by_codes('object'):
        data = get_base_table_data(object_)
        data.append(truncate_string(object_.description))
        table.rows.append(data)
    return render_template('object/index.html', table=table)
def save(form, event=None, code=None, origin=None):
    g.cursor.execute('BEGIN')
    try:
        log_action = 'insert'
        if event:
            log_action = 'update'
            event.delete_links(['P117', 'P7', 'P24'])
        else:
            event = EntityMapper.insert(code, form.name.data)
        event.name = form.name.data
        event.description = form.description.data
        event.update()
        event.save_dates(form)
        event.save_nodes(form)
        if form.event.data:
            entity = EntityMapper.get_by_id(form.event.data)
            event.link('P117', entity)
        if form.place.data:
            place = LinkMapper.get_linked_entity(int(form.place.data), 'P53')
            event.link('P7', place)
        if event.class_.code == 'E8' and form.given_place.data:  # Link place for acquisition
            places = [EntityMapper.get_by_id(i) for i in ast.literal_eval(form.given_place.data)]
            event.link('P24', places)
        url = url_for('event_view', id_=event.id)
        if origin:
            url = url_for(origin.view_name + '_view', id_=origin.id) + '#tab-event'
            if origin.view_name == 'reference':
                link_id = origin.link('P67', event)
                url = url_for('reference_link_update', link_id=link_id, origin_id=origin.id)
            elif origin.view_name == 'source':
                origin.link('P67', event)
            elif origin.view_name == 'actor':
                link_id = event.link('P11', origin)
                url = url_for('involvement_update', id_=link_id, origin_id=origin.id)
            elif origin.view_name == 'file':
                origin.link('P67', event)
        if form.continue_.data == 'yes':
            url = url_for('event_insert', code=code, origin_id=origin.id if origin else None)
        g.cursor.execute('COMMIT')
        logger.log_user(event.id, log_action)
        flash(_('entity created') if log_action == 'insert' else _('info update'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        url = url_for('event_index')
    return url
def actor_index():
    header = app.config['TABLE_HEADERS']['actor'] + ['description']
    table = {'id': 'actor', 'header': header, 'data': []}
    for actor in EntityMapper.get_by_codes('actor'):
        data = get_base_table_data(actor)
        data.append(truncate_string(actor.description))
        table['data'].append(data)
    return render_template('actor/index.html', table=table)
 def test_content_and_newsletter(self):
     with app.app_context():
         self.login()
         self.app.post(url_for('actor_insert', code='E21'), data={'name': 'Oliver Twist'})
         with app.test_request_context():
             app.preprocess_request()
             EntityMapper.insert('E61', '2017-04-01')  # Add orphaned date
             EntityMapper.insert('E31', 'One forsaken file entity', 'file')  # Add orphaned file
         rv = self.app.get(url_for('admin_orphans'))
         assert all(x in rv.data for x in [b'Oliver Twist', b'2017-04-01', b'forsaken'])
         rv = self.app.get(url_for('admin_orphans_delete', parameter='orphans'))
         assert b'2017-04-01' not in rv.data
         self.app.get(url_for('admin_orphans_delete', parameter='unlinked'))
         self.app.get(url_for('admin_orphans_delete', parameter='types'))
         self.app.get(url_for('admin_orphans_delete', parameter='whatever bogus string'))
         rv = self.app.get(url_for('admin_newsletter'))
         assert b'Newsletter' in rv.data
def source_insert(origin_id=None):
    origin = EntityMapper.get_by_id(origin_id) if origin_id else None
    form = build_form(SourceForm, 'Source')
    if origin:
        del form.insert_and_continue
    if form.validate_on_submit():
        return redirect(save(form, origin=origin))
    return render_template('source/insert.html', form=form, origin=origin)
def reference_insert(code, origin_id=None):
    origin = EntityMapper.get_by_id(origin_id) if origin_id else None
    form = build_form(ReferenceForm, uc_first('Information Carrier' if code == 'carrier' else code))
    if origin:
        del form.insert_and_continue
    if form.validate_on_submit():
        return redirect(save(form, code=code, origin=origin))
    return render_template('reference/insert.html', form=form, code=code, origin=origin)