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)
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)
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'))
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
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)
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
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)
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)
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)
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)
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
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)
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)
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
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
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)
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'))
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
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)
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
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'))
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
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
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)
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'))
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)
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
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)
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
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()]
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)
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)
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)