Beispiel #1
0
def user_insert():
    form = UserForm()
    form.group.choices = get_groups()
    if not session['settings']['mail']:
        del form.send_info
    if form.validate_on_submit():
        user_id = UserMapper.insert(form)
        flash(_('user created'), 'info')
        if session['settings']['mail'] and form.send_info.data:  # pragma: no cover
            subject = _(
                'Your account information for %(sitename)s',
                sitename=session['settings']['site_name'])
            body = _('Account information for %(username)s', username=form.username.data) + ' '
            body += _('at') + ' ' + request.scheme + '://' + request.headers['Host'] + '\n\n'
            body += uc_first(_('username')) + ': ' + form.username.data + '\n'
            body += uc_first(_('password')) + ': ' + form.password.data + '\n'
            if send_mail(subject, body, form.email.data, False):
                flash(
                    _('Sent account information mail to %(email)s.', email=form.email.data), 'info')
            else:
                flash(
                    _('Failed to send account details to %(email)s.',
                      email=form.email.data),
                    'error')
            return redirect(url_for('user_index'))
        if form.continue_.data == 'yes':
            return redirect(url_for('user_insert'))
        return redirect(url_for('user_view', id_=user_id))
    return render_template('user/insert.html', form=form)
Beispiel #2
0
def build_table_form(class_name: str, linked_entities: Iterator) -> str:
    """ Returns a form with a list of entities with checkboxes"""
    from openatlas.models.entity import EntityMapper
    table = Table(Table.HEADERS[class_name] + [''])
    linked_ids = [entity.id for entity in linked_entities]
    file_stats = get_file_stats() if class_name == 'file' else None
    if class_name == 'file':
        entities = EntityMapper.get_by_system_type('file', nodes=True)
    elif class_name == 'place':
        entities = EntityMapper.get_by_system_type('place',
                                                   nodes=True,
                                                   aliases=True)
    else:
        entities = EntityMapper.get_by_codes(class_name)
    for entity in entities:
        if entity.id in linked_ids:
            continue  # Don't show already linked entries
        input_ = '<input id="selection-{id}" name="values" type="checkbox" value="{id}">'.format(
            id=entity.id)
        table.rows.append(get_base_table_data(entity, file_stats) + [input_])
    if not table.rows:
        return uc_first(_('no entries'))
    return """
        <form class="table" id="checkbox-form" method="post">
            <input id="csrf_token" name="csrf_token" type="hidden" value="{token}">
            <input id="checkbox_values" name="checkbox_values" type="hidden">
            {table} <button name="form-submit" id="form-submit" type="submit">{add}</button>
        </form>""".format(add=uc_first(_('add')),
                          token=generate_csrf(),
                          table=table.display(class_name))
def export_csv():
    path = app.config['EXPORT_FOLDER_PATH'] + '/csv'
    writeable = True if os.access(path, os.W_OK) else False
    form = ExportCsvForm()
    if form.validate_on_submit() and writeable:
        Export.export_csv(form)
        logger.log('info', 'database', 'CSV export')
        flash(_('data was exported as CSV'), 'info')
        return redirect(url_for('export_csv'))
    table = {'id': 'csv', 'header': ['name', 'size'], 'data': [],
             'sort': 'sortList: [[0, 1]],headers: {0: { sorter: "text" }}'}
    for file in [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]:
        name = basename(file)
        if name == '.gitignore':
            continue
        link = '<a href="{url}">{label}</a>'.format(url=url_for('download_csv', filename=name),
                                                    label=uc_first(_('download')))
        data = [name, convert_size(os.path.getsize(path + '/' + name)), link]
        if is_authorized('admin') and writeable:
            confirm = ' onclick="return confirm(\'' + _('Delete %(name)s?', name=name) + '\')"'
            delete = '<a href="' + url_for('delete_csv', filename=name)
            delete += '" ' + confirm + '>' + uc_first(_('delete')) + '</a>'
            data.append(delete)
        table['data'].append(data)
    return render_template('export/export_csv.html', form=form, table=table, writeable=writeable)
def export_sql():
    path = app.config['EXPORT_FOLDER_PATH'] + '/sql'
    writeable = True if os.access(path, os.W_OK) else False
    form = ExportSqlForm()
    if form.validate_on_submit() and writeable:
        if Export.export_sql():
            logger.log('info', 'database', 'SQL export')
            flash(_('data was exported as SQL'), 'info')
        else:  # pragma: no cover
            logger.log('error', 'database', 'SQL export failed')
            flash(_('SQL export failed'), 'error')
        return redirect(url_for('export_sql'))
    table = {'id': 'sql', 'header': ['name', 'size'], 'data': [],
             'sort': 'sortList: [[0, 1]],headers: {0: { sorter: "text" }}'}
    for file in [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]:
        name = basename(file)
        if name == '.gitignore':
            continue
        url = url_for('download_sql', filename=name)
        data = [name, convert_size(os.path.getsize(path + '/' + name)),
                '<a href="' + url + '">' + uc_first(_('download')) + '</a>']
        if is_authorized('admin') and writeable:
            confirm = ' onclick="return confirm(\'' + _('Delete %(name)s?', name=name) + '\')"'
            delete = '<a href="' + url_for('delete_sql', filename=name)
            delete += '" ' + confirm + '>' + uc_first(_('delete')) + '</a>'
            data.append(delete)
        table['data'].append(data)
    return render_template('export/export_sql.html', form=form, table=table, writeable=writeable)
Beispiel #5
0
def add_buttons(form: Any,
                name: str,
                entity: Union[Entity, None],
                origin: Optional[Entity] = None) -> FlaskForm:
    setattr(form, 'save', SubmitField(_('save') if entity else _('insert')))
    if entity:
        return form
    if 'continue' in FORMS[name] and (
            name in ['involvement', 'find', 'human_remains', 'type']
            or not origin):
        setattr(form, 'insert_and_continue',
                SubmitField(uc_first(_('insert and continue'))))
        setattr(form, 'continue_', HiddenField())
    insert_add = uc_first(_('insert and add')) + ' '
    if name == 'place':
        setattr(form, 'insert_and_continue',
                SubmitField(uc_first(_('insert and continue'))))
        setattr(form, 'continue_', HiddenField())
        setattr(form, 'insert_continue_sub',
                SubmitField(insert_add + _('feature')))
    elif name == 'feature' and origin and origin.class_.name == 'place':
        setattr(form, 'insert_and_continue',
                SubmitField(uc_first(_('insert and continue'))))
        setattr(form, 'continue_', HiddenField())
        setattr(form, 'insert_continue_sub',
                SubmitField(insert_add + _('stratigraphic unit')))
    elif name == 'stratigraphic_unit':
        setattr(form, 'insert_and_continue',
                SubmitField(uc_first(_('insert and continue'))))
        setattr(form, 'continue_', HiddenField())
        setattr(form, 'insert_continue_sub',
                SubmitField(insert_add + _('find')))
        setattr(form, 'insert_continue_human_remains',
                SubmitField(insert_add + _('human remains')))
    return form
def reset_confirm(code):  # pragma: no cover
    user = UserMapper.get_by_reset_code(code)
    if not user:
        logger.log('info', 'auth', 'unknown reset code')
        flash(_('invalid password reset confirmation code'), 'error')
        abort(404)
    hours = session['settings']['reset_confirm_hours']
    if datetime.datetime.now() > user.password_reset_date + datetime.timedelta(hours=hours):
        logger.log('info', 'auth', 'reset code expired')
        flash(_('This reset confirmation code has expired.'), 'error')
        abort(404)
    password = UserMapper.generate_password()
    user.password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
    user.password_reset_code = None
    user.password_reset_date = None
    user.login_failed_count = 0
    user.update()
    subject = _('New password for %(sitename)s', sitename=session['settings']['site_name'])
    body = _('New password for %(username)s', username=user.username) + ' '
    body += _('at') + ' ' + request.scheme + '://' + request.headers['Host'] + ':\n\n'
    body += uc_first(_('username')) + ': ' + user.username + '\n'
    body += uc_first(_('password')) + ': ' + password + '\n'
    if send_mail(subject, body, user.email, False):
        flash(_('Send new password mail to %(email)s.', email=user.email), 'info')
    else:
        flash(_('Failed to send password mail to %(email)s.', email=user.email), 'error')
    return redirect(url_for('login'))
Beispiel #7
0
def reset_confirm(code: str) -> str:  # pragma: no cover
    user = UserMapper.get_by_reset_code(code)
    if not user:
        logger.log('info', 'auth', 'unknown reset code')
        flash(_('invalid password reset confirmation code'), 'error')
        abort(404)
    hours = session['settings']['reset_confirm_hours']
    if datetime.datetime.now() > user.password_reset_date + datetime.timedelta(
            hours=hours):
        logger.log('info', 'auth', 'reset code expired')
        flash(_('This reset confirmation code has expired.'), 'error')
        abort(404)
    password = UserMapper.generate_password()
    user.password = bcrypt.hashpw(password.encode('utf-8'),
                                  bcrypt.gensalt()).decode('utf-8')
    user.password_reset_code = None
    user.password_reset_date = None
    user.login_failed_count = 0
    user.update()
    subject = _('New password for %(sitename)s',
                sitename=session['settings']['site_name'])
    body = _('New password for %(username)s', username=user.username) + ' '
    body += _('at') + ' ' + request.scheme + '://' + request.headers[
        'Host'] + ':\n\n'
    body += uc_first(_('username')) + ': ' + user.username + '\n'
    body += uc_first(_('password')) + ': ' + password + '\n'
    if send_mail(subject, body, user.email, False):
        flash(_('Send new password mail to %(email)s.', email=user.email),
              'info')
    else:
        flash(
            _('Failed to send password mail to %(email)s.', email=user.email),
            'error')
    return redirect(url_for('login'))
Beispiel #8
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', 'system type', 'created', 'updated',
                              'description'])}
    for entity in DateMapper.get_invalid_dates():
        tables['dates'].rows.append([link(entity), link(entity.class_), entity.print_base_type(),
                                     entity.system_type, format_date(entity.created),
                                     format_date(entity.modified),
                                     truncate_string(entity.description)])
    for link_ in DateMapper.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'
        url = url_for(label + '_update', id_=link_.id, origin_id=link_.domain.id)
        tables['link_dates'].rows.append(['<a href="' + url + '">' + uc_first(_(label)) + '</a>',
                                          link(link_.domain), link(link_.range)])
    for link_ in DateMapper.invalid_involvement_dates():
        event = link_.domain
        actor = link_.range
        update_url = url_for('involvement_update', id_=link_.id, origin_id=actor.id)
        data = ([link(actor), link(event), g.classes[event.class_.code].name,
                 link_.type.name if link_.type else '', truncate_string(link_.description),
                 '<a href="' + update_url + '">' + uc_first(_('edit')) + '</a>'])
        tables['involvement_dates'].rows.append(data)
    return render_template('admin/check_dates.html', tables=tables)
Beispiel #9
0
def export_csv() -> str:
    path = app.config['EXPORT_FOLDER_PATH'] + '/csv'
    writeable = True if os.access(path, os.W_OK) else False
    form = ExportCsvForm()
    if form.validate_on_submit() and writeable:
        Export.export_csv(form)
        logger.log('info', 'database', 'CSV export')
        flash(_('data was exported as CSV'), 'info')
        return redirect(url_for('export_csv'))
    table = Table(['name', 'size'], order='[[0, "desc"]]')
    for file in [
            f for f in os.listdir(path)
            if os.path.isfile(os.path.join(path, f))
    ]:
        name = basename(file)
        if name == '.gitignore':
            continue
        link = '<a href="{url}">{label}</a>'.format(url=url_for('download_csv',
                                                                filename=name),
                                                    label=uc_first(
                                                        _('download')))
        data = [name, convert_size(os.path.getsize(path + '/' + name)), link]
        if is_authorized('admin') and writeable:
            confirm = ' onclick="return confirm(\'' + _('Delete %(name)s?',
                                                        name=name) + '\')"'
            delete = '<a href="' + url_for('delete_csv', filename=name)
            delete += '" ' + confirm + '>' + uc_first(_('delete')) + '</a>'
            data.append(delete)
        table.rows.append(data)
    return render_template('export/export_csv.html',
                           form=form,
                           table=table,
                           writeable=writeable)
Beispiel #10
0
def settings_index():
    form = TestMail()
    if form.validate_on_submit(
    ) and session['settings']['mail']:  # pragma: no cover
        user = current_user
        subject = _('Test mail from %(site_name)s',
                    site_name=session['settings']['site_name'])
        body = _('This test mail was sent by %(username)s',
                 username=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))
    else:
        form.receiver.data = current_user.email

    settings = session['settings']
    groups = OrderedDict([
        ('general',
         OrderedDict([(_('site name'), settings['site_name']),
                      (_('default language'),
                       app.config['LANGUAGES'][settings['default_language']]),
                      (_('default table rows'),
                       settings['default_table_rows']),
                      (_('log level'),
                       app.config['LOG_LEVELS'][int(settings['log_level'])]),
                      (_('debug mode'), uc_first(_('on'))
                       if settings['debug_mode'] else uc_first(_('off')))])),
        ('mail',
         OrderedDict([
             (_('mail'),
              uc_first(_('on')) if settings['mail'] else uc_first(_('off'))),
             (_('mail transport username'),
              settings['mail_transport_username']),
             (_('mail transport host'), settings['mail_transport_host']),
             (_('mail transport port'), settings['mail_transport_port']),
             (_('mail from email'), settings['mail_from_email']),
             (_('mail from name'), settings['mail_from_name']),
             (_('mail recipients feedback'),
              ';'.join(settings['mail_recipients_feedback']))
         ])),
        ('authentication',
         OrderedDict([
             (_('random password length'), settings['random_password_length']),
             (_('minimum password length'),
              settings['minimum_password_length']),
             (_('reset confirm hours'), settings['reset_confirm_hours']),
             (_('failed login tries'), settings['failed_login_tries']),
             (_('failed login forget minutes'),
              settings['failed_login_forget_minutes'])
         ]))
    ])
    return render_template('settings/index.html',
                           groups=groups,
                           settings=settings,
                           form=form)
Beispiel #11
0
 class NewsLetterForm(FlaskForm):
     subject = StringField('', [InputRequired()],
                           render_kw={
                               'placeholder': uc_first(_('subject')),
                               'autofocus': True
                           })
     body = TextAreaField('', [InputRequired()],
                          render_kw={'placeholder': uc_first(_('content'))})
     save = SubmitField(_('send'))
def description(self, entity):
    if not entity.description:
        return ''
    text = entity.description.replace('\r\n', '<br />')
    label = util.uc_first(_('description'))
    if hasattr(entity, 'system_type') and entity.system_type == 'source content':
        label = util.uc_first(_('content'))
    html = """<p class="description-title">{label}</p>
        <div class="description more">{description}</div>""".format(label=label, description=text)
    return html
def data_table(self, data):
    html = '<div class="data-table">'
    for key, value in data:
        if value or value == 0:
            value = util.uc_first(_('no')) if value is False else value
            value = util.uc_first(_('yes')) if value is True else value
            html += '<div class="table-row"><div>' + util.uc_first(key) + '</div>'
            html += '<div class="table-cell">' + str(value) + '</div></div>'
    html += '</div>'
    return html
def display_move_form(self, form, root_name):
    html = ''
    for field in form:
        if type(field) is TreeField:
            html += '<p>' + root_name + ' ' + str(field) + '</p>'
    html += '<p><a class="button" id="select-all">' + util.uc_first(_('select all')) + '</a>'
    html += '<a class="button" id="select-none">' + util.uc_first(_('deselect all')) + '</a></p>'
    table = {'id': 'move', 'header': ['#', util.uc_first(_('selection'))], 'data': []}
    for item in form.selection:
        table['data'].append([item, item.label.text])
    return html + util.pager(table)
 def __call__(self, field: TreeField, **kwargs: Any) -> TreeSelect:
     from openatlas.models.node import NodeMapper
     selection = ''
     selected_ids = []
     if field.data:
         field.data = field.data[0] if type(
             field.data) is list else field.data
         selection = g.nodes[int(field.data)].name
         selected_ids.append(g.nodes[int(field.data)].id)
     html = """
         <input id="{name}-button" name="{name}-button" type="text"
             class="table-select {required}" onfocus="this.blur()"
             readonly="readonly" value="{selection}" placeholder="{change_label}">
         <a id="{name}-clear" {clear_style} class="button"
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
             <div id="{name}-dialog" class="overlay-container">
                 <input class="tree-filter" id="{name}-tree-search" placeholder="{filter}">
                 <div id="{name}-tree"></div>
             </div>
         </div>
         <script>
             $(document).ready(function () {{
                 createOverlay("{name}","{title}",false,);
                 $("#{name}-tree").jstree({{
                     "core" : {{"check_callback" : true, 'data':[{tree_data}]}},
                     "search": {{"case_insensitive": true, "show_only_matches": true}},
                     "plugins" : ["search"],
                 }});
                 $("#{name}-tree").on("select_node.jstree", function (e, data) {{
                     selectFromTree("{name}", data.node.id, data.node.text);
                 }});
                 $("#{name}-tree-search").keyup(function() {{
                     if (this.value.length >= {min_chars}) {{
                         $("#{name}-tree").jstree("search", $(this).val());
                     }}
                     else if (this.value.length == 0) {{
                         $("#{name}-tree").jstree("search", $(this).val());
                         $("#{name}-tree").jstree(true).show_all();
                     }}                        
                 }});
             }});
         </script>""".format(
         filter=uc_first(_('type to search')),
         min_chars=session['settings']['minimum_jstree_search'],
         name=field.id,
         title=g.nodes[int(field.id)].name,
         change_label=uc_first(_('change')),
         clear_label=uc_first(_('clear')),
         selection=selection,
         tree_data=NodeMapper.get_tree_data(int(field.id), selected_ids),
         clear_style='' if selection else ' style="display: none;" ',
         required=' required' if field.flags.required else '')
     return super(TreeSelect, self).__call__(field, **kwargs) + html
Beispiel #16
0
def description(self, entity) -> str:
    if not entity.description:
        return ''
    text = entity.description.replace('\r\n', '<br />')
    label = util.uc_first(_('description'))
    if hasattr(entity,
               'system_type') and entity.system_type == 'source content':
        label = util.uc_first(_('content'))
    html = """<h2>{label}</h2>
        <div class="description more">{description}</div>""".format(
        label=label, description=text)
    return html
def event_view(id_):
    event = EntityMapper.get_by_id(id_)
    event.set_dates()
    tables = {
        'info': get_entity_data(event),
        'file': {'id': 'files', 'data': [],
                 'header': app.config['TABLE_HEADERS']['file'] + [_('main image')]},
        'subs': {'id': 'sub-event', 'data': [], 'header': app.config['TABLE_HEADERS']['event']},
        'source': {'id': 'source', 'data': [], 'header': app.config['TABLE_HEADERS']['source']},
        'actor': {'id': 'actor', 'data': [],
                  'header': ['actor', 'class', 'involvement', 'first', 'last', 'description']},
        'reference': {'id': 'reference', 'data': [],
                      'header': app.config['TABLE_HEADERS']['reference'] + ['pages']}}
    for link_ in event.get_links(['P11', 'P14', 'P22', 'P23']):
        first = link_.first
        if not link_.first and event.first:
            first = '<span class="inactive" style="float:right">' + str(event.first) + '</span>'
        last = link_.last
        if not link_.last and event.last:
            last = '<span class="inactive" style="float:right">' + str(event.last) + '</span>'
        data = ([link(link_.range),
                 g.classes[link_.range.class_.code].name,
                 link_.type.name if link_.type else '',
                 first, last,
                 truncate_string(link_.description)])
        if is_authorized('editor'):
            update_url = url_for('involvement_update', id_=link_.id, origin_id=event.id)
            unlink_url = url_for('link_delete', id_=link_.id, origin_id=event.id) + '#tab-actor'
            data.append('<a href="' + update_url + '">' + uc_first(_('edit')) + '</a>')
            data.append(display_remove_link(unlink_url, link_.range.name))
        tables['actor']['data'].append(data)
    profile_image_id = event.get_profile_image_id()
    for link_ in event.get_links('P67', True):
        domain = link_.domain
        data = get_base_table_data(domain)
        if domain.view_name == 'file':  # pragma: no cover
            extension = data[3].replace('.', '')
            data.append(get_profile_image_table_link(domain, event, extension, profile_image_id))
            if not profile_image_id and extension in app.config['DISPLAY_FILE_EXTENSIONS']:
                profile_image_id = domain.id
        if domain.view_name not in ['source', 'file']:
            data.append(truncate_string(link_.description))
            if is_authorized('editor'):
                update_url = url_for('reference_link_update', link_id=link_.id, origin_id=event.id)
                data.append('<a href="' + update_url + '">' + uc_first(_('edit')) + '</a>')
        if is_authorized('editor'):
            url = url_for('link_delete', id_=link_.id, origin_id=event.id)
            data.append(display_remove_link(url + '#tab-' + domain.view_name, domain.name))
        tables[domain.view_name]['data'].append(data)
    for sub_event in event.get_linked_entities('P117', True):
        tables['subs']['data'].append(get_base_table_data(sub_event))
    return render_template('event/view.html', event=event, tables=tables,
                           profile_image_id=profile_image_id)
Beispiel #18
0
def reference_insert(code, origin_id=None):
    origin = EntityMapper.get_by_id(origin_id) if origin_id else None
    form_code = 'Information Carrier' if code == 'carrier' else uc_first(code)
    form = build_form(ReferenceForm, uc_first(form_code))
    if origin:
        del form.insert_and_continue
    if form.validate_on_submit():
        return redirect(save(form, code=code, origin=origin))
    return render_template('reference/insert.html',
                           form=form,
                           code=code,
                           origin=origin)
Beispiel #19
0
def add_note_tab(entity: Entity) -> Tab:
    tab = Tab('note', entity=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'],
            f'<a href="{url_for("note_view", id_=note["id"])}">'
            f'{uc_first(_("view"))}</a>']
        tab.table.rows.append(data)
    return tab
Beispiel #20
0
def note(self, entity: Entity) -> str:
    if not current_user.settings['module_notes'] or not util.is_authorized(
            'contributor'):
        return ''  # pragma no cover
    if not entity.note:
        url = url_for('note_insert', entity_id=entity.id)
        return '<p><a href="' + url + '">+ ' + util.uc_first(
            _('note')) + '</a></p>'
    url = url_for('note_update', entity_id=entity.id)
    html = '<h2>' + util.uc_first(
        _('note')) + '</h2><p>' + entity.note + '</p>'
    html += '<a href="' + url + '">' + util.uc_first(_('edit note')) + '</a>'
    return html
Beispiel #21
0
def data_table(self, data: Iterator) -> str:
    html = '<div class="data-table">'
    for key, value in data:
        if value or value == 0:
            value = util.uc_first(_('no')) if value is False else value
            value = util.uc_first(_('yes')) if value is True else value
            html += '''
                <div class="table-row">
                    <div>{key}</div>
                    <div class="table-cell">{value}</div>
                </div>'''.format(key=util.uc_first(key), value=value)
    html += '</div>'
    return html
Beispiel #22
0
def admin_check_similar() -> str:
    form = SimilarForm()
    choices = ['source', 'event', 'actor', 'place', 'feature', 'stratigraphic unit', 'find',
               'reference', 'file']
    form.classes.choices = [(x, uc_first(_(x))) for x in choices]
    table = Table(['name', uc_first(_('count'))])
    if form.validate_on_submit():
        for sample_id, sample in EntityMapper.get_similar_named(form).items():
            html = link(sample['entity'])
            for entity in sample['entities']:
                html += '<br/>' + link(entity)
            table.rows.append([html, len(sample['entities']) + 1])
        table = table if table.rows else 'none found'
    return render_template('admin/check_similar.html', table=table, form=form)
Beispiel #23
0
 def __call__(self, field, **kwargs):
     from openatlas.models.node import NodeMapper
     selection = ''
     selected_ids = []
     if field.data:
         field.data = field.data[0] if isinstance(field.data, list) else field.data
         selection = g.nodes[int(field.data)].name
         selected_ids.append(g.nodes[int(field.data)].id)
     try:
         hierarchy_id = int(field.id)
     except ValueError:
         hierarchy_id = NodeMapper.get_hierarchy_by_name(uc_first(field.id)).id
     root = g.nodes[hierarchy_id]
     html = """
         <input id="{name}-button" name="{name}-button" type="text"
             class="table-select {required}" onfocus="this.blur()"
             readonly="readonly" value="{selection}" placeholder="{change_label}" />
         <a id="{name}-clear" {clear_style} class="button"
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
             <div id="{name}-dialog" class="overlay-container">
                 <input class="tree-filter" id="{name}-tree-search" placeholder="Filter" />
                 <div id="{name}-tree"></div>
             </div>
         </div>
         <script>
             $(document).ready(function () {{
                 createOverlay("{name}","{title}",false,);
                 $("#{name}-tree").jstree({{
                     "core" : {{"check_callback" : true, 'data':[{tree_data}]}},
                     "search": {{"case_insensitive": true, "show_only_matches": true}},
                     "plugins" : ["search"],
                 }});
                 $("#{name}-tree").on("select_node.jstree", function (e, data) {{
                     selectFromTree("{name}", data.node.id, data.node.text);
                 }});
                 $("#{name}-tree-search").keyup(function() {{
                     $("#{name}-tree").jstree("search", $(this).val());
                 }});
             }});
         </script>""".format(
         name=field.id,
         title=root.name,
         change_label=uc_first(_('change')),
         clear_label=uc_first(_('clear')),
         selection=selection,
         tree_data=NodeMapper.get_tree_data(hierarchy_id, selected_ids),
         clear_style='' if selection else ' style="display: none;" ',
         required=' required' if field.flags.required else '')
     return super(TreeSelect, self).__call__(field, **kwargs) + html
 def __call__(self, field, **kwargs):
     from openatlas.models.node import NodeMapper
     selection = ''
     selected_ids = []
     if field.data:
         field.data = field.data[0] if type(field.data) is list else field.data
         selection = g.nodes[int(field.data)].name
         selected_ids.append(g.nodes[int(field.data)].id)
     html = """
         <input id="{name}-button" name="{name}-button" type="text"
             class="table-select {required}" onfocus="this.blur()"
             readonly="readonly" value="{selection}" placeholder="{change_label}" />
         <a id="{name}-clear" {clear_style} class="button"
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
             <div id="{name}-dialog" class="overlay-container">
                 <input class="tree-filter" id="{name}-tree-search" placeholder="{filter}" />
                 <div id="{name}-tree"></div>
             </div>
         </div>
         <script>
             $(document).ready(function () {{
                 createOverlay("{name}","{title}",false,);
                 $("#{name}-tree").jstree({{
                     "core" : {{"check_callback" : true, 'data':[{tree_data}]}},
                     "search": {{"case_insensitive": true, "show_only_matches": true}},
                     "plugins" : ["search"],
                 }});
                 $("#{name}-tree").on("select_node.jstree", function (e, data) {{
                     selectFromTree("{name}", data.node.id, data.node.text);
                 }});
                 $("#{name}-tree-search").keyup(function() {{
                     if (this.value.length >= {min_chars}) {{
                         $("#{name}-tree").jstree("search", $(this).val());
                     }}
                 }});
             }});
         </script>""".format(
         filter=uc_first(_('type to search')),
         min_chars=session['settings']['minimum_jstree_search'],
         name=field.id,
         title=g.nodes[int(field.id)].name,
         change_label=uc_first(_('change')),
         clear_label=uc_first(_('clear')),
         selection=selection,
         tree_data=NodeMapper.get_tree_data(int(field.id), selected_ids),
         clear_style='' if selection else ' style="display: none;" ',
         required=' required' if field.flags.required else '')
     return super(TreeSelect, self).__call__(field, **kwargs) + html
Beispiel #25
0
def admin_orphans() -> str:
    header = ['name', 'class', 'type', 'system type', 'created', 'updated', 'description']
    tables = {'orphans': Table(header),
              'unlinked': Table(header),
              'missing_files': Table(header),
              'circular': Table(['entity']),
              'nodes': Table(['name', 'root']),
              'orphaned_files': Table(['name', 'size', 'date', 'ext'])}
    tables['circular'].rows = [[link(entity)] for entity in EntityMapper.get_circular()]
    for entity in EntityMapper.get_orphans():
        name = 'unlinked' if entity.class_.code in app.config['CODE_CLASS'].keys() else 'orphans'
        tables[name].rows.append([link(entity),
                                  link(entity.class_),
                                  entity.print_base_type(),
                                  entity.system_type,
                                  format_date(entity.created),
                                  format_date(entity.modified),
                                  truncate_string(entity.description)])
    for node in NodeMapper.get_orphans():
        tables['nodes'].rows.append([link(node), link(g.nodes[node.root[-1]])])

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

    # Get orphaned files (no corresponding entity)
    for file in os.scandir(app.config['UPLOAD_FOLDER_PATH']):
        name = file.name
        if name != '.gitignore' and splitext(file.name)[0] not in file_ids:
            confirm = ' onclick="return confirm(\'' + _('Delete %(name)s?', name=name) + '\')"'
            tables['orphaned_files'].rows.append([
                name,
                convert_size(file.stat().st_size),
                format_date(datetime.datetime.utcfromtimestamp(file.stat().st_ctime)),
                splitext(name)[1],
                '<a href="' + url_for('download_file', filename=name) + '">' + uc_first(
                    _('download')) + '</a>',
                '<a href="' + url_for('admin_file_delete', filename=name) + '" ' +
                confirm + '>' + uc_first(_('delete')) + '</a>'])
    return render_template('admin/orphans.html', tables=tables)
Beispiel #26
0
def display_move_form(self, form, root_name: str) -> str:
    html = ''
    for field in form:
        if type(field) is TreeField:
            html += '<p>' + root_name + ' ' + str(field) + '</p>'
    html += """
        <p>
            <a class="button" id="select-all">{select_all}</a>
            <a class="button" id="select-none">{deselect_all}</a>
        </p>""".format(select_all=util.uc_first(_('select all')),
                       deselect_all=util.uc_first(_('deselect all')))
    table = Table(['#', util.uc_first(_('selection'))])
    for item in form.selection:
        table.rows.append([item, item.label.text])
    return html + table.display('move')
Beispiel #27
0
def index() -> str:
    tables = {'overview': Table(paging=False, defs='[{className: "dt-body-right", targets: 1}]'),
              'bookmarks': Table(['name', 'class', 'first', 'last'],
                                 defs='[{className: "dt-body-right", targets: [2,3]}]'),
              'notes': Table(['name', 'class', 'first', 'last', _('note')],
                             defs='[{className: "dt-body-right", targets: [2,3]}]'),
              'latest': Table(['name', 'class', 'first', 'last', 'date', 'user'],
                              order='[[4, "desc"]]',
                              defs='[{className: "dt-body-right", targets: [2,3]}]')}
    if current_user.is_authenticated and hasattr(current_user, 'bookmarks'):
        for entity_id in current_user.bookmarks:
            entity = EntityMapper.get_by_id(entity_id)
            tables['bookmarks'].rows.append([link(entity), g.classes[entity.class_.code].name,
                                             entity.first, entity.last,
                                             bookmark_toggle(entity.id, True)])
        for entity_id, text in UserMapper.get_notes().items():
            entity = EntityMapper.get_by_id(entity_id)
            tables['notes'].rows.append([link(entity), g.classes[entity.class_.code].name,
                                        entity.first, entity.last, truncate_string(text)])
        for name, count in EntityMapper.get_overview_counts().items():
            if count:
                count = format_number(count) if count else ''
                url = url_for(name + '_index') if name != 'find' else url_for('place_index')
                tables['overview'].rows.append([
                    '<a href="' + url + '">' + uc_first(_(name)) + '</a>', count])
        for entity in EntityMapper.get_latest(8):
            tables['latest'].rows.append([
                link(entity), g.classes[entity.class_.code].name,
                entity.first, entity.last, format_date(entity.created),
                link(logger.get_log_for_advanced_view(entity.id)['creator'])])
    intro = ContentMapper.get_translation('intro')
    return render_template('index/index.html', intro=intro, tables=tables)
Beispiel #28
0
def reference_link_update(link_: Link, origin: Entity) -> Union[str, Response]:
    origin = Entity.get_by_id(origin.id)
    form = AddReferenceForm()
    del form.reference
    if form.validate_on_submit():
        link_.description = form.page.data
        link_.update()
        flash(_('info update'), 'info')
        tab = link_.range.class_.view if origin.class_.view == 'reference' \
            else 'reference'
        return redirect(f"{url_for('view', id_=origin.id)}#tab-{tab}")
    form.save.label.text = _('save')
    form.page.data = link_.description
    if link_.domain.class_.name == 'external_reference':
        form.page.label.text = uc_first(_('link text'))
    return render_template(
        'display_form.html',
        form=form,
        crumbs=[
            [_(origin.class_.view),
             url_for('index', view=origin.class_.view)],
            origin,
            link_.domain if link_.domain.id != origin.id else
            link_.range,
            _('edit')])
Beispiel #29
0
def hierarchy_update(id_: int) -> str:
    root = g.nodes[id_]
    if root.system:
        abort(403)
    form = build_form(HierarchyForm, 'hierarchy', root)  # type: HierarchyForm
    form.forms.choices = NodeMapper.get_form_choices(root)
    if root.value_type:
        del form.multiple
    elif root.multiple:
        form.multiple.render_kw = {'disabled': 'disabled'}
    if form.validate_on_submit():
        if form.name.data != root.name and NodeMapper.get_nodes(form.name.data):
            flash(_('error name exists'), 'error')
            return redirect(url_for('node_index') + '#tab-' + str(root.id))
        save(form, root)
        flash(_('info update'), 'info')
        return redirect(url_for('node_index') + '#tab-' + str(root.id))
    form.multiple = root.multiple
    table = Table(['form', 'count'], paging=False)
    for form_id, form_ in root.forms.items():
        url = url_for('hierarchy_remove_form', id_=root.id, remove_id=form_id)
        link = '<a href="' + url + '">' + uc_first(_('remove')) + '</a>'
        count = NodeMapper.get_form_count(root, form_id)
        table.rows.append([form_['name'], format_number(count) if count else link])
    return render_template('hierarchy/update.html', node=root, form=form, table=table,
                           forms=[form.id for form in form.forms])
def hierarchy_update(id_):
    root = g.nodes[id_]
    if root.system:
        abort(403)
    form = build_form(HierarchyForm, 'hierarchy', root)
    form.forms.choices = NodeMapper.get_form_choices(root)
    if root.value_type:
        del form.multiple
    elif root.multiple:
        form.multiple.render_kw = {'disabled': 'disabled'}
    if form.validate_on_submit():
        if form.name.data != root.name and NodeMapper.get_nodes(form.name.data):
            flash(_('error name exists'), 'error')
            return redirect(url_for('node_index') + '#tab-' + str(root.id))
        save(form, root)
        flash(_('info update'), 'info')
        return redirect(url_for('node_index') + '#tab-' + str(root.id))
    form.multiple = root.multiple
    table = {'id': 'used_forms', 'show_pager': False, 'data': [], 'sort': 'sortList: [[0, 0]]',
             'header': ['form', 'count']}
    for form_id, form_ in root.forms.items():
        url = url_for('hierarchy_remove_form', id_=root.id, remove_id=form_id)
        link = '<a href="' + url + '">' + uc_first(_('remove')) + '</a>'
        count = NodeMapper.get_form_count(root, form_id)
        table['data'].append([form_['name'], format_number(count) if count else link])
    return render_template('hierarchy/update.html', node=root, form=form, table=table,
                           forms=[form.id for form in form.forms])
Beispiel #31
0
def reference_add(id_: int, class_name: str) -> str:
    reference = EntityMapper.get_by_id(id_)
    form = getattr(openatlas.views.reference,
                   'Add' + uc_first(class_name) + 'Form')()
    if form.validate_on_submit():
        property_code = 'P128' if reference.class_.code == 'E84' else 'P67'
        entity = EntityMapper.get_by_id(getattr(form, class_name).data)
        reference.link(property_code, entity, form.page.data)
        return redirect(
            url_for('reference_view', id_=reference.id) + '#tab-' + class_name)
    if reference.system_type == 'external reference':
        form.page.label.text = uc_first(_('link text'))
    return render_template('reference/add.html',
                           reference=reference,
                           form=form,
                           class_name=class_name)
Beispiel #32
0
 def check_single_type_duplicates() -> list:
     # Find entities with multiple types attached which should be single
     from openatlas.models.node import NodeMapper
     from openatlas.models.entity import EntityMapper
     data = []
     for id_, node in g.nodes.items():
         if not node.root and not node.multiple and not node.value_type:
             node_ids = NodeMapper.get_all_sub_ids(node)
             if node_ids:
                 sql = """
                     SELECT domain_id FROM model.link
                     WHERE property_code = 'P2' AND range_id IN %(node_ids)s
                     GROUP BY domain_id HAVING COUNT(*) > 1;"""
                 g.cursor.execute(sql, {'node_ids': tuple(node_ids)})
                 debug_model['link sql'] += 1
                 for row in g.cursor.fetchall():
                     offending_nodes = []
                     entity = EntityMapper.get_by_id(row.domain_id, nodes=True)
                     for entity_node in entity.nodes:
                         if g.nodes[entity_node.root[-1]].id == node.id:
                             url = url_for('admin_delete_single_type_duplicate',
                                           entity_id=entity.id, node_id=entity_node.id)
                             offending_nodes.append(
                                 '<a href="' + url + '">' + uc_first(_('remove')) + '</a> ' +
                                 entity_node.name)
                     data.append([link(entity), entity.class_.name,
                                  link(g.nodes[id_]), '<br />'.join(offending_nodes)])
     return data
def reference_view(id_):
    reference = EntityMapper.get_by_id(id_)
    tables = {
        'info': get_entity_data(reference),
        'file': {'id': 'files', 'data': [],
                 'header': app.config['TABLE_HEADERS']['file'] + ['page'] + [_('main image')]}}
    for name in ['source', 'event', 'actor', 'place', 'feature', 'stratigraphic-unit', 'find']:
        header = app.config['TABLE_HEADERS'][name] + ['page']
        tables[name] = {'id': name, 'header': header, 'data': []}
    for link_ in reference.get_links('P67', True):
        domain = link_.domain
        data = get_base_table_data(domain)
        if is_authorized('editor'):
            url = url_for('link_delete', id_=link_.id, origin_id=reference.id) + '#tab-file'
            data.append(display_remove_link(url, domain.name))
        tables['file']['data'].append(data)
    profile_image_id = reference.get_profile_image_id()
    for link_ in reference.get_links(['P67', 'P128']):
        range_ = link_.range
        data = get_base_table_data(range_)
        data.append(truncate_string(link_.description))
        if range_.view_name == 'file':  # pragma: no cover
            ext = data[3].replace('.', '')
            data.append(get_profile_image_table_link(range_, reference, ext, profile_image_id))
            if not profile_image_id and ext in app.config['DISPLAY_FILE_EXTENSIONS']:
                profile_image_id = range_.id
        if is_authorized('editor'):
            url = url_for('reference_link_update', link_id=link_.id, origin_id=reference.id)
            data.append('<a href="' + url + '">' + uc_first(_('edit')) + '</a>')
            url = url_for('link_delete', id_=link_.id, origin_id=reference.id)
            data.append(display_remove_link(url + '#tab-' + range_.table_name, range_.name))
        tables[range_.table_name]['data'].append(data)
    return render_template('reference/view.html', reference=reference, tables=tables,
                           profile_image_id=profile_image_id)
Beispiel #34
0
    def __init__(self,
                 name: str,
                 content: Optional[str] = None,
                 table: Optional[Table] = None,
                 buttons: Optional[List[str]] = None,
                 entity: Optional['Entity'] = None) -> None:

        self.name = name
        self.content = content
        self.title = uc_first(_(name.replace('_', ' ')))
        self.entity = entity
        self.table = table if table else Table()
        id_ = None
        view = None
        class_ = None
        if entity:
            id_ = entity.id
            view = entity.class_.view
            class_ = entity.class_
            self.table.header = g.table_headers[name]
        if name == 'reference' or entity and entity.class_.view == 'reference':
            self.table.header = self.table.header + ['page']
        buttons = buttons if buttons else []
        self.add_buttons(name, buttons, view, id_, class_)
        self.buttons = buttons \
            if buttons and is_authorized('contributor') else []
Beispiel #35
0
def get_form_settings(form: Any, profile: bool = False) -> dict[str, str]:
    if isinstance(form, ProfileForm):
        return {
            _('name'): current_user.real_name,
            _('email'): current_user.email,
            _('show email'): str(
                _('on') if current_user.settings['show_email'] else _('off')),
            _('newsletter'): str(
                _('on') if current_user.settings['newsletter'] else _('off'))}
    settings = {}
    for field in form:
        if field.type in ['CSRFTokenField', 'HiddenField', 'SubmitField']:
            continue
        label = uc_first(field.label.text)
        if profile and field.name in current_user.settings:
            value = current_user.settings[field.name]
        elif field.name in g.settings:
            value = g.settings[field.name]
        else:  # pragma: no cover
            value = ''  # In case of a missing setting after an update
        if field.type in ['StringField', 'IntegerField']:
            settings[label] = value
        if field.type == 'BooleanField':  # str() needed for templates
            settings[label] = str(_('on')) if value else str(_('off'))
        if field.type == 'SelectField':
            if isinstance(value, str) and value.isdigit():
                value = int(value)
            settings[label] = dict(field.choices).get(value)
        if field.name in [
                'mail_recipients_feedback',
                'file_upload_allowed_extension']:
            settings[label] = ' '.join(value)
    return settings
Beispiel #36
0
 def check_single_type_duplicates() -> list:
     # Find entities with multiple types attached which should be single
     from openatlas.models.node import NodeMapper
     from openatlas.models.entity import EntityMapper
     data = []
     for id_, node in g.nodes.items():
         if not node.root and not node.multiple and not node.value_type:
             node_ids = NodeMapper.get_all_sub_ids(node)
             if node_ids:
                 sql = """
                     SELECT domain_id FROM model.link
                     WHERE property_code = 'P2' AND range_id IN %(node_ids)s
                     GROUP BY domain_id HAVING COUNT(*) > 1;"""
                 g.execute(sql, {'node_ids': tuple(node_ids)})
                 for row in g.cursor.fetchall():
                     offending_nodes = []
                     entity = EntityMapper.get_by_id(row.domain_id,
                                                     nodes=True)
                     for entity_node in entity.nodes:
                         if g.nodes[entity_node.root[-1]].id == node.id:
                             url = url_for(
                                 'admin_delete_single_type_duplicate',
                                 entity_id=entity.id,
                                 node_id=entity_node.id)
                             offending_nodes.append('<a href="' + url +
                                                    '">' +
                                                    uc_first(_('remove')) +
                                                    '</a> ' +
                                                    entity_node.name)
                     data.append([
                         link(entity), entity.class_.name,
                         link(g.nodes[id_]), '<br />'.join(offending_nodes)
                     ])
     return data
def index():
    tables = {
        'counts': {'id': 'overview', 'header': [], 'data': [], 'show_pager': False},
        'bookmarks': {'id': 'bookmarks', 'data': [], 'show_pager': False,
                      'header': ['name', 'class', 'first', 'last']},
        'latest': {'id': 'latest', 'data': [], 'show_pager': False,
                   'header': ['name', 'class', 'first', 'last', 'date', 'user']}}
    if current_user.is_authenticated and hasattr(current_user, 'bookmarks'):
        for entity_id in current_user.bookmarks:
            entity = EntityMapper.get_by_id(entity_id)
            tables['bookmarks']['data'].append([
                link(entity),
                g.classes[entity.class_.code].name,
                entity.first,
                entity.last,
                bookmark_toggle(entity.id, True)])
        for name, count in EntityMapper.get_overview_counts().items():
            count = format_number(count) if count else ''
            tables['counts']['data'].append([
                '<a href="' + url_for(name + '_index') + '">' + uc_first(_(name)) + '</a>', count])
        for entity in EntityMapper.get_latest(8):
            tables['latest']['data'].append([
                link(entity),
                g.classes[entity.class_.code].name,
                entity.first,
                entity.last,
                format_date(entity.created),
                link(logger.get_log_for_advanced_view(entity.id)['creator'])])
    intro = ContentMapper.get_translation('intro')
    return render_template('index/index.html', intro=intro, tables=tables)
Beispiel #38
0
class MailForm(Form):
    mail = BooleanField(uc_first(_('mail')))
    mail_transport_username = StringField(uc_first(_('mail transport username')))
    mail_transport_host = StringField(uc_first(_('mail transport host')))
    mail_transport_port = StringField(uc_first(_('mail transport port')))
    mail_from_email = StringField(uc_first(_('mail from email')), [Email()])
    mail_from_name = StringField(uc_first(_('mail from name')))
    mail_recipients_feedback = StringField(uc_first(_('mail recipients feedback')))
    save = SubmitField(uc_first(_('save')))
Beispiel #39
0
 def __call__(self, field, **kwargs):
     file_stats = None
     class_ = 'place' if field.id in ['residence', 'begins_in', 'ends_in'] else field.id
     if class_ == 'place':
         aliases = current_user.settings['table_show_aliases']
         entities = EntityMapper.get_by_system_type('place', nodes=True, aliases=aliases)
     elif class_ == 'reference':
         entities = EntityMapper.get_by_system_type('bibliography') + \
                    EntityMapper.get_by_system_type('edition') + \
                    EntityMapper.get_by_system_type('external reference')
     elif class_ == 'file':
         entities = EntityMapper.get_display_files()
         file_stats = get_file_stats()
     else:
         entities = EntityMapper.get_by_codes(class_)
     selection = ''
     table = Table(Table.HEADERS[class_])
     for entity in entities:
         # Todo: don't show self e.g. at source
         if field.data and entity.id == int(field.data):
             selection = entity.name
         data = get_base_table_data(entity, file_stats)
         data[0] = """<a onclick="selectFromTable(this,'{name}', {entity_id})">{entity_name}</a>
                     """.format(name=field.id,
                                entity_id=entity.id,
                                entity_name=truncate_string(entity.name, span=False))
         data[0] = '<br />'.join([data[0]] + [
             truncate_string(alias) for id_, alias in entity.aliases.items()])
         table.rows.append(data)
     html = """
         <input id="{name}-button" name="{name}-button" class="table-select {required}"
             type="text" placeholder="{change_label}" onfocus="this.blur()" readonly="readonly"
             value="{selection}">
         <a id="{name}-clear" class="button" {clear_style}
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
         <div id="{name}-dialog" class="overlay-container">{table}</div></div>
         <script>$(document).ready(function () {{createOverlay("{name}", "{title}");}});</script>
         """.format(name=field.id,
                    title=_(field.id.replace('_', ' ')),
                    change_label=uc_first(_('change')),
                    clear_label=uc_first(_('clear')),
                    table=table.display(field.id),
                    selection=selection,
                    clear_style='' if selection else ' style="display: none;" ',
                    required=' required' if field.flags.required else '')
     return super(TableSelect, self).__call__(field, **kwargs) + html
Beispiel #40
0
 def __call__(self, field, **kwargs):
     selection = ''
     class_ = field.id
     if class_ in ['residence', 'begins_in', 'ends_in']:
         class_ = 'place'
     header = app.config['TABLE_HEADERS'][class_]
     table = {'id': field.id, 'header': header, 'data': []}
     file_stats = None
     if class_ == 'place':
         entities = EntityMapper.get_by_system_type('place')
     elif class_ == 'reference':
         entities = EntityMapper.get_by_system_type('bibliography') + \
                    EntityMapper.get_by_system_type('edition') + \
                    EntityMapper.get_by_system_type('external reference')
     elif class_ == 'file':
         entities = EntityMapper.get_display_files()
         file_stats = get_file_stats()
     else:
         entities = EntityMapper.get_by_codes(class_)
     for entity in entities:
         # Todo: don't show self e.g. at source
         if field.data and entity.id == int(field.data):
             selection = entity.name
         data = get_base_table_data(entity, file_stats)
         data[0] = """<a onclick="selectFromTable(this,'{name}', {entity_id})">{entity_name}</a>
                     """.format(name=field.id,
                                entity_id=entity.id,
                                entity_name=truncate_string(entity.name, span=False))
         table['data'].append(data)
     html = """
         <input id="{name}-button" name="{name}-button" class="table-select {required}"
             type="text" placeholder="{change_label}" onfocus="this.blur()" readonly="readonly"
             value="{selection}">
         <a id="{name}-clear" class="button" {clear_style}
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
         <div id="{name}-dialog" class="overlay-container">{pager}</div></div>
         <script>$(document).ready(function () {{createOverlay("{name}", "{title}");}});</script>
         """.format(name=field.id,
                    title=_(field.id.replace('_', ' ')),
                    change_label=uc_first(_('change')),
                    clear_label=uc_first(_('clear')),
                    pager=pager(table),
                    selection=selection,
                    clear_style='' if selection else ' style="display: none;" ',
                    required=' required' if field.flags.required else '')
     return super(TableSelect, self).__call__(field, **kwargs) + html
Beispiel #41
0
def build_add_reference_form(class_: str) -> FlaskForm:
    class Form(FlaskForm):
        pass

    setattr(Form, class_, TableField(_(class_), [InputRequired()]))
    setattr(Form, 'page', StringField(_('page')))
    setattr(Form, 'save', SubmitField(uc_first(_('insert'))))
    return Form()
Beispiel #42
0
 def __call__(self, field, **kwargs):
     selection = ''
     class_ = field.id
     if class_ in ['residence', 'appears_first', 'appears_last']:
         class_ = 'place'
     header = app.config['TABLE_HEADERS'][class_]
     table = {'id': field.id, 'header': header, 'data': []}
     if class_ == 'place':
         entities = EntityMapper.get_by_system_type('place')
     elif class_ == 'reference':
         entities = EntityMapper.get_by_system_type('bibliography') + \
                    EntityMapper.get_by_system_type('edition')
     elif class_ == 'file':
         entities = EntityMapper.get_by_system_type('file')
     else:
         entities = EntityMapper.get_by_codes(class_)
     for entity in entities:
         # Todo: don't show self e.g. at source
         if field.data and entity.id == int(field.data):
             selection = entity.name
         data = get_base_table_data(entity)
         data[0] = """<a onclick="selectFromTable(this,'{name}', {entity_id})">{entity_name}</a>
                     """.format(
                     name=field.id,
                     entity_id=entity.id,
                     entity_name=truncate_string(entity.name, span=False))
         table['data'].append(data)
     html = """
         <input id="{name}-button" name="{name}-button" class="table-select {required}"
             type="text" placeholder="{change_label}" onfocus="this.blur()" readonly="readonly"
             value="{selection}">
         <a id="{name}-clear" class="button" {clear_style}
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
         <div id="{name}-dialog" class="overlay-container">{pager}</div></div>
         <script>$(document).ready(function () {{createOverlay("{name}", "{title}");}});</script>
         """.format(
             name=field.id,
             title=_(field.id.replace('_', ' ')),
             change_label=uc_first(_('change')),
             clear_label=uc_first(_('clear')),
             pager=pager(table),
             selection=selection,
             clear_style='' if selection else ' style="display: none;" ',
             required=' required' if field.flags.required else '')
     return super(TableSelect, self).__call__(field, **kwargs) + html
def reference_insert(code, origin_id=None):
    origin = EntityMapper.get_by_id(origin_id) if origin_id else None
    form = build_form(ReferenceForm, uc_first('Information Carrier' if code == 'carrier' else code))
    if origin:
        del form.insert_and_continue
    if form.validate_on_submit():
        return redirect(save(form, code=code, origin=origin))
    return render_template('reference/insert.html', form=form, code=code, origin=origin)
 def __call__(self, field: TreeField, **kwargs: Any) -> TreeMultiSelect:
     selection = ''
     selected_ids = []
     root = g.nodes[int(field.id)]
     if field.data:
         # Somehow field.data can be a string after a failed form validation, so fix that below
         field.data = ast.literal_eval(
             field.data) if type(field.data) is str else field.data
         for entity_id in field.data:
             selected_ids.append(entity_id)
             selection += g.nodes[entity_id].name + '<br>'
     html = """
         <span id="{name}-button" class="button">{change_label}</span>
         <div id="{name}-selection" style="text-align:left;">{selection}</div>
         <div id="{name}-overlay" class="overlay">
            <div id="{name}-dialog" class="overlay-container">
                <input class="tree-filter" id="{name}-tree-search" placeholder="{filter}">
                <div id="{name}-tree"></div>
            </div>
         </div>
         <script>
             createOverlay("{name}", "{title}", true, "tree");
             $("#{name}-tree").jstree({{
                 "core" : {{ "check_callback" : true, 'data':[{tree_data}] }},
                 "search": {{"case_insensitive": true, "show_only_matches": true}},
                 "plugins": ["search", "checkbox"],
                 "checkbox": {{"three_state": false}}
             }});
             $("#{name}-tree-search").keyup(function(){{
                 if (this.value.length >= {min_chars}) {{
                     $("#{name}-tree").jstree("search", $(this).val());
                 }}
                 else if (this.value.length == 0) {{
                     $("#{name}-tree").jstree("search", $(this).val());
                     $("#{name}-tree").jstree(true).show_all();
                 }}
             }});
         </script>""".format(
         filter=uc_first(_('type to search')),
         min_chars=session['settings']['minimum_jstree_search'],
         name=field.id,
         title=root.name,
         selection=selection,
         change_label=uc_first(_('change')),
         tree_data=NodeMapper.get_tree_data(int(field.id), selected_ids))
     return super(TreeMultiSelect, self).__call__(field, **kwargs) + html
Beispiel #45
0
def display_delete_link(self, entity) -> str:
    """ Build a link to delete an entity with a JavaScript confirmation dialog."""
    name = entity.name.replace('\'', '')
    confirm = 'onclick="return confirm(\'' + _('Delete %(name)s?',
                                               name=name) + '\')"'
    url = url_for(entity.view_name + '_delete', id_=entity.id)
    return '<a ' + confirm + ' href="' + url + '">' + util.uc_first(
        _('delete')) + '</a>'
def manual_link(self, wiki_site):
    # Creates a link to a manual page
    html = """
        <p class="manual">
            <a class="manual" href="{url}" rel="noopener" target="_blank">
                <img style="height:14px;" src="/static/images/icons/book.png" alt='' /> 
                {label}
            </a>
        </p>""".format(url='https://redmine.openatlas.eu/projects/uni/wiki/' + wiki_site,
                       label=util.uc_first(_('manual')))
    return html
def reference_add2(reference_id, class_name):
    """ Link an entity to reference coming from the reference."""
    reference_ = EntityMapper.get_by_id(reference_id)
    form = getattr(openatlas.views.reference, 'Add' + uc_first(class_name) + 'Form')()
    if form.validate_on_submit():
        property_code = 'P128' if reference_.class_.code == 'E84' else 'P67'
        entity = EntityMapper.get_by_id(getattr(form, class_name).data)
        reference_.link(property_code, entity, form.page.data)
        return redirect(url_for('reference_view', id_=reference_.id) + '#tab-' + class_name)
    return render_template('reference/add2.html', reference=reference_, form=form,
                           class_name=class_name)
 def __call__(self, field, **kwargs):
     selection = ''
     selected_ids = []
     root = g.nodes[int(field.id)]
     if field.data:
         # Somehow field.data can be a string after a failed form validation, so fix that below
         field.data = ast.literal_eval(field.data) if type(field.data) is str else field.data
         for entity_id in field.data:
             selected_ids.append(entity_id)
             selection += g.nodes[entity_id].name + '<br />'
     html = """
         <span id="{name}-button" class="button">{change_label}</span>
         <div id="{name}-selection" style="text-align:left;">{selection}</div>
         <div id="{name}-overlay" class="overlay">
            <div id="{name}-dialog" class="overlay-container">
                <input class="tree-filter" id="{name}-tree-search" placeholder="{filter}" />
                <div id="{name}-tree"></div>
            </div>
         </div>
         <script>
             createOverlay("{name}", "{title}", true, "tree");
             $("#{name}-tree").jstree({{
                 "core" : {{ "check_callback" : true, 'data':[{tree_data}] }},
                 "search": {{"case_insensitive": true, "show_only_matches": true}},
                 "plugins": ["search", "checkbox"],
                 "checkbox": {{"three_state": false}}
             }});
             $("#{name}-tree-search").keyup(function(){{
                 if (this.value.length >= {min_chars}) {{
                     $("#{name}-tree").jstree("search", $(this).val());
                 }}
             }});
         </script>""".format(
         filter=uc_first(_('type to search')),
         min_chars=session['settings']['minimum_jstree_search'],
         name=field.id,
         title=root.name,
         selection=selection,
         change_label=uc_first(_('change')),
         tree_data=NodeMapper.get_tree_data(int(field.id), selected_ids))
     return super(TreeMultiSelect, self).__call__(field, **kwargs) + html
def profile_index():
    user = current_user
    data = {'info': [
        (_('username'), user.username),
        (_('full name'), user.real_name),
        (_('email'), user.email),
        (_('show email'), uc_first(_('on')) if user.settings['show_email'] else uc_first(_('off'))),
        (_('newsletter'), uc_first(_('on')) if user.settings['newsletter'] else uc_first(_('off')))
    ]}
    form = DisplayForm()
    if form.validate_on_submit():
        user.settings['language'] = form.language.data
        user.settings['theme'] = form.theme.data
        user.settings['table_rows'] = form.table_rows.data
        user.settings['layout'] = form.layout.data
        g.cursor.execute('BEGIN')
        try:
            user.update_settings()
            g.cursor.execute('COMMIT')
            session['language'] = form.language.data
            flash(_('info update'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        return redirect(url_for('profile_index'))

    form.language.data = user.settings['language']
    form.theme.data = user.settings['theme']
    form.table_rows.data = user.settings['table_rows']
    form.layout.data = user.settings['layout']
    data['display'] = [
        (form.language.label, form.language),
        (str(form.table_rows.label) +
            display_tooltip(form.table_rows.description), form.table_rows),
        (str(form.layout.label) + display_tooltip(form.layout.description), form.layout)]
    return render_template('profile/index.html', data=data, form=form)
def content_index():
    header = ['name']
    for language in app.config['LANGUAGES'].keys():
        header.append(language)
    header.append('text')
    table_content = {'id': 'content', 'header': header, 'data': []}
    for item, languages in ContentMapper.get_content().items():
        url = url_for('content_view', item=item)
        content = ['<a href="' + url + '">' + util.uc_first(_(item)) + '</a>']
        html_ok = '<img src="/static/images/icons/dialog-apply.png" alt="ok" \>'
        for language in app.config['LANGUAGES'].keys():
            content.append(html_ok if languages[language] else '')
        content.append(languages[session['language']])
        table_content['data'].append(content)
    return render_template('content/index.html', table_content=table_content)
def search_index():
    classes = ['source', 'event', 'actor', 'place', 'reference']
    form = SearchForm()
    form.classes.choices = [(x, uc_first(_(x))) for x in classes]
    form.classes.default = classes
    form.classes.process(request.form)
    table = {'data': []}
    if request.method == 'POST' and 'global-term' in request.form and request.form['global-term']:
        # Coming from global search
        form.term.data = request.form['global-term']
        form.classes.data = classes
        table = build_search_table(form)
    if form.validate_on_submit():
        table = build_search_table(form)
    return render_template('search/index.html', form=form, table=table)
def display_menu(self, origin):
    """ Returns html with the menu and mark appropriate item as selected."""
    html = ''
    if current_user.is_authenticated:
        selected = origin.view_name if origin else ''
        items = ['overview', 'source', 'event', 'actor', 'place', 'reference', 'types', 'admin']
        for item in items:
            if selected:
                css = 'active' if item == selected else ''
            else:
                css = 'active' if request.path.startswith('/' + item) or \
                                  (item == 'overview' and request.path == '/') else ''
            html += '<div class="{css}"><a href="/{item}">{label}</a></div>'.format(
                css=css, item=item, label=util.uc_first(_(item)))
    return html
Beispiel #53
0
 def print_base_type(self):
     from openatlas.models.node import NodeMapper
     if not self.view_name or self.view_name == 'actor':  # actors have no base type
         return ''
     root_name = self.view_name.title()
     if self.view_name == 'reference':
         root_name = self.system_type.title()
     elif self.view_name == 'file':
         root_name = 'License'
     elif self.view_name == 'place':
         root_name = uc_first(self.system_type)
         if self.system_type == 'stratigraphic unit':
             root_name = 'Stratigraphic Unit'
     root_id = NodeMapper.get_hierarchy_by_name(root_name).id
     for node in self.nodes:
         if node.root and node.root[-1] == root_id:
             return node.name
     return ''
def source_view(id_):
    source = EntityMapper.get_by_id(id_)
    tables = {
        'info': get_entity_data(source),
        'text': {'id': 'translation', 'data': [], 'header': ['text', 'type', 'content']},
        'file': {'id': 'files', 'data': [],
                 'header': app.config['TABLE_HEADERS']['file'] + [_('main image')]},
        'reference': {'id': 'source', 'data': [],
                      'header': app.config['TABLE_HEADERS']['reference'] + ['page']}}
    for text in source.get_linked_entities('P73'):
        tables['text']['data'].append([
            link(text),
            next(iter(text.nodes)).name if text.nodes else '',
            truncate_string(text.description)])
    for name in ['actor', 'event', 'place', 'feature', 'stratigraphic-unit', 'find']:
        tables[name] = {'id': name, 'header': app.config['TABLE_HEADERS'][name], 'data': []}
    for link_ in source.get_links('P67'):
        range_ = link_.range
        data = get_base_table_data(range_)
        if is_authorized('editor'):
            url = url_for('link_delete', id_=link_.id, origin_id=source.id)
            data.append(display_remove_link(url + '#tab-' + range_.table_name, range_.name))
        tables[range_.table_name]['data'].append(data)
    profile_image_id = source.get_profile_image_id()
    for link_ in source.get_links(['P67', 'P128'], True):
        domain = link_.domain
        data = get_base_table_data(domain)
        if domain.view_name == 'file':  # pragma: no cover
            extension = data[3].replace('.', '')
            data.append(get_profile_image_table_link(domain, source, extension, profile_image_id))
            if not profile_image_id and extension in app.config['DISPLAY_FILE_EXTENSIONS']:
                profile_image_id = domain.id
        if domain.view_name not in ['file']:
            data.append(link_.description)
            if is_authorized('editor'):
                update_url = url_for('reference_link_update', link_id=link_.id, origin_id=source.id)
                data.append('<a href="' + update_url + '">' + uc_first(_('edit')) + '</a>')
        if is_authorized('editor'):
            url = url_for('link_delete', id_=link_.id, origin_id=source.id)
            data.append(display_remove_link(url + '#tab-' + domain.view_name, domain.name))
        tables[domain.view_name]['data'].append(data)
    return render_template('source/view.html', source=source, tables=tables,
                           profile_image_id=profile_image_id)
Beispiel #55
0
 def __call__(self, field, **kwargs):
     if field.data and type(field.data) is str:
         field.data = ast.literal_eval(field.data)
     selection = ''
     class_ = field.id if field.id != 'given_place' else 'place'
     table = Table(Table.HEADERS[class_])
     # Make checkbox column sortable and show selected on top
     table.headers = 'headers:{' + str(len(table.header)) + ':{sorter:"checkbox"}},'
     table.sort = 'sortList:[[' + str(len(table.header)) + ', 0],[0, 0]],'
     if class_ == 'place':
         aliases = current_user.settings['table_show_aliases']
         entities = EntityMapper.get_by_system_type('place', nodes=True, aliases=aliases)
     else:
         entities = EntityMapper.get_by_codes(class_)
     for entity in entities:
         selection += entity.name + '<br/>' if field.data and entity.id in field.data else ''
         data = get_base_table_data(entity)
         data[0] = re.sub(re.compile('<a.*?>'), '', data[0])  # Remove links
         data.append("""<input type="checkbox" id="{id}" {checked} value="{name}"
             class="multi-table-select">""".format(
             id=str(entity.id),
             name=entity.name,
             checked='checked = "checked"' if field.data and entity.id in field.data else ''))
         table.rows.append(data)
     html = """
         <span id="{name}-button" class="button">{change_label}</span><br />
         <div id="{name}-selection" class="selection" style="text-align:left;">{selection}</div>
         <div id="{name}-overlay" class="overlay">
         <div id="{name}-dialog" class="overlay-container">{table}</div></div>
         <script>
             $(document).ready(function () {{createOverlay("{name}", "{title}", true);}});
         </script>""".format(name=field.id,
                             change_label=uc_first(_('change')),
                             title=_(field.id.replace('_', ' ')),
                             selection=selection,
                             table=table.display(field.id, remove_rows=False))
     return super(TableMultiSelect, self).__call__(field, **kwargs) + html
 def __call__(self, field, **kwargs):
     if field.data and type(field.data) is str:
         field.data = ast.literal_eval(field.data)
     selection = ''
     class_ = field.id if field.id != 'given_place' else 'place'
     table = {'id': field.id, 'header': app.config['TABLE_HEADERS'][class_], 'data': []}
     # Make checkbox column sortable and show selected on top
     table['headers'] = 'headers: { ' + str(len(table['header'])) + ': { sorter: "checkbox" } }'
     table['sort'] = 'sortList: [[' + str(len(table['header'])) + ',0],[0,0]]'
     if class_ == 'place':
         entities = EntityMapper.get_by_system_type('place')
     else:
         entities = EntityMapper.get_by_codes(class_)
     for entity in entities:
         selection += entity.name + '<br/>' if field.data and entity.id in field.data else ''
         data = get_base_table_data(entity)
         data[0] = truncate_string(entity.name)  # Replace entity link with entity name
         html = """<input type="checkbox" id="{id}" {checked} value="{name}"
             class="multi-table-select">""".format(
                 id=str(entity.id), name=entity.name,
                 checked='checked = "checked"' if field.data and entity.id in field.data else '')
         data.append(html)
         table['data'].append(data)
     html = """
         <span id="{name}-button" class="button">{change_label}</span><br />
         <div id="{name}-selection" class="selection" style="text-align:left;">{selection}</div>
         <div id="{name}-overlay" class="overlay">
         <div id="{name}-dialog" class="overlay-container">{pager}</div></div>
         <script>
             $(document).ready(function () {{createOverlay("{name}", "{title}", true);}});
         </script>""".format(
             name=field.id,
             change_label=uc_first(_('change')),
             title=_(field.id.replace('_', ' ')),
             selection=selection,
             pager=pager(table, remove_rows=False))
     return super(TableMultiSelect, self).__call__(field, **kwargs) + html
def actor_view(id_):
    actor = EntityMapper.get_by_id(id_)
    actor.set_dates()
    objects = []
    info = get_entity_data(actor)
    residence = actor.get_linked_entity('P74')
    if residence:
        object_ = residence.get_linked_entity('P53', True)
        objects.append(object_)
        info.append((uc_first(_('residence')), link(object_)))
    first = actor.get_linked_entity('OA8')
    if first:
        object_ = first.get_linked_entity('P53', True)
        objects.append(object_)
        info.append((uc_first(_('appears first')), link(object_)))
    last = actor.get_linked_entity('OA9')
    if last:
        object_ = last.get_linked_entity('P53', True)
        objects.append(object_)
        info.append((uc_first(_('appears last')), link(object_)))
    tables = {
        'info': info,
        'file': {'id': 'files', 'data': [],
                 'header': app.config['TABLE_HEADERS']['file'] + [_('main image')]},
        'source': {'id': 'source', 'data': [], 'header': app.config['TABLE_HEADERS']['source']},
        'reference': {'id': 'reference', 'data': [],
                      'header': app.config['TABLE_HEADERS']['reference'] + ['pages']},
        'event': {'id': 'event', 'data': [],
                  'header': ['event', 'class', 'involvement', 'first', 'last', 'description']},
        'relation': {'id': 'relation', 'data': [], 'sort': 'sortList:[[0,0]]',
                     'header': ['relation', 'actor', 'first', 'last', 'description']},
        'member_of': {'id': 'member_of', 'data': [],
                      'header': ['member of', 'function', 'first', 'last', 'description']}}
    profile_image_id = actor.get_profile_image_id()
    for link_ in actor.get_links('P67', True):
        domain = link_.domain
        data = get_base_table_data(domain)
        if domain.view_name == 'file':
            extension = data[3].replace('.', '')
            data.append(get_profile_image_table_link(domain, actor, extension, profile_image_id))
            if not profile_image_id and extension in app.config['DISPLAY_FILE_EXTENSIONS']:
                profile_image_id = domain.id
        if domain.view_name not in ['source', 'file']:
            data.append(truncate_string(link_.description))
            if is_authorized('editor'):
                update_url = url_for('reference_link_update', link_id=link_.id, origin_id=actor.id)
                data.append('<a href="' + update_url + '">' + uc_first(_('edit')) + '</a>')
        if is_authorized('editor'):
            url = url_for('link_delete', id_=link_.id, origin_id=actor.id)
            data.append(display_remove_link(url + '#tab-' + domain.view_name, domain.name))
        tables[domain.view_name]['data'].append(data)

    # Todo: Performance - getting every place of every object for every event is very costly
    for link_ in actor.get_links(['P11', 'P14', 'P22', 'P23'], True):
        event = link_.domain
        first = link_.first
        place = event.get_linked_entity('P7')
        if place:
            objects.append(place.get_linked_entity('P53', True))
        if not link_.first and event.first:
            first = '<span class="inactive" style="float:right">' + str(event.first) + '</span>'
        last = link_.last
        if not link_.last and event.last:
            last = '<span class="inactive" style="float:right">' + str(event.last) + '</span>'
        data = ([link(event),
                 g.classes[event.class_.code].name,
                 link_.type.name if link_.type else '',
                 first,
                 last,
                 truncate_string(link_.description)])
        if is_authorized('editor'):
            update_url = url_for('involvement_update', id_=link_.id, origin_id=actor.id)
            unlink_url = url_for('link_delete', id_=link_.id, origin_id=actor.id) + '#tab-event'
            data.append('<a href="' + update_url + '">' + uc_first(_('edit')) + '</a>')
            data.append(display_remove_link(unlink_url, link_.domain.name))
        tables['event']['data'].append(data)
    for link_ in actor.get_links('OA7') + actor.get_links('OA7', True):
        if actor.id == link_.domain.id:
            type_ = link_.type.get_name_directed() if link_.type else ''
            related = link_.range
        else:
            type_ = link_.type.get_name_directed(True) if link_.type else ''
            related = link_.domain
        data = ([type_, link(related), link_.first, link_.last, truncate_string(link_.description)])
        if is_authorized('editor'):
            update_url = url_for('relation_update', id_=link_.id, origin_id=actor.id)
            unlink_url = url_for('link_delete', id_=link_.id, origin_id=actor.id) + '#tab-relation'
            data.append('<a href="' + update_url + '">' + uc_first(_('edit')) + '</a>')
            data.append(display_remove_link(unlink_url, related.name))
        tables['relation']['data'].append(data)
    for link_ in actor.get_links('P107', True):
        data = ([link(link_.domain),
                 link_.type.name if link_.type else '',
                 link_.first,
                 link_.last,
                 truncate_string(link_.description)])
        if is_authorized('editor'):
            update_url = url_for('member_update', id_=link_.id, origin_id=actor.id)
            unlink_url = url_for('link_delete', id_=link_.id, origin_id=actor.id) + '#tab-member-of'
            data.append('<a href="' + update_url + '">' + uc_first(_('edit')) + '</a>')
            data.append(display_remove_link(unlink_url, link_.domain.name))
        tables['member_of']['data'].append(data)
    if actor.class_.code in app.config['CLASS_CODES']['group']:
        tables['member'] = {'id': 'member', 'data': [],
                            'header': ['member', 'function', 'first', 'last', 'description']}
        for link_ in actor.get_links('P107'):
            data = ([link(link_.range),
                     link_.type.name if link_.type else '',
                     link_.first,
                     link_.last,
                     truncate_string(link_.description)])
            if is_authorized('editor'):
                update_url = url_for('member_update', id_=link_.id, origin_id=actor.id)
                unlink_url = url_for('link_delete', id_=link_.id,
                                     origin_id=actor.id) + '#tab-member'
                data.append('<a href="' + update_url + '">' + uc_first(_('edit')) + '</a>')
                data.append(display_remove_link(unlink_url, link_.range.name))
            tables['member']['data'].append(data)
    gis_data = GisMapper.get_all(objects) if objects else None
    if gis_data and gis_data['gisPointSelected'] == '[]':
        gis_data = None
    return render_template('actor/view.html', actor=actor, tables=tables, gis_data=gis_data,
                           profile_image_id=profile_image_id)
def display_form(self, form, form_id=None, for_persons=False):
    multipart = 'enctype="multipart/form-data"' if hasattr(form, 'file') else ''
    if 'update' in request.path:
        if hasattr(form, 'save') and hasattr(form.save, 'label'):
            form.save.label.text = _('save')
        if hasattr(form, 'insert_and_continue'):
            del form.insert_and_continue
    id_attribute = ' id="' + form_id + '" ' if form_id else ''
    html = {'main': '', 'types': '', 'value_types': '', 'header': '', 'footer': ''}

    def display_value_type_fields(subs, html_=''):
        for sub_id in subs:
            sub = g.nodes[sub_id]
            field_ = getattr(form, str(sub_id))
            html_ += """
                <div class="table-row value-type-switch">
                    <div><label>{label}</label> {tooltip}</div>
                    <div class="table-cell">{field}</div>
                </div>
            """.format(label=sub.name, tooltip=display_tooltip(sub.description),
                       field=field_(class_='value-type'))
            html_ += display_value_type_fields(sub.subs)
        return html_

    for field in form:
        if type(field) is ValueFloatField:
            continue
        class_ = 'required' if field.flags.required else ''
        class_ += ' integer' if type(field) is IntegerField else ''
        for validator in field.validators:
            class_ += ' email' if type(validator) is Email else ''
        errors = ''
        for error in field.errors:
            errors += util.uc_first(error)
        if field.type in ['TreeField', 'TreeMultiField']:
            hierarchy_id = int(field.id)
            node = g.nodes[hierarchy_id]
            label = node.name
            if node.name in app.config['BASE_TYPES']:
                label = util.uc_first(_('type'))
            if field.label.text == 'super':
                label = util.uc_first(_('super'))
            if node.value_type and 'is_node_form' not in form:
                html['value_types'] += """
                        <div class="table-row value-type-switch">
                            <div></div>
                            <div class="table-cell">
                                <label style="font-weight:bold;">{label}</label> {tooltip}
                            </div>
                        </div>
                    """.format(label=label, tooltip=display_tooltip(node.description))
                html['value_types'] += display_value_type_fields(node.subs)
                continue
            else:
                type_field = """
                    <div class="table-row">
                        <div><label>{label}</label> {info}</div>
                        <div class="table-cell">{field}</div>
                    </div>
                """.format(label=label, field=str(field(class_=class_)) + errors,
                           info='' if 'is_node_form' in form else display_tooltip(node.description))
                if node.name in app.config['BASE_TYPES']:  # base type should be above other fields
                    html['types'] = type_field + html['types']
                else:
                    html['types'] += type_field
                continue
        if field.type in ['CSRFTokenField', 'HiddenField']:
            html['header'] += str(field)
            continue
        field.label.text = util.uc_first(field.label.text)
        field.label.text += ' *' if field.flags.required and form_id != 'login-form' else ''
        if field.id == 'description':
            html['footer'] += '<br />{label}<br />{text}<br />'.format(
                label=field.label, text=field(class_=class_))
            continue
        if field.type == 'SubmitField':
            html['footer'] += str(field)
            continue
        if field.id.split('_', 1)[0] == 'date':  # if it's a date field use a function to add dates
            if field.id == 'date_begin_year':
                html['footer'] += util.add_dates_to_form(form, for_persons)
            continue
        field.label.text += display_tooltip(field.description)
        errors = ' <span class="error">' + errors + ' </span>' if errors else ''
        if field.id in ('file', 'name'):
            html['header'] += '<div class="table-row"><div>' + str(field.label) + '</div>'
            html['header'] += '<div class="table-cell">' + str(field(class_=class_)) + errors
            html['header'] += '</div></div>'
            continue
        html['main'] += '<div class="table-row"><div>' + str(field.label) + '</div>'
        html['main'] += '<div class="table-cell">' + str(field(class_=class_)).replace('> ', '>')
        html['main'] += errors + '</div></div>'

    html_all = '<form method="post"' + id_attribute + ' ' + multipart + '>'
    html_all += '<div class="data-table">'
    if html['value_types']:
        values_html = """
            <div class="table-row">
                <div>
                    <label>{values}</label>
                </div>
                <div class="table-cell value-type-switcher">
                    <span id="value-type-switcher" class="button">{show}</span>
                </div>
            </div>""".format(values=util.uc_first(_('values')), show=util.uc_first(_('show')))
        html['value_types'] = values_html + html['value_types']
    html_all += html['header'] + html['types'] + html['main'] + html['value_types'] + html['footer']
    html_all += '</div></form>'
    return html_all
def display_delete_link(self, entity):
    """ Build a link to delete an entity with a JavaScript confirmation dialog."""
    name = entity.name.replace('\'', '')
    confirm = 'onclick="return confirm(\'' + _('Delete %(name)s?', name=name) + '\')"'
    url = url_for(entity.view_name + '_delete', id_=entity.id)
    return '<a ' + confirm + ' href="' + url + '">' + util.uc_first(_('delete')) + '</a>'
def uc_first(self, string):
    return util.uc_first(string)