コード例 #1
0
def browse(name, ref=None):
    project = Project.get(Project.name == name)
    query = Feature.select().where(Feature.project == project)
    features = []
    for f in query:
        features.append([f.ref, f.lon, f.lat, f.action])
    return render_template('browse.html', project=project, features=features, ref=ref)
コード例 #2
0
def project(name):
    project = Project.get(Project.name == name)
    desc = project.description.replace('\n', '<br>')
    cnt = project.feature_count
    val1 = Feature.select(Feature.id).where(Feature.project == project,
                                            Feature.validates_count > 0)
    val2 = Feature.select(Feature.id).where(Feature.project == project,
                                            Feature.validates_count >= 2)
    if project.validate_modified:
        val1 = val1.where(Feature.action == 'm')
        val2 = val2.where(Feature.action == 'm')
        cnt = Feature.select(Feature.id).where(Feature.project == project,
                                               Feature.action == 'm').count()
    corrected = Feature.select(Feature.id).where(
        Feature.project == project, Feature.audit.is_null(False), Feature.audit != '').count()
    skipped = Feature.select(Feature.id).where(
        Feature.project == project, Feature.audit.contains('"skip": true')).count()
    user = get_user()
    if user:
        has_skipped = Task.select().join(Feature).where(
            Task.user == user, Task.skipped == True, Feature.project == project).count() > 0
    else:
        has_skipped = False
    return render_template('project.html', project=project, admin=is_admin(user, project),
                           count=cnt, desc=desc, val1=val1.count(), val2=val2.count(),
                           corrected=corrected, skipped=skipped,
                           has_skipped=has_skipped)
コード例 #3
0
def all_features(pid):
    project = Project.get(Project.id == pid)
    query = Feature.select().where(Feature.project == project)
    features = []
    for f in query:
        features.append([f.ref, [f.lat/1e7, f.lon/1e7], f.action])
    return app.response_class('features = {}'.format(json.dumps(
        features, ensure_ascii=False).encode('utf-8')), mimetype='application/javascript')
コード例 #4
0
def export_audit(pid):
    project = Project.get(Project.id == pid)
    if not is_admin(get_user(), project):
        return redirect(url_for('front'))
    update_audit(project)
    project.save()
    return app.response_class(
        project.audit or '{}', mimetype='application/json',
        headers={'Content-Disposition': 'attachment;filename=audit_{}.json'.format(project.name)})
コード例 #5
0
def add_project(pid=None):
    user = get_user()
    if not is_admin(user):
        return redirect(url_for('front'))
    if pid:
        project = Project.get(Project.id == pid)
    else:
        project = Project()
    return render_template('newproject.html', project=project)
コード例 #6
0
def clear_skipped(pid):
    project = Project.get(Project.id == pid)
    user = get_user()
    if user:
        features = Feature.select().where(Feature.project == project)
        query = Task.delete().where(
            Task.user == user, Task.skipped == True,
            Task.feature.in_(features))
        query.execute()
    return redirect(url_for('project', name=project.name))
コード例 #7
0
def tasks(name, ref=None):
    if not get_user():
        return redirect(url_for('login', next=request.path))
    project = Project.get(Project.name == name)
    if not project.can_validate:
        if ref:
            return redirect(url_for('browse', name=name, ref=ref))
        else:
            flash('Project validation is disabled')
            return redirect(url_for('project', name=name))
    return render_template('task.html', project=project, ref=ref)
コード例 #8
0
def api_feature(pid):
    user = get_user()
    project = Project.get(Project.id == pid)
    if user and request.method == 'POST' and project.can_validate:
        ref_and_audit = request.get_json()
        if ref_and_audit and len(ref_and_audit) == 2:
            skipped = ref_and_audit[1] is None
            feat = Feature.get(Feature.project == project, Feature.ref == ref_and_audit[0])
            user_did_it = Task.select(Task.id).where(
                Task.user == user, Task.feature == feat).count() > 0
            Task.create(user=user, feature=feat, skipped=skipped)
            if not skipped:
                if len(ref_and_audit[1]):
                    new_audit = json.dumps(ref_and_audit[1], sort_keys=True, ensure_ascii=False)
                else:
                    new_audit = None
                if feat.audit != new_audit:
                    feat.audit = new_audit
                    feat.validates_count = 1
                elif not user_did_it:
                    feat.validates_count += 1
                feat.save()
    fref = request.args.get('ref')
    if fref:
        feature = Feature.get(Feature.project == project, Feature.ref == fref)
    elif not user or request.args.get('browse') == '1':
        feature = Feature.select().where(Feature.project == project).order_by(fn_Random()).get()
    else:
        try:
            # Maybe use a join: https://stackoverflow.com/a/35927141/1297601
            task_query = Task.select(Task.id).where(Task.user == user, Task.feature == Feature.id)
            query = Feature.select().where(
                Feature.project == project, Feature.validates_count < 2).where(
                    ~fn.EXISTS(task_query)).order_by(fn_Random())
            if project.validate_modified:
                query = query.where(Feature.action == 'm')
            if user.bboxes:
                bboxes = BBoxes(user)
                feature = None
                for f in query:
                    if bboxes.contains(f.lat/1e7, f.lon/1e7):
                        feature = f
                        break
                    elif not feature:
                        feature = f
                if not feature:
                    raise Feature.DoesNotExist()
            else:
                feature = query.get()
        except Feature.DoesNotExist:
            return jsonify(feature={}, ref=None, audit=None)
    return jsonify(feature=json.loads(feature.feature), ref=feature.ref,
                   audit=json.loads(feature.audit or 'null'))
コード例 #9
0
ファイル: projecttestcase.py プロジェクト: ryanakca/yokadi
    def testAdd(self):
        tui.addInputAnswers("y")
        self.cmd.do_p_add("p1")

        tui.addInputAnswers("y", "y")
        self.cmd.do_p_add("p2 @kw1 @kw2=12")

        projects = list(Project.select())
        result = [x.name for x in projects]
        expected = [u"p1", u"p2"]
        self.assertEqual(result, expected)

        kwDict = Project.get(2).getKeywordDict()
        self.assertEqual(kwDict, dict(kw1=None, kw2=12))
コード例 #10
0
def external_audit(pid):
    project = Project.get(Project.id == pid)
    if not is_admin(get_user(), project):
        return redirect(url_for('front'))
    query = Feature.select().where(Feature.project == project, Feature.audit.is_null(False))
    result = {}
    for feat in query:
        audit = json.loads(feat.audit or {})
        props = json.loads(feat.feature)['properties']
        eaudit = {}
        if 'move' in audit:
            if audit['move'] == 'osm':
                if 'were_coords' in props['were_coords']:
                    eaudit['move'] = props['were_coords']
            elif isinstance(audit['move'], list) and len(audit['move']) == 2:
                eaudit['move'] = audit['move']
        if 'keep' in audit:
            keep = {}
            for k in audit['keep']:
                orig = None
                if 'tags_deleted.'+k in props:
                    orig = props['tags_deleted.'+k]
                elif 'tags_changed.'+k in props:
                    orig = props['tags_changed.'+k]
                    orig = orig[:orig.find(' -> ')]
                if orig:
                    keep[k] = orig
            if keep:
                eaudit['keep'] = keep
        if audit.get('skip'):
            if audit.get('comment', '').lower() != 'duplicate':
                eaudit['skip'] = audit.get('comment', '<no reason>')
        if eaudit:
            result[feat.ref] = eaudit
    return app.response_class(
        json.dumps(result, ensure_ascii=False, indent=1, sort_keys=True),
        mimetype='application/json', headers={
            'Content-Disposition': 'attachment;filename=ext_audit_{}.json'.format(project.name)
        })
コード例 #11
0
def delete_project(pid):
    project = Project.get(Project.id == pid)
    if not is_admin(get_user(), project):
        return redirect(url_for('front'))
    project.delete_instance(recursive=True)
    return redirect(url_for('front'))
コード例 #12
0
def upload_project():
    def add_flash(pid, msg):
        flash(msg)
        return redirect(url_for('add_project', pid=pid))

    user = get_user()
    if not is_admin(user):
        return redirect(url_for('front'))
    pid = request.form['pid']
    if pid:
        pid = int(pid)
        project = Project.get(Project.id == pid)
        if not is_admin(user, project):
            return redirect(url_for('front'))
        update_audit(project)
    else:
        pid = None
        project = Project()
        project.feature_count = 0
        project.bbox = ''
        project.owner = user
    project.name = request.form['name'].strip()
    if not project.name:
        return add_flash(pid, 'Empty name - bad')
    project.title = request.form['title'].strip()
    if not project.title:
        return add_flash(pid, 'Empty title - bad')
    project.url = request.form['url'].strip()
    if not project.url:
        project.url = None
    project.description = request.form['description'].strip()
    project.can_validate = request.form.get('validate') is not None
    project.validate_modified = request.form.get('validate_modified') is not None
    project.hidden = request.form.get('is_hidden') is not None

    if 'json' not in request.files or request.files['json'].filename == '':
        if not pid:
            return add_flash(pid, 'Would not create a project without features')
        features = []
    else:
        try:
            features = json.load(codecs.getreader('utf-8')(request.files['json']))
        except ValueError as e:
            return add_flash(pid, 'Error in the uploaded features file: {}'.format(e))
        if 'features' not in features or not features['features']:
            return add_flash(pid, 'No features found in the JSON file')
        features = features['features']

    audit = None
    if 'audit' in request.files and request.files['audit'].filename:
        try:
            audit = json.load(codecs.getreader('utf-8')(request.files['audit']))
        except ValueError as e:
            return add_flash(pid, 'Error in the uploaded audit file: {}'.format(e))
        if not audit:
            return add_flash(pid, 'No features found in the audit JSON file')

    proj_audit = json.loads(project.audit or '{}')
    if audit:
        proj_audit.update(audit)
        project.audit = json.dumps(proj_audit, ensure_ascii=False)
    if features or audit or not project.updated:
        project.updated = datetime.datetime.utcnow().date()
    project.save()

    if features:
        with database.atomic():
            update_features(project, features, proj_audit)

    if project.feature_count == 0:
        project.delete_instance()
        return add_flash('Zero features in the JSON file')

    return redirect(url_for('project', name=project.name))
コード例 #13
0
def table(name, page):
    PER_PAGE = 200
    project = Project.get(Project.name == name)
    query = Feature.select().where(Feature.project == project).order_by(
        Feature.id).paginate(page, PER_PAGE)
    show_validated = request.args.get('all') == '1'
    if not show_validated:
        query = query.where(Feature.validates_count < 2)
    pagination = Pagination(page, PER_PAGE, query.count(True))
    columns = set()
    features = []
    for feature in query:
        data = json.loads(feature.feature)
        audit = json.loads(feature.audit or 'null')
        if audit and len(audit.get('move', '')) == 2:
            coord = audit['move']
        else:
            coord = data['geometry']['coordinates']
        f = {'ref': feature.ref, 'lon': coord[0], 'lat': coord[1],
             'action': data['properties']['action']}
        tags = {}
        for p, v in data['properties'].items():
            if not p.startswith('tags') and not p.startswith('ref_unused_tags'):
                continue
            k = p[p.find('.')+1:]
            if k.startswith('ref'):
                continue
            tag = {}
            if data['properties']['action'] in ('create', 'delete') and p.startswith('tags.'):
                columns.add(k)
                tag['before'] = ''
                tag['after'] = v
                tag['accepted'] = not audit or k not in audit.get('keep', [])
                tag['action'] = data['properties']['action']
            else:
                if p.startswith('tags.'):
                    continue
                if p.startswith('tags_') or p.startswith('ref_unused_tags'):
                    columns.add(k)
                tag['accepted'] = p.startswith('tags_') or (
                    audit and k in audit.get('override', []))
                if p.startswith('tags_new'):
                    tag['before'] = ''
                    tag['after'] = v
                    tag['action'] = 'created'
                elif p.startswith('tags_del'):
                    tag['before'] = ''  # swapping to print deleted value
                    tag['after'] = v
                    tag['action'] = 'deleted'
                elif p.startswith('tags_cha'):
                    i = v.find(' -> ')
                    tag['before'] = v[:i]
                    tag['after'] = v[i+4:]
                    tag['action'] = 'changed'
                elif p.startswith('ref_unused'):
                    tag['before'] = data['properties'].get('tags.'+k, '')
                    tag['after'] = v
                    tag['action'] = 'changed'
            tags[k] = tag
        f['tags'] = tags
        features.append(f)

    return render_template('table.html', project=project, pagination=pagination,
                           columns=sorted(columns), rows=features,
                           show_validated=show_validated)