def review():
    nquads = get_uncommited_quads(g.userid)
    print nquads
    if request.method == 'POST' and len(nquads) > 0:
        # set status of proposed quads to "proposed"
        revert = request.form.get('unchecked', 'revert') == 'revert'
        checked = []
        unchecked = []
        additions = []
        removals = []
        commitid = nquads[0]['commitid']
        message = request.form.get('comment')
        print request.form
        for q in nquads:
            if q['subject'] in request.form and str(q['id']) in request.form:
                checked.append(q['id'])
            else:
                unchecked.append(q['id'])
                if not revert:
                    if q['type'] == 'addition':
                        additions.append([q['subject'], q['predicate'], q['object'], q['context']])
                    else:
                        removals.append([q['subject'], q['predicate'], q['object'], q['context']])
        if 'revert' in request.form:
            if revert:
                revert_changes(checked)
            else:
                revert_changes(unchecked)
            nquads = get_uncommited_quads(g.userid)
        else: # if 'submit' in request.form
            # revert unchecked changes
            revert_changes(unchecked, commit=False)
            # propose remaining changes
            propose_changeset(g.userid, message=message, commit=False)
            # if "keep" unchecked was selected, re-apply unchecked
            if not revert:
                store_triples(g.userid, additions, removals, commit=False)
            commit_db()
            return redirect(url_for('proposal', proposal_=commitid))
    # <context> / <subj> / predicates: [pred + obj]
    return render_template('review_changes.html', changes=prepare_nquads_for_template(nquads))
def render_template(template, **kwargs):
    if session.get('logged_in', False):
        changes = len(get_uncommited_quads(g.userid))
    else:
        changes = 0
    return flask.render_template(template, no_of_uncommited_changes=changes, **kwargs)
def ontology(ontology_):
    ont = query_db('select * from ontologies where prefix = ?', [ontology_], one=True)
    # get the graph for the relevant ontology
    graph = get_graph(ontology_)
    if graph is None:
        # TODO: 404
        return redirect(url_for('index'))
    resource_ = request.args.get('resource_', None)
    errors = []
    # for recreating a page if there are errors
    changes = {'addition':[], 'removal':[]}

    # if ?resource_=xxx is present and xxx is not None then go into "resource viewing mode"
    if resource_ is not None:
        properties = {}
        # get the label of the resource
        res_name = get_label(resource_)

        # force the resource to a URIRef
        uri2res = lambda uri: uri if isinstance(uri, rdflib.URIRef) else rdflib.URIRef(uri)
        r = uri2res(resource_)

        # build list of (type,predicate,object)s, using an empty string for the type of original triples
        tpos = [('', p, o) for p, o in graph.predicate_objects(subject=r)]
        # include additions/removals from uncommited proposal
        if session.get('logged_in', False):
            tpos.extend([(s['type'], uri2res(s['predicate']), parse_string_rdfobject(s['object'])) for s in get_uncommited_quads(g.userid, resource_)])

        # TODO: these 2 lines may be redundant now as most form validation is done in the UI, remove them  completely when this is confirmed
        # include additions from changes (only present if errors in form submission)
        tpos.extend([('addition', uri2res(stmt['pred']), parse_string_rdfobject(stmt['val'])) for stmt in changes['addition']])
        # include removals from changes (only present if errors in form submission)
        tpos.extend([('removal', uri2res(stmt['pred']), parse_string_rdfobject(stmt['val'])) for stmt in changes['removal']])
        # TODO: add "modified" type (maybe)
        for t,p,o in tpos:
            # get existing values for this predicate
            item = properties.get(p,
                                  {'value': [],
                                   'qname': get_qname(p), 
                                   'label': get_label(p)})
            # convert rdf object to a dict
            v = rdfobject2dict(o)
            # add 'deleted' or 'added' 'class' value (used by templates)
            if t == 'removal':
                try:
                    # if it's a removal, it should already exist in the values list
                    # find it and add the class to the existing entry
                    idx = item['value'].index(v)
                    v['class'] = 'deleted'
                    item['value'][idx] = v
                except ValueError:
                    pass # caused when .index fails
            else:
                if t == 'addition':
                    v['class'] = 'added'
                item['value'].append(v)

            # update the changes
            properties[p] = item

            # TODO: this may be redundant with the get_label call above
            # simply sets the resource name variable to the value of the RDFS.label predicate
            if res_name is '' and p == RDFS.label:
                res_name = v['value']

        # if there were no predicates, consider this a "new resource" and present the "create resource" view
        # with the URI already filled in
        # TODO: a lot of this is duplicate code from the create_resource function
        is_new = False
        if len(properties) == 0:
            # create new resource
            properties = {}
            properties[RDF.type] = {'value': [{'type':"URI", 'value':"", 'class':'added'}],
                                    'qname': 'rdf:type',
                                    'label': 'type'}
            properties[RDFS.label] = {'value': [{'type':"Literal", 'value':"", 'class':'added'}],
                                      'qname': 'rdfs:label', 
                                      'label': 'label'}
            res_name='Create New Resource'
            is_new=True

        # TODO: proposal/history stuff
        proposals = []
        history = []
        return render_template('resource.html',
                               ontology_=ont,
                               uri=resource_,
                               name=res_name,
                               properties_=properties,
                               proposals=proposals,
                               history=history,
                               is_new=is_new,
                               auto_save=False)

    # if no resource is requested, go to the ontology view, retrieving a list of all the subjects in the ontology
    resources = [{'uri':s[0], 'qname':get_qname(s[0]), 'label':get_label(s[0])} for s in graph.triples((None, RDF.type, None))]
    proposals = None #[s for s,_ in groupby(pgraph.subjects()) if isinstance(s, rdflib.URIRef)] # TODO and not s.startswith(changeset_base_uri)
    return render_template('ontology.html', ontology_=ont, resources=resources, proposals=proposals)