def format_list(nodes, italics=True, show_label=True): ''' add "and" and commas to a list ''' items = [helpers.unthe(n['props']['identifier']) for n in nodes] if not items: return '' if len(items) == 2: if italics: result = '_%s_ and _%s_' % (items[0], items[1]) else: result = '%s and %s' % (items[0], items[1]) elif len(items) > 1: if italics: result = '_%s_, and _%s_' % ('_, _'.join(items[0:-1]), items[-1]) else: result = '%s, and %s' % (', '.join(items[0:-1]), items[-1]) else: result = '_%s_' % items[0] if italics else '%s' % items[0] label = helpers.pluralize(nodes[0]['label']) \ if len(items) > 1 else nodes[0]['label'] return 'the %s %s' % (label, result) if show_label else result
def item(label, uid): ''' generic page for an item :param label: the desired neo4j label :param uid: the human-readable uid of the node :return: customized data for this label rendered item page template ''' # load and validate url data label = helpers.sanitize(label) if not graph.validate_label(label): logging.error('Invalid label %s', label) return render_template(request.url, 'label-404.html', labels=graph.get_labels()) try: data = helpers.get_node(uid) except NameError: items = graph.get_all(label) return render_template(request.url, 'item-404.html', items=items['nodes'], search=graph.search(uid)['nodes'], label=label) node = data['node'] rels = data['rels'] # ----- page header/metadata title = node['props']['identifier'] # ----- formatted data switch = { 'parent:book': grimoire_item, 'parent:entity': entity_item, 'art': art_item, 'language': language_item, 'edition': edition_item, 'publisher': publisher_item, 'editor': editor_item, 'default': generic_item, 'spell': spell_item, 'talisman': spell_item, 'parent:ingredient': ingredient_item, 'outcome': outcome_item } key = node['parent_label'] if node['parent_label'] in switch else \ (label if label in switch else 'default') item_data = switch[key](node, rels) item_data['rels'] = helpers.combine_rels(item_data['rels']) # ----- sidebar sidebar = [] related = graph.related(uid, label) if related['nodes']: sidebar = [{'title': 'Similar %s' % \ helpers.capitalize_filter(helpers.pluralize(label)), 'data': related['nodes']}] sidebar += get_others(data['rels'], node) if not item_data['content'] and not item_data['excerpts']: item_data['content'] = 'The %s "%s."' % \ (helpers.format_filter(label), helpers.unthe(title)) max_main_length = max([len(i['data']) for i in item_data['main']] + [0]) default_collapse = len(item_data['main']) > 2 or max_main_length > 30 return render_template(request.url, 'item.html', data=item_data, title=title, label=label, sidebar=sidebar, default_collapse=default_collapse)
def generic_item(node, rels): ''' standard item processing :param node: the item node :param rels: default relationship list :return: customized data for this label ''' def format_field(field): ''' deal with array data ''' if isinstance(field, list): return [{'text': i} for i in field] return [{'text': field}] data = {'id': node['id']} try: data['content'] = markdown(node['props']['content']) except AttributeError: data['content'] = '' # -- build timeline events = extract_rel_list(rels, 'event', 'end') for event in events: event['props']['relevant'] = True related = graph.get_related_events(node['props']['uid']) related = zip(related['nodes'], related['rels']) for rel_item in related: event = rel_item[0] this = 'this %s' % helpers.format_filter(node['label']) rel_type = helpers.format_filter(rel_item[1]['type']) if rel_item[1]['start']['props']['uid'] == node['props']['uid']: note = '(%s %s %s)' % \ (this, rel_type, helpers.unthe(rel_item[1]['end']['props']['identifier'])) else: note = '(%s %s)' % (rel_type, this) event['note'] = note events.append(event) data['timeline'], data['start_date'], \ data['end_date'] = build_timeline(events) excerpts = extract_rel_list_by_type(rels, 'excerpt', 'end') for excerpt in excerpts: try: excerpt['props']['content'] = markdown(excerpt['props']['content']) except AttributeError: pass data['excerpts'] = excerpts data['images'] = extract_rel_list_by_type(rels, 'image', 'end', label='image') # remove special node types from relationship lists remove = ['excerpt', 'event', 'image', 'contains_item'] data['rels'] = helpers.exclude_rels(rels, remove) data['details'] = {k: format_field(node['props'][k]) for k in node['props'] if k not in ['content', 'uid', 'identifier', 'owned', 'buy', 'date_precision', 'isbn']} data['buy'] = node['props']['buy'] if 'buy' in node['props'] else None data['props'] = node['props'] data['sidebar'] = [] data['main'] = [] data['has_details'] = len([d for d in data['details'] if \ data['details'][d]]) > 0 data['link'] = node['link'] return data
def item(label, uid): ''' generic page for an item :param label: the desired neo4j label :param uid: the human-readable uid of the node :return: customized data for this label rendered item page template ''' # load and validate url data label = helpers.sanitize(label) if not graph.validate_label(label): logging.error('Invalid label %s', label) return render_template(request.url, '404.html', labels=graph.get_labels()) try: data = helpers.get_node(uid) except NameError: items = graph.get_all(label) return render_template(request.url, '404.html', items=items['nodes'], search=graph.search(uid)['nodes'], label=label) node = data['node'] rels = data['rels'] # ----- page header/metadata title = node['props']['identifier'] # ----- formatted data switch = { 'parent:book': grimoire_item, 'parent:entity': entity_item, 'art': art_item, 'language': language_item, 'edition': edition_item, 'publisher': publisher_item, 'editor': editor_item, 'default': generic_item, 'spell': spell_item, 'talisman': spell_item, 'parent:ingredient': ingredient_item, 'outcome': outcome_item } key = node['parent_label'] if node['parent_label'] in switch else \ (label if label in switch else 'default') item_data = switch[key](node, rels) item_data['rels'] = helpers.combine_rels(item_data['rels']) # ----- sidebar sidebar = [] related = graph.related(uid, label) if related['nodes']: sidebar = [{'title': 'Similar %s' % \ helpers.capitalize_filter(helpers.pluralize(label)), 'data': related['nodes']}] sidebar += get_others(data['rels'], node) if not item_data['content'] and not item_data['excerpts']: item_data['content'] = 'The %s "%s."' % \ (helpers.format_filter(label), helpers.unthe(title)) max_main_length = max([len(i['data']) for i in item_data['main']] + [0]) default_collapse = len(item_data['main']) > 2 or max_main_length > 30 return render_template(request.url, 'item.html', data=item_data, title=title, label=label, sidebar=sidebar, default_collapse=default_collapse)
def generic_item(node, rels): ''' standard item processing :param node: the item node :param rels: default relationship list :return: customized data for this label ''' def format_field(field): ''' deal with array data ''' if isinstance(field, list): return [{'text': i} for i in field] return [{'text': field}] data = {'id': node['id']} try: content = node['props']['content'].encode('ascii', 'xmlcharrefreplace') data['content'] = markdown(content) except AttributeError: data['content'] = '' # -- build timeline events = extract_rel_list(rels, 'event', 'end') for event in events: event['props']['relevant'] = True related = graph.get_related_events(node['props']['uid']) related = zip(related['nodes'], related['rels']) for rel_item in related: event = rel_item[0] this = 'this %s' % helpers.format_filter(node['label']) rel_type = helpers.format_filter(rel_item[1]['type']) if rel_item[1]['start']['props']['uid'] == node['props']['uid']: note = '(%s %s %s)' % \ (this, rel_type, helpers.unthe(rel_item[1]['end']['props']['identifier'])) else: note = '(%s %s)' % (rel_type, this) event['note'] = note events.append(event) data['timeline'], data['start_date'], \ data['end_date'] = build_timeline(events) excerpts = extract_rel_list_by_type(rels, 'excerpt', 'end') for excerpt in excerpts: try: excerpt['props']['content'] = markdown(excerpt['props']['content']) except AttributeError: pass data['excerpts'] = excerpts data['images'] = extract_rel_list_by_type(rels, 'image', 'end', label='image') # remove special node types from relationship lists remove = ['excerpt', 'event', 'image', 'contains_item'] data['rels'] = helpers.exclude_rels(rels, remove) data['details'] = { k: format_field(node['props'][k]) for k in node['props'] if k not in [ 'content', 'uid', 'identifier', 'owned', 'buy', 'date_precision', 'isbn', 'full_version' ] } if 'full_version' in node['props']: data['full_version'] = node['props']['full_version'] data['buy'] = node['props']['buy'] if 'buy' in node['props'] else None data['props'] = node['props'] data['sidebar'] = [] data['main'] = [] data['has_details'] = len([d for d in data['details'] if \ data['details'][d]]) > 0 data['link'] = node['link'] return data