def build_table_form(class_name: str, linked_entities: Iterator) -> str: """ Returns a form with a list of entities with checkboxes""" from openatlas.models.entity import EntityMapper table = Table(Table.HEADERS[class_name] + ['']) linked_ids = [entity.id for entity in linked_entities] file_stats = get_file_stats() if class_name == 'file' else None if class_name == 'file': entities = EntityMapper.get_by_system_type('file', nodes=True) elif class_name == 'place': entities = EntityMapper.get_by_system_type('place', nodes=True, aliases=True) else: entities = EntityMapper.get_by_codes(class_name) for entity in entities: if entity.id in linked_ids: continue # Don't show already linked entries input_ = '<input id="selection-{id}" name="values" type="checkbox" value="{id}">'.format( id=entity.id) table.rows.append(get_base_table_data(entity, file_stats) + [input_]) if not table.rows: return uc_first(_('no entries')) return """ <form class="table" id="checkbox-form" method="post"> <input id="csrf_token" name="csrf_token" type="hidden" value="{token}"> <input id="checkbox_values" name="checkbox_values" type="hidden"> {table} <button name="form-submit" id="form-submit" type="submit">{add}</button> </form>""".format(add=uc_first(_('add')), token=generate_csrf(), table=table.display(class_name))
def build_table_form(class_: str, linked_entities: List[Entity]) -> str: """ Returns a form with a list of entities with checkboxes.""" if class_ == 'file': entities = Entity.get_by_class('file', nodes=True) elif class_ == 'place': entities = Entity.get_by_class('place', nodes=True, aliases=True) else: entities = Entity.get_by_view(class_) linked_ids = [entity.id for entity in linked_entities] table = Table([''] + g.table_headers[class_], order=[[1, 'asc']]) file_stats = get_file_stats() if class_ == 'file' else None 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([input_] + get_base_table_data(entity, file_stats)) 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} <input id="save" class="{class_}" name="save" type="submit" value="{link}"> </form>""".format(link=uc_first(_('link')), token=generate_csrf(), class_=app.config['CSS']['button']['primary'], table=table.display(class_))
def file_index() -> str: table = Table(['date'] + Table.HEADERS['file']) file_stats = get_file_stats() for entity in EntityMapper.get_by_system_type('file', nodes=True): date = 'N/A' if entity.id in file_stats: date = format_date( datetime.datetime.utcfromtimestamp( file_stats[entity.id]['date'])) table.rows.append([ date, link(entity), entity.print_base_type(), convert_size(file_stats[entity.id]['size']) if entity.id in file_stats else 'N/A', file_stats[entity.id]['ext'] if entity.id in file_stats else 'N/A', truncate_string(entity.description) ]) if os.name != "posix": # pragma: no cover # For other operating systems e.g. Windows, we would need adaptions here return render_template('file/index.html', table=table, disk_space_values={}) statvfs = os.statvfs(app.config['UPLOAD_FOLDER_PATH']) disk_space = statvfs.f_frsize * statvfs.f_blocks free_space = statvfs.f_frsize * statvfs.f_bavail # Available space without reserved blocks disk_space_values = { 'total': convert_size(statvfs.f_frsize * statvfs.f_blocks), 'free': convert_size(statvfs.f_frsize * statvfs.f_bavail), 'percent': 100 - math.ceil(free_space / (disk_space / 100)) } return render_template('file/index.html', table=table, disk_space_values=disk_space_values)
def before_request() -> None: from openatlas.models.model import CidocClass, CidocProperty from openatlas.models.node import Node from openatlas.models.settings import Settings from openatlas.models.reference_system import ReferenceSystem if request.path.startswith('/static'): # pragma: no cover return # Avoid overhead for files if not using Apache with static alias open_connection(app.config) session['settings'] = Settings.get_settings() session['language'] = get_locale() g.cidoc_classes = CidocClass.get_all() g.properties = CidocProperty.get_all() from openatlas.models import system g.table_headers = system.get_table_headers() g.classes = system.get_system_classes() g.view_class_mapping = system.view_class_mapping g.class_view_mapping = system.get_class_view_mapping() g.nodes = Node.get_all_nodes() g.reference_systems = ReferenceSystem.get_all() g.file_stats = get_file_stats() # Set max file upload in MB app.config['MAX_CONTENT_LENGTH'] = \ session['settings']['file_upload_max_size'] * 1024 * 1024 if request.path.startswith('/api/'): ip = request.environ.get('HTTP_X_REAL_IP', request.remote_addr) if not current_user.is_authenticated \ and not session['settings']['api_public'] \ and ip not in app.config['ALLOWED_IPS']: raise AccessDeniedError # pragma: no cover
def admin_logo(id_: Optional[int] = None) -> Union[str, Response]: if session['settings']['logo_file_id']: abort(418) # pragma: no cover - Logo already set if id_: Settings.set_logo(id_) return redirect(url_for('admin_index') + '#tab-file') file_stats = get_file_stats() table = Table([''] + g.table_headers['file'] + ['date']) for entity in Entity.get_display_files(): date = 'N/A' if entity.id in file_stats: date = format_date( datetime.datetime.utcfromtimestamp( file_stats[entity.id]['date'])) table.rows.append([ link(_('set'), url_for('admin_logo', id_=entity.id)), truncate(entity.name), entity.print_standard_type(), convert_size(file_stats[entity.id]['size']) if entity.id in file_stats else 'N/A', file_stats[entity.id]['ext'] if entity.id in file_stats else 'N/A', entity.description, date ]) return render_template( 'admin/logo.html', table=table, title=_('logo'), crumbs=[[_('admin'), url_for('admin_index') + '#tab-files'], _('logo')])
def get_table(view: str) -> Table: table = Table(g.table_headers[view]) if view == 'file': table.header = ['date'] + table.header file_stats = get_file_stats() for entity in Entity.get_by_class('file', nodes=True): date = 'N/A' if entity.id in file_stats: date = format_date( datetime.datetime.utcfromtimestamp( file_stats[entity.id]['date'])) table.rows.append([ date, link(entity), entity.print_standard_type(), convert_size(file_stats[entity.id]['size']) if entity.id in file_stats else 'N/A', file_stats[entity.id]['ext'] if entity.id in file_stats else 'N/A', entity.description ]) elif view == 'reference_system': for system in g.reference_systems.values(): table.rows.append([ link(system), system.count if system.count else '', external_url(system.website_url), external_url(system.resolver_url), system.placeholder, link(g.nodes[system.precision_default_id]) if system.precision_default_id else '', system.description ]) else: classes = ['place'] if view == 'place' else g.view_class_mapping[view] entities = Entity.get_by_class(classes, nodes=True) table.rows = [get_base_table_data(item) for item in entities] return table
def get_display_files() -> List[Entity]: entities = [] if not g.file_stats: g.file_stats = get_file_stats() for row in Db.get_by_class('file', nodes=True): ext = g.file_stats[row['id']]['ext'] \ if row['id'] in g.file_stats else 'N/A' if ext in app.config['DISPLAY_FILE_EXTENSIONS']: entities.append(Entity(row)) return entities
def delete_orphaned_resized_images() -> None: from openatlas.util.util import get_file_stats if not g.file_stats: g.file_stats = get_file_stats() for size in app.config['IMAGE_SIZE'].values(): p = Path(app.config['RESIZED_IMAGES']) / size for file in p.glob('**/*'): file_name = file.name.rsplit('.', 1)[0].lower() if not file_name.isdigit() \ or int(file_name) not in g.file_stats: file.unlink() # pragma: no cover
def create_resized_images() -> None: from openatlas.models.entity import Entity from openatlas.util.util import get_file_stats if not g.file_stats: g.file_stats = get_file_stats() for entity in Entity.get_by_class('file'): if entity.id in g.file_stats \ and g.file_stats[entity.id]['ext'] \ in app.config['ALLOWED_IMAGE_EXT']: ImageProcessing.resize_image( f"{entity.id}{g.file_stats[entity.id]['ext']}")
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
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
def get_table(view: str) -> Table: header = g.table_headers[view] if view == 'file': header = ['date'] + header if session['settings']['image_processing'] \ and current_user.settings['table_show_icons']: header.insert(1, _('icon')) table = Table(header) if view == 'file': if not g.file_stats: g.file_stats = get_file_stats() for entity in Entity.get_by_class('file', nodes=True): date = 'N/A' if entity.id in g.file_stats: date = format_date( datetime.datetime.utcfromtimestamp( g.file_stats[entity.id]['date'])) data = [ date, link(entity), link(entity.standard_type), g.file_stats[entity.id]['size'] if entity.id in g.file_stats else 'N/A', g.file_stats[entity.id]['ext'] if entity.id in g.file_stats else 'N/A', entity.description ] if session['settings']['image_processing'] \ and current_user.settings['table_show_icons']: data.insert(1, file_preview(entity.id)) table.rows.append(data) elif view == 'reference_system': for system in g.reference_systems.values(): table.rows.append([ link(system), system.count if system.count else '', external_url(system.website_url), external_url(system.resolver_url), system.placeholder, link(g.nodes[system.precision_default_id]) if system.precision_default_id else '', system.description ]) else: classes = 'place' if view == 'place' else g.view_class_mapping[view] entities = Entity.get_by_class(classes, nodes=True, aliases=True) table.rows = [get_base_table_data(entity) for entity in entities] return table
def __call__(self, field, **kwargs): file_stats = None place_fields = [ 'residence', 'begins_in', 'ends_in', 'place_to', 'place_from' ] class_ = 'place' if field.id in place_fields 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_]) # Table definitions (aligning) if class_ == 'event': table.defs += '[{className: "dt-body-right", targets: [3,4]}]' elif class_ in ['actor', 'group', 'feature', 'place']: table.defs += '[{className: "dt-body-right", targets: [2,3]}]' 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