예제 #1
0
 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
예제 #2
0
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')])
예제 #3
0
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')])
예제 #4
0
 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
예제 #5
0
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')])
예제 #6
0
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
예제 #7
0
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])
예제 #8
0
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')])
예제 #9
0
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')])
예제 #10
0
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')])
예제 #11
0
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])
예제 #12
0
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')])
예제 #13
0
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')])
예제 #14
0
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
예제 #15
0
 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 ''
예제 #16
0
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')])
예제 #17
0
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')])
예제 #18
0
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')])
예제 #19
0
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('&nbsp;>&nbsp; '.join(items))
예제 #20
0
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')])
예제 #21
0
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)
예제 #22
0
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])
예제 #23
0
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')])
예제 #24
0
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')])
예제 #25
0
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())
                           })
예제 #26
0
def link(self: Any, entity: Entity) -> str:
    return display.link(entity)
예제 #27
0
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))
예제 #28
0
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)
예제 #29
0
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))
예제 #30
0
def admin_orphans() -> str:
    header = [
        'name', 'class', 'type', 'system type', 'created', 'updated',
        'description'
    ]
    tables = {
        'orphans': Table(header),
        'unlinked': Table(header),
        'missing_files': Table(header),
        'circular': Table(['entity']),
        'nodes': Table(['name', 'root']),
        'orphaned_files': Table(['name', 'size', 'date', 'ext'])
    }
    tables['circular'].rows = [[link(entity)]
                               for entity in 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')])