def check_single_type_duplicates() -> List[List[str]]: from openatlas.models.node import Node from openatlas.models.entity import Entity data = [] for node in g.nodes.values(): if node.root or node.multiple or node.value_type: continue # pragma: no cover node_ids = Node.get_all_sub_ids(node) if not node_ids: continue # pragma: no cover for id_ in Db.check_single_type_duplicates(node_ids): offending_nodes = [] entity = Entity.get_by_id(id_, nodes=True) for entity_node in entity.nodes: if g.nodes[entity_node.root[-1]].id != node.id: continue # pragma: no cover offending_nodes.append( '<a href="{url}">{label}</a> {name}'.format( label=uc_first(_('remove')), name=entity_node.name, url=url_for('admin_delete_single_type_duplicate', entity_id=entity.id, node_id=entity_node.id))) data.append([ link(entity), entity.class_.name, link(g.nodes[node.id]), '<br><br><br><br><br>'.join(offending_nodes) ]) return data
def user_activity(user_id: int = 0) -> str: form = ActivityForm() form.user.choices = [(0, _('all'))] + User.get_users_for_form() if form.validate_on_submit(): activities = User.get_activities( int(form.limit.data), int(form.user.data), form.action.data) elif user_id: form.user.data = user_id activities = User.get_activities(100, user_id, 'all') else: activities = User.get_activities(100, 0, 'all') table = Table(['date', 'user', 'action', 'entity'], order=[[0, 'desc']]) for row in activities: try: entity = link(Entity.get_by_id(row['entity_id'])) except AttributeError: # pragma: no cover - entity already deleted entity = 'id ' + str(row['entity_id']) user = User.get_by_id(row['user_id']) user = link(user) if user else 'id ' + str(row['user_id']) table.rows.append([format_date(row['created']), user, _(row['action']), entity]) return render_template( 'user/activity.html', table=table, form=form, title=_('user'), crumbs=[[_('admin'), url_for('admin_index')], _('activity')])
def add_crumbs(view_name: str, class_: str, origin: Union[Entity, None], structure: Optional[Dict[str, Any]], insert_: Optional[bool] = False) -> List[Any]: label = origin.class_.name if origin else view_name if label in g.class_view_mapping: label = g.class_view_mapping[label] label = _(label.replace('_', ' ')) crumbs = [[ label, url_for('index', view=origin.class_.view if origin else view_name) ], link(origin)] if structure and (not origin or not origin.class_.name == 'artifact'): crumbs = [[_('place'), url_for('index', view='place')], structure['place'] if origin and origin.class_.name != 'place' else '', structure['feature'], structure['stratigraphic_unit'], link(origin)] if view_name == 'type': crumbs = [[_('types'), url_for('node_index')]] if isinstance(origin, Node) and origin.root: for node_id in reversed(origin.root): crumbs += [link(g.nodes[node_id])] crumbs += [origin] return crumbs + (['+ ' + g.classes[class_].label] if insert_ else [_('edit')])
def check_links() -> List[Dict[str, str]]: """ Check all existing links for CIDOC CRM validity and return the invalid ones.""" from openatlas.util.display import link from openatlas.models.entity import Entity invalid_links = [] for row in Db.get_cidoc_links(): 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(row) for item in invalid_linking: for row2 in Db.get_invalid_links(item): domain = Entity.get_by_id(row2['domain_id']) range_ = Entity.get_by_id(row2['range_id']) invalid_links.append({ 'domain': link(domain) + ' (' + domain.cidoc_class.code + ')', 'property': link(g.properties[row2['property_code']]), 'range': link(range_) + ' (' + range_.cidoc_class.code + ')' }) return invalid_links
def property_index() -> str: classes = g.cidoc_classes properties = g.properties table = Table([ 'code', 'name', 'inverse', 'domain', 'domain name', 'range', 'range name', 'count' ], defs=[{ 'className': 'dt-body-right', 'targets': 7 }, { 'orderDataType': 'cidoc-model', 'targets': [0, 3, 5] }, { 'sType': 'numeric', 'targets': [0] }]) for property_id, property_ in properties.items(): table.rows.append([ link(property_), property_.name, property_.name_inverse, link(classes[property_.domain_class_code]), classes[property_.domain_class_code].name, link(classes[property_.range_class_code]), classes[property_.range_class_code].name, format_number(property_.count) if property_.count else '' ]) return render_template('table.html', table=table, title=_('model'), crumbs=[[_('model'), url_for('model_index')], _('properties')])
def get_table(view: str) -> Table: table = Table(g.table_headers[view]) if view == 'file': table.header = ['date'] + table.header file_stats = get_file_stats() for entity in Entity.get_by_class('file', nodes=True): date = 'N/A' if entity.id in file_stats: date = format_date( datetime.datetime.utcfromtimestamp( file_stats[entity.id]['date'])) table.rows.append([ date, link(entity), entity.print_standard_type(), convert_size(file_stats[entity.id]['size']) if entity.id in file_stats else 'N/A', file_stats[entity.id]['ext'] if entity.id in file_stats else 'N/A', entity.description ]) elif view == 'reference_system': for system in g.reference_systems.values(): table.rows.append([ link(system), system.count if system.count else '', external_url(system.website_url), external_url(system.resolver_url), system.placeholder, link(g.nodes[system.precision_default_id]) if system.precision_default_id else '', system.description ]) else: classes = ['place'] if view == 'place' else g.view_class_mapping[view] entities = Entity.get_by_class(classes, nodes=True) table.rows = [get_base_table_data(item) for item in entities] return table
def property_view(code: str) -> str: property_ = g.properties[code] domain = g.cidoc_classes[property_.domain_class_code] range_ = g.cidoc_classes[property_.range_class_code] info = { 'code': property_.code, 'name': property_.name, 'inverse': property_.name_inverse, 'domain': link(domain) + ' ' + domain.name, 'range': link(range_) + ' ' + range_.name } tables = {} for table in ['super', 'sub']: tables[table] = Table(paging=False, defs=[{ 'orderDataType': 'cidoc-model', 'targets': [0] }, { 'sType': 'numeric', 'targets': [0] }]) for code in getattr(property_, table): tables[table].rows.append( [link(g.properties[code]), g.properties[code].name]) return render_template( 'model/property_view.html', tables=tables, property_=property_, info=info, title=_('model'), crumbs=[[_('model'), url_for('model_index')], [_('properties'), url_for('property_index')], property_.code])
def class_index() -> str: table = Table(['code', 'name', 'count'], defs=[{ 'className': 'dt-body-right', 'targets': 2 }, { 'orderDataType': 'cidoc-model', 'targets': [0] }, { 'sType': 'numeric', 'targets': [0] }]) for class_id, class_ in g.cidoc_classes.items(): count = '' if class_.count: count = format_number(class_.count) if class_.code not in ['E53', 'E41', 'E82']: count = link(format_number(class_.count), url_for('class_entities', code=class_.code)) table.rows.append([link(class_), class_.name, count]) return render_template('table.html', table=table, title=_('model'), crumbs=[[_('model'), url_for('model_index')], _('classes')])
def class_entities(code: str) -> str: table = Table(['name'], rows=[[link(entity)] for entity in Entity.get_by_cidoc_class(code)]) return render_template('table.html', table=table, title=_('model'), crumbs=[[_('model'), url_for('model_index')], [_('classes'), url_for('class_index')], link(g.cidoc_classes[code]), _('entities')])
def show_untyped_entities(id_: int) -> str: hierarchy = g.nodes[id_] table = Table(['name', 'class', 'first', 'last', 'description']) for entity in Node.get_untyped(hierarchy.id): table.rows.append([ link(entity), entity.class_.label, entity.first, entity.last, entity.description]) return render_template( 'table.html', entity=hierarchy, table=table, crumbs=[[_('types'), url_for('node_index')], link(hierarchy), _('untyped entities')])
def class_view(code: str) -> str: class_ = g.cidoc_classes[code] tables = {} for table in ['super', 'sub']: tables[table] = Table(paging=False, defs=[{ 'orderDataType': 'cidoc-model', 'targets': [0] }, { 'sType': 'numeric', 'targets': [0] }]) for code_ in getattr(class_, table): tables[table].rows.append( [link(g.cidoc_classes[code_]), g.cidoc_classes[code_].name]) tables['domains'] = Table(paging=False, defs=[{ 'orderDataType': 'cidoc-model', 'targets': [0] }, { 'sType': 'numeric', 'targets': [0] }]) tables['ranges'] = Table(paging=False, defs=[{ 'orderDataType': 'cidoc-model', 'targets': [0] }, { 'sType': 'numeric', 'targets': [0] }]) for key, property_ in g.properties.items(): if class_.code == property_.domain_class_code: tables['domains'].rows.append([link(property_), property_.name]) elif class_.code == property_.range_class_code: tables['ranges'].rows.append([link(property_), property_.name]) return render_template('model/class_view.html', class_=class_, tables=tables, info={ 'code': class_.code, 'name': class_.name }, title=_('model'), crumbs=[[_('model'), url_for('model_index')], [_('classes'), url_for('class_index')], class_.code])
def admin_logo(id_: Optional[int] = None) -> Union[str, Response]: if session['settings']['logo_file_id']: abort(418) # pragma: no cover - Logo already set if id_: Settings.set_logo(id_) return redirect(url_for('admin_index') + '#tab-file') file_stats = get_file_stats() table = Table([''] + g.table_headers['file'] + ['date']) for entity in Entity.get_display_files(): date = 'N/A' if entity.id in file_stats: date = format_date( datetime.datetime.utcfromtimestamp( file_stats[entity.id]['date'])) table.rows.append([ link(_('set'), url_for('admin_logo', id_=entity.id)), truncate(entity.name), entity.print_standard_type(), convert_size(file_stats[entity.id]['size']) if entity.id in file_stats else 'N/A', file_stats[entity.id]['ext'] if entity.id in file_stats else 'N/A', entity.description, date ]) return render_template( 'admin/logo.html', table=table, title=_('logo'), crumbs=[[_('admin'), url_for('admin_index') + '#tab-files'], _('logo')])
def admin_log() -> str: form = LogForm() form.user.choices = [(0, _('all'))] + User.get_users_for_form() table = Table(['date', 'priority', 'type', 'message', 'user', 'info'], order=[[0, 'desc']]) logs = logger.get_system_logs(form.limit.data, form.priority.data, form.user.data) for row in logs: user = None if row['user_id']: try: user = link(User.get_by_id(row['user_id'])) except AttributeError: # pragma: no cover - user already deleted user = '******' + str(row['user_id']) table.rows.append([ format_datetime(row['created']), str(row['priority']) + ' ' + app.config['LOG_LEVELS'][row['priority']], row['type'], row['message'], user, row['info'] ]) return render_template( 'admin/log.html', table=table, form=form, title=_('admin'), crumbs=[[_('admin'), url_for('admin_index') + '#tab-general'], _('system log')])
def build_search_table(form: FlaskForm) -> Table: table = Table(['name', 'class', 'first', 'last', 'description']) for entity in search(form): table.rows.append([ link(entity), g.classes[entity.class_.name].label, entity.first, entity.last, entity.description ]) return table
def print_standard_type(self) -> str: from openatlas.models.node import Node if not self.class_.standard_type: return '' root_id = Node.get_hierarchy(self.class_.standard_type).id for node in self.nodes: if node.root and node.root[-1] == root_id: return link(node) return ''
def admin_check_similar() -> str: form = SimilarForm() form.classes.choices = [(x.name, x.label) for name, x in g.classes.items() if x.label] table = None if form.validate_on_submit(): table = Table(['name', _('count')]) for sample_id, sample in Entity.get_similar_named(form).items(): html = link(sample['entity']) for entity in sample['entities']: html += '<br><br><br><br><br>' + link( entity) # Workaround for linebreaks in tables table.rows.append([html, len(sample['entities']) + 1]) return render_template( 'admin/check_similar.html', table=table, form=form, title=_('admin'), crumbs=[[_('admin'), url_for('admin_index') + '#tab-data'], _('check similar names')])
def import_index() -> str: table = Table([_('project'), _('entities'), _('description')]) for project in Import.get_all_projects(): table.rows.append( [link(project), format_number(project.count), project.description]) return render_template( 'import/index.html', table=table, title=_('import'), crumbs=[[_('admin'), url_for('admin_index') + '#tab-data'], _('import')])
def admin_check_dates() -> str: # Get invalid date combinations (e.g. begin after end) tables = { 'link_dates': Table(['link', 'domain', 'range']), 'involvement_dates': Table(['actor', 'event', 'class', 'involvement', 'description']), 'dates': Table(['name', 'class', 'type', 'created', 'updated', 'description']) } for entity in Date.get_invalid_dates(): tables['dates'].rows.append([ link(entity), entity.class_.label, entity.print_standard_type(), format_date(entity.created), format_date(entity.modified), entity.description ]) for link_ in Date.get_invalid_link_dates(): label = '' if link_.property.code == 'OA7': # pragma: no cover label = 'relation' elif link_.property.code == 'P107': # pragma: no cover label = 'member' elif link_.property.code in ['P11', 'P14', 'P22', 'P23']: label = 'involvement' tables['link_dates'].rows.append([ link( _(label), url_for(label + '_update', id_=link_.id, origin_id=link_.domain.id)), link(link_.domain), link(link_.range) ]) for link_ in Date.invalid_involvement_dates(): event = link_.domain actor = link_.range data = [ link(actor), link(event), event.class_.label, link_.type.name if link_.type else '', link_.description, link( _('edit'), url_for('involvement_update', id_=link_.id, origin_id=actor.id)) ] tables['involvement_dates'].rows.append(data) return render_template( 'admin/check_dates.html', tables=tables, title=_('admin'), crumbs=[[_('admin'), url_for('admin_index') + '#tab-data'], _('check dates')])
def breadcrumb(self: Any, crumbs: List[Any]) -> str: items = [] for item in crumbs: if not item: continue # Item can be None e.g. if a dynamic generated URL has no origin parameter elif isinstance(item, Entity) or isinstance(item, Project) or isinstance(item, User): items.append(display.link(item)) elif isinstance(item, list): items.append('<a href="{url}">{label}</a>'.format( url=item[1], label=display.truncate(display.uc_first(str(item[0]))))) else: items.append(display.uc_first(item)) return Markup(' > '.join(items))
def admin_check_link_duplicates( delete: Optional[str] = None) -> Union[str, Response]: if delete: delete_count = str(Link.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 row in Link.check_link_duplicates(): table.rows.append([ link(Entity.get_by_id(row['domain_id'])), link(Entity.get_by_id(row['range_id'])), link(g.properties[row['property_code']]), row['description'], link(g.nodes[row['type_id']]) if row['type_id'] else '', format_date(row['begin_from']), format_date(row['begin_to']), row['begin_comment'], format_date(row['end_from']), format_date(row['end_to']), row['end_comment'], row['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=Link.check_single_type_duplicates()) return render_template( 'admin/check_link_duplicates.html', table=table, duplicates=duplicates, title=_('admin'), crumbs=[[_('admin'), url_for('admin_index') + '#tab-data'], _('check link duplicates')])
def display_external_references(self: Any, entity: Entity) -> str: system_links = [] for link_ in entity.reference_systems: system = g.reference_systems[link_.domain.id] name = link_.description if system.resolver_url: name = '<a href="{url}" target="_blank" rel="noopener noreferrer">{name}</a>'.format( url=system.resolver_url + name, name=name) system_links.append('''{name} ({match} {at} {system_name})'''.format( name=name, match= g.nodes[link_.type.id].name, at=_('at'), system_name= display.link(link_.domain))) html = '<br>'.join(system_links) if not html: return '' return Markup('<h2>' + display.uc_first(_('external reference systems')) + '</h2>' + html)
def import_project_view(id_: int) -> str: table = Table( [_('name'), _('class'), _('description'), 'origin ID', _('date')]) for entity in Entity.get_by_project_id(id_): table.rows.append([ link(entity), entity.class_.label, entity.description, entity.origin_id, format_date(entity.created) ]) project = Import.get_project_by_id(id_) return render_template( 'import/project_view.html', project=project, table=table, title=_('import'), crumbs=[[_('admin'), url_for('admin_index') + '#tab-data'], [_('import'), url_for('import_index')], project.name])
def note_view(id_: int) -> str: note = User.get_note_by_id(id_) if not note['public'] and note['user_id'] != current_user.id: abort(403) # pragma: no cover entity = Entity.get_by_id(note['entity_id']) buttons: List[str] = [] if note['user_id'] == current_user.id: buttons = [ button(_('edit'), url_for('note_update', id_=note['id'])), button(_('delete'), url_for('note_delete', id_=note['id']))] elif is_authorized('manager'): # pragma: no cover buttons = [button(_('set private'), url_for('note_set_private', id_=note['id']))] return render_template( 'user/note.html', entity=entity, note=note, tabs={'info': Tab('info')}, buttons=buttons, crumbs=[ [_(entity.class_.view), url_for('index', view=entity.class_.view)], link(entity), _('note')])
def hierarchy_update(id_: int) -> Union[str, Response]: hierarchy = g.nodes[id_] if g.nodes[id_].value_type: tab_hash = '#menu-tab-value_collapse-' else: tab_hash = '#menu-tab-custom_collapse-' if hierarchy.standard: abort(403) form = build_form('hierarchy', hierarchy) form.forms.choices = Node.get_form_choices(hierarchy) if hasattr(form, 'multiple') and form.multiple.data: form.multiple.render_kw = {'disabled': 'disabled'} if form.validate_on_submit(): if form.name.data != hierarchy.name and Node.get_nodes(form.name.data): flash(_('error name exists'), 'error') return redirect(url_for('node_index') + tab_hash + str(hierarchy.id)) save(form, hierarchy) flash(_('info update'), 'info') return redirect(url_for('node_index') + tab_hash + str(hierarchy.id)) form.multiple = hierarchy.multiple table = Table(paging=False) for form_id, form_ in hierarchy.forms.items(): link_ = link( _('remove'), url_for('hierarchy_remove_form', id_=hierarchy.id, form_id=form_id)) count = Node.get_form_count(hierarchy, form_id) label = g.classes[form_['name']].label table.rows.append([label, format_number(count) if count else link_]) return render_template( 'display_form.html', form=form, table=table, forms=[form.id for form in form.forms], manual_page='entity/type', title=_('types'), crumbs=[[_('types'), url_for('node_index')], hierarchy, _('edit')])
def admin_index(action: Optional[str] = None, id_: Optional[int] = None) -> Union[str, Response]: if is_authorized('manager'): if id_ and action == 'delete_user': user = User.get_by_id(id_) if not user \ or user.id == current_user.id \ or (user.group == 'admin' and not is_authorized('admin')): abort(403) # pragma: no cover User.delete(id_) flash(_('user deleted'), 'info') elif action == 'remove_logo': Settings.set_logo() return redirect(url_for('admin_index') + '#tab-file') dirs = { 'uploads': True if os.access(app.config['UPLOAD_DIR'], os.W_OK) else False, 'export/sql': True if os.access(app.config['EXPORT_DIR'] / 'sql', os.W_OK) else False, 'export/csv': True if os.access(app.config['EXPORT_DIR'] / 'csv', os.W_OK) else False } tables = { 'user': Table([ 'username', 'name', 'group', 'email', 'newsletter', 'created', 'last login', 'entities' ]), 'content': Table(['name'] + [language for language in app.config['LANGUAGES'].keys()]) } for user in User.get_all(): count = User.get_created_entities_count(user.id) email = user.email if is_authorized( 'manager') or user.settings['show_email'] else '' tables['user'].rows.append([ link(user), user.real_name, user.group, email, _('yes') if user.settings['newsletter'] else '', format_date(user.created), format_date(user.login_last_success), format_number(count) if count else '' ]) for item, languages in Content.get_content().items(): content = [uc_first(_(item))] for language in app.config['LANGUAGES'].keys(): content.append(sanitize(languages[language], 'text')) content.append(link(_('edit'), url_for('admin_content', item=item))) tables['content'].rows.append(content) form = None if is_authorized('admin'): form = TestMailForm() if form.validate_on_submit( ) and session['settings']['mail']: # pragma: no cover subject = _('Test mail from %(site_name)s', site_name=session['settings']['site_name']) body = _('This test mail was sent by %(username)s', username=current_user.username) body += ' ' + _('at') + ' ' + request.headers['Host'] if send_mail(subject, body, form.receiver.data): flash( _('A test mail was sent to %(email)s.', email=form.receiver.data), 'info') else: form.receiver.data = current_user.email return render_template('admin/index.html', form=form, tables=tables, settings=session['settings'], writeable_dirs=dirs, disk_space_info=get_disk_space_info(), imports=Import.get_all_projects(), title=_('admin'), crumbs=[_('admin')], info={ 'file': get_form_settings(FilesForm()), 'general': get_form_settings(GeneralForm()), 'mail': get_form_settings(MailForm()), 'map': get_form_settings(MapForm()), 'api': get_form_settings(ApiForm()), 'modules': get_form_settings(ModulesForm()) })
def link(self: Any, entity: Entity) -> str: return display.link(entity)
def entity_view(id_: int) -> Union[str, Response]: if id_ in g.nodes: # Nodes have their own view entity = g.nodes[id_] if not entity.root: if entity.class_.name == 'administrative_unit': tab_hash = '#menu-tab-places_collapse-' elif entity.standard: tab_hash = '#menu-tab-standard_collapse-' elif entity.value_type: tab_hash = '#menu-tab-value_collapse-' else: tab_hash = '#menu-tab-custom_collapse-' return redirect(url_for('node_index') + tab_hash + str(id_)) elif id_ in g.reference_systems: entity = g.reference_systems[id_] else: entity = Entity.get_by_id(id_, nodes=True, aliases=True) if not entity.class_.view: flash(_("This entity can't be viewed directly."), 'error') abort(400) event_links = None # Needed for actor overlays = None # Needed for place tabs = {'info': Tab('info')} if isinstance(entity, Node): tabs['subs'] = Tab('subs', entity) tabs['entities'] = Tab('entities', entity) root = g.nodes[entity.root[-1]] if entity.root else None if root and root.value_type: # pragma: no cover tabs['entities'].table.header = [ _('name'), _('value'), _('class'), _('info') ] for item in entity.get_linked_entities(['P2', 'P89'], inverse=True, nodes=True): if item.class_.name in ['location', 'reference_system']: continue # pragma: no cover if item.class_.name == 'object_location': # pragma: no cover item = item.get_linked_entity_safe('P53', inverse=True) data = [link(item)] if root and root.value_type: # pragma: no cover data.append(format_number(item.nodes[entity])) data.append(item.class_.label) data.append(item.description) tabs['entities'].table.rows.append(data) for sub_id in entity.subs: sub = g.nodes[sub_id] tabs['subs'].table.rows.append( [link(sub), sub.count, sub.description]) if not tabs[ 'entities'].table.rows: # If no entities available get links with this type_id tabs['entities'].table.header = [_('domain'), _('range')] for row in Link.get_entities_by_node(entity): tabs['entities'].table.rows.append([ link(Entity.get_by_id(row['domain_id'])), link(Entity.get_by_id(row['range_id'])) ]) elif isinstance(entity, ReferenceSystem): for form_id, form in entity.get_forms().items(): tabs[form['name']] = Tab(form['name'], origin=entity) tabs[form['name']].table = Table( [_('entity'), 'id', _('precision')]) for link_ in entity.get_links('P67'): name = link_.description if entity.resolver_url: name = \ '<a href="{url}" target="_blank" rel="noopener noreferrer">{name}</a>'.format( url=entity.resolver_url + name, name=name) tab_name = link_.range.class_.name tabs[tab_name].table.rows.append( [link(link_.range), name, link_.type.name]) for form_id, form in entity.get_forms().items(): if not tabs[form['name']].table.rows and is_authorized('manager'): tabs[form['name']].buttons = [ button( _('remove'), url_for('reference_system_remove_form', system_id=entity.id, form_id=form_id)) ] elif entity.class_.view == 'actor': for name in ['source', 'event', 'relation', 'member_of', 'member']: tabs[name] = Tab(name, entity) event_links = entity.get_links(['P11', 'P14', 'P22', 'P23', 'P25'], True) for link_ in event_links: event = link_.domain places = event.get_linked_entities(['P7', 'P26', 'P27']) link_.object_ = None for place in places: object_ = place.get_linked_entity_safe('P53', True) entity.linked_places.append(object_) link_.object_ = object_ # Needed later for first/last appearance info first = link_.first if not link_.first and event.first: first = '<span class="inactive">' + event.first + '</span>' last = link_.last if not link_.last and event.last: last = '<span class="inactive">' + event.last + '</span>' data = [ link(event), event.class_.label, link(link_.type), first, last, link_.description ] data = add_edit_link( data, url_for('involvement_update', id_=link_.id, origin_id=entity.id)) data = add_remove_link(data, link_.domain.name, link_, entity, 'event') tabs['event'].table.rows.append(data) for link_ in entity.get_links('OA7') + entity.get_links('OA7', True): type_ = '' if entity.id == link_.domain.id: related = link_.range if link_.type: type_ = link(link_.type.get_name_directed(), url_for('entity_view', id_=link_.type.id)) else: related = link_.domain if link_.type: type_ = link(link_.type.get_name_directed(True), url_for('entity_view', id_=link_.type.id)) data = [ type_, link(related), link_.first, link_.last, link_.description ] data = add_edit_link( data, url_for('relation_update', id_=link_.id, origin_id=entity.id)) data = add_remove_link(data, related.name, link_, entity, 'relation') tabs['relation'].table.rows.append(data) for link_ in entity.get_links('P107', True): data = [ link(link_.domain), link(link_.type), link_.first, link_.last, link_.description ] data = add_edit_link( data, url_for('member_update', id_=link_.id, origin_id=entity.id)) data = add_remove_link(data, link_.domain.name, link_, entity, 'member-of') tabs['member_of'].table.rows.append(data) if entity.class_.name != 'group': del tabs['member'] else: for link_ in entity.get_links('P107'): data = [ link(link_.range), link(link_.type), link_.first, link_.last, link_.description ] data = add_edit_link( data, url_for('member_update', id_=link_.id, origin_id=entity.id)) data = add_remove_link(data, link_.range.name, link_, entity, 'member') tabs['member'].table.rows.append(data) elif entity.class_.view == 'artifact': tabs['source'] = Tab('source', entity) elif entity.class_.view == 'event': for name in ['subs', 'source', 'actor']: tabs[name] = Tab(name, entity) for sub_event in entity.get_linked_entities('P117', inverse=True, nodes=True): tabs['subs'].table.rows.append(get_base_table_data(sub_event)) tabs['actor'].table.header.insert( 5, _('activity')) # Add a table column for activity for link_ in entity.get_links(['P11', 'P14', 'P22', 'P23']): first = link_.first if not link_.first and entity.first: first = '<span class="inactive">' + entity.first + '</span>' last = link_.last if not link_.last and entity.last: last = '<span class="inactive">' + entity.last + '</span>' data = [ link(link_.range), link_.range.class_.label, link_.type.name if link_.type else '', first, last, g.properties[link_.property.code].name_inverse, link_.description ] data = add_edit_link( data, url_for('involvement_update', id_=link_.id, origin_id=entity.id)) data = add_remove_link(data, link_.range.name, link_, entity, 'actor') tabs['actor'].table.rows.append(data) entity.linked_places = [ location.get_linked_entity_safe('P53', True) for location in entity.get_linked_entities(['P7', 'P26', 'P27']) ] elif entity.class_.view == 'file': for name in [ 'source', 'event', 'actor', 'place', 'feature', 'stratigraphic_unit', 'artifact', 'human_remains', 'reference', 'type' ]: tabs[name] = Tab(name, entity) entity.image_id = entity.id if get_file_path(entity.id) else None for link_ in entity.get_links('P67'): range_ = link_.range data = get_base_table_data(range_) data = add_remove_link(data, range_.name, link_, entity, range_.class_.name) tabs[range_.class_.view].table.rows.append(data) for link_ in entity.get_links('P67', True): data = get_base_table_data(link_.domain) data.append(link_.description) data = add_edit_link( data, url_for('reference_link_update', link_id=link_.id, origin_id=entity.id)) data = add_remove_link(data, link_.domain.name, link_, entity, 'reference') tabs['reference'].table.rows.append(data) elif entity.class_.view == 'place': tabs['source'] = Tab('source', entity) tabs['event'] = Tab('event', entity) tabs['reference'] = Tab('reference', entity) if entity.class_.name == 'place': tabs['actor'] = Tab('actor', entity) tabs['feature'] = Tab('feature', origin=entity) elif entity.class_.name == 'feature': tabs['stratigraphic_unit'] = Tab('stratigraphic_unit', origin=entity) elif entity.class_.name == 'stratigraphic_unit': tabs['find'] = Tab('find', origin=entity) tabs['human_remains'] = Tab('human_remains', origin=entity) entity.location = entity.get_linked_entity_safe('P53', nodes=True) event_ids = [ ] # Keep track of already inserted events to prevent doubles for event in entity.location.get_linked_entities(['P7', 'P26', 'P27'], inverse=True): tabs['event'].table.rows.append(get_base_table_data(event)) event_ids.append(event.id) for event in entity.get_linked_entities('P24', inverse=True): if event.id not in event_ids: # Don't add again if already in table tabs['event'].table.rows.append(get_base_table_data(event)) if 'actor' in tabs: for link_ in entity.location.get_links(['P74', 'OA8', 'OA9'], inverse=True): actor = Entity.get_by_id(link_.domain.id) tabs['actor'].table.rows.append([ link(actor), g.properties[link_.property.code].name, actor.class_.name, actor.first, actor.last, actor.description ]) elif entity.class_.view == 'reference': for name in [ 'source', 'event', 'actor', 'place', 'feature', 'stratigraphic_unit', 'human_remains', 'artifact', 'file' ]: tabs[name] = Tab(name, entity) for link_ in entity.get_links('P67'): range_ = link_.range data = get_base_table_data(range_) data.append(link_.description) data = add_edit_link( data, url_for('reference_link_update', link_id=link_.id, origin_id=entity.id)) data = add_remove_link(data, range_.name, link_, entity, range_.class_.name) tabs[range_.class_.view].table.rows.append(data) elif entity.class_.view == 'source': for name in [ 'actor', 'artifact', 'feature', 'event', 'human_remains', 'place', 'stratigraphic_unit', 'text' ]: tabs[name] = Tab(name, entity) for text in entity.get_linked_entities('P73', nodes=True): tabs['text'].table.rows.append([ link(text), next(iter(text.nodes)).name if text.nodes else '', text.description ]) for link_ in entity.get_links('P67'): range_ = link_.range data = get_base_table_data(range_) data = add_remove_link(data, range_.name, link_, entity, range_.class_.name) tabs[range_.class_.view].table.rows.append(data) if entity.class_.view in [ 'actor', 'artifact', 'event', 'place', 'source', 'type' ]: if entity.class_.view != 'reference' and not isinstance(entity, Node): tabs['reference'] = Tab('reference', entity) if entity.class_.view == 'artifact': tabs['event'] = Tab('event', entity) for link_ in entity.get_links('P25', True): data = get_base_table_data(link_.domain) tabs['event'].table.rows.append(data) tabs['file'] = Tab('file', entity) entity.image_id = entity.get_profile_image_id() tabs['file'].table.header.append(uc_first(_('overlay'))) for link_ in entity.get_links('P67', inverse=True): domain = link_.domain data = get_base_table_data(domain) if domain.class_.view == 'file': # pragma: no cover extension = data[3] data.append( get_profile_image_table_link(domain, entity, extension, entity.image_id)) if not entity.image_id and extension in app.config[ 'DISPLAY_FILE_EXTENSIONS']: entity.image_id = domain.id if entity.class_.view == 'place' and is_authorized('editor') and \ current_user.settings['module_map_overlay']: overlays = Overlay.get_by_object(entity) if extension in app.config['DISPLAY_FILE_EXTENSIONS']: if domain.id in overlays: data = add_edit_link( data, url_for('overlay_update', id_=overlays[domain.id].id)) else: data.append( link( _('link'), url_for('overlay_insert', image_id=domain.id, place_id=entity.id, link_id=link_.id))) else: # pragma: no cover data.append('') if domain.class_.view not in ['source', 'file']: data.append(link_.description) data = add_edit_link( data, url_for('reference_link_update', link_id=link_.id, origin_id=entity.id)) if domain.class_.view == 'reference_system': entity.reference_systems.append(link_) continue data = add_remove_link(data, domain.name, link_, entity, domain.class_.view) tabs[domain.class_.view].table.rows.append(data) structure = None # Needed for place gis_data = None # Needed for place if entity.class_.view in ['artifact', 'place']: structure = get_structure(entity) if structure: for item in structure['subunits']: tabs[item.class_.name].table.rows.append( get_base_table_data(item)) gis_data = Gis.get_all([entity], structure) if gis_data['gisPointSelected'] == '[]' \ and gis_data['gisPolygonSelected'] == '[]' \ and gis_data['gisLineSelected'] == '[]' \ and (not structure or not structure['super_id']): gis_data = {} if not gis_data: gis_data = Gis.get_all( entity.linked_places) if entity.linked_places else None entity.info_data = get_entity_data(entity, event_links=event_links) tabs['note'] = Tab('note', entity) for note in current_user.get_notes_by_entity_id(entity.id): data = [ format_date(note['created']), uc_first(_('public')) if note['public'] else uc_first(_('private')), link(User.get_by_id(note['user_id'])), note['text'], '<a href="{url}">{label}</a>'.format(url=url_for('note_view', id_=note['id']), label=uc_first(_('view'))) ] tabs['note'].table.rows.append(data) return render_template( 'entity/view.html', entity=entity, tabs=tabs, buttons=add_buttons(entity), structure=structure, # Needed for place views overlays=overlays, # Needed for place views gis_data=gis_data, title=entity.name, crumbs=add_crumbs(entity, structure))
def overview() -> str: tables = { 'overview': Table(paging=False, defs=[{ 'className': 'dt-body-right', 'targets': 1 }]), 'bookmarks': Table(['name', 'class', _('first'), _('last')]), 'notes': Table(['date', _('visibility'), 'entity', 'class', _('note')]), 'latest': Table(order=[[0, 'desc']]) } if current_user.is_authenticated and hasattr(current_user, 'bookmarks'): for entity_id in current_user.bookmarks: entity = Entity.get_by_id(entity_id) tables['bookmarks'].rows.append([ link(entity), entity.class_.label, entity.first, entity.last, bookmark_toggle(entity.id, True) ]) for note in User.get_notes_by_user_id(current_user.id): entity = Entity.get_by_id(note['entity_id']) tables['notes'].rows.append([ format_date(note['created']), uc_first(_('public')) if note['public'] else uc_first( _('private')), link(entity), entity.class_.label, note['text'], '<a href="{url}">{label}</a>'.format(url=url_for( 'note_view', id_=note['id']), label=uc_first(_('view'))) ]) for name, count in Entity.get_overview_counts().items(): if count: url = url_for('index', view=g.class_view_mapping[name]) if name == 'administrative_unit': url = url_for('node_index') + '#menu-tab-places' elif name == 'type': url = url_for('node_index') elif name == 'find': url = url_for('index', view='artifact') elif name in [ 'feature', 'human_remains', 'stratigraphic_unit', 'source_translation' ]: url = '' tables['overview'].rows.append([ link(g.classes[name].label, url) if url else g.classes[name].label, format_number(count) ]) for entity in Entity.get_latest(8): tables['latest'].rows.append([ format_date(entity.created), link(entity), entity.class_.label, entity.first, entity.last, link(logger.get_log_for_advanced_view(entity.id)['creator']) ]) return render_template('index/index.html', intro=Content.get_translation('intro'), crumbs=['overview'], tables=tables)
def update(id_: int) -> Union[str, Response]: entity = Entity.get_by_id(id_, nodes=True, aliases=True) if not entity.class_.view: abort(422) # pragma: no cover elif not is_authorized(entity.class_.write_access): abort(403) # pragma: no cover elif isinstance(entity, Node): root = g.nodes[entity.root[-1]] if entity.root else None if not root and (entity.standard or entity.locked): abort(403) # pragma: no cover # Archaeological sub units geonames_module = False if entity.class_.name == 'place' and ReferenceSystem.get_by_name( 'GeoNames').forms: geonames_module = True structure = None gis_data = None overlays = None location = None if entity.class_.view in ['artifact', 'place']: structure = get_structure(entity) location = entity.get_linked_entity_safe('P53', nodes=True) gis_data = Gis.get_all([entity], structure) overlays = Overlay.get_by_object(entity) form = build_form(entity.class_.name, entity, location=location) if entity.class_.view == 'event': form.event_id.data = entity.id elif isinstance(entity, ReferenceSystem) and entity.system: form.name.render_kw['readonly'] = 'readonly' if form.validate_on_submit(): if isinstance(entity, Node): valid = True root = g.nodes[entity.root[-1]] new_super_id = getattr(form, str(root.id)).data new_super = g.nodes[int(new_super_id)] if new_super_id else None if new_super: if new_super.id == entity.id: flash(_('error node self as super'), 'error') valid = False if new_super.root and entity.id in new_super.root: flash(_('error node sub as super'), 'error') valid = False if not valid: return redirect(url_for('entity_view', id_=entity.id)) if was_modified(form, entity): # pragma: no cover del form.save flash(_('error modified'), 'error') return render_template('entity/update.html', form=form, entity=entity, structure=structure, modifier=link( logger.get_log_for_advanced_view( entity.id)['modifier'])) return redirect(save(form, entity)) populate_update_form(form, entity) return render_template('entity/update.html', form=form, entity=entity, structure=structure, gis_data=gis_data, overlays=overlays, geonames_module=geonames_module, title=entity.name, crumbs=add_crumbs(view_name=entity.class_.view, class_=entity.class_.name, origin=entity, structure=structure))
def 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 Entity.get_circular()] for entity in Entity.get_orphans(): if isinstance(entity, ReferenceSystem): continue name = 'unlinked' if entity.class_.view else 'orphans' tables[name].rows.append([ link(entity), link(entity.class_), entity.print_standard_type(), entity.class_.label, format_date(entity.created), format_date(entity.modified), entity.description ]) for node in Node.get_node_orphans(): tables['nodes'].rows.append([link(node), link(g.nodes[node.root[-1]])]) # Get orphaned file entities with no corresponding file entity_file_ids = [] for entity in Entity.get_by_class('file', nodes=True): entity_file_ids.append(entity.id) if not get_file_path(entity): tables['missing_files'].rows.append([ link(entity), link(entity.class_), entity.print_standard_type(), entity.class_.label, format_date(entity.created), format_date(entity.modified), entity.description ]) # Get orphaned files with no corresponding entity for file in app.config['UPLOAD_DIR'].iterdir(): if file.name != '.gitignore' and int(file.stem) not in entity_file_ids: tables['orphaned_files'].rows.append([ file.stem, convert_size(file.stat().st_size), format_date( datetime.datetime.utcfromtimestamp(file.stat().st_ctime)), file.suffix, link(_('download'), url_for('download_file', filename=file.name)), delete_link(file.name, url_for('admin_file_delete', filename=file.name)) ]) return render_template( 'admin/check_orphans.html', tables=tables, title=_('admin'), crumbs=[[_('admin'), url_for('admin_index') + '#tab-data'], _('orphans')])