예제 #1
0
    def testGetOrCreateProject(self):
        # interactive
        tui.addInputAnswers("y")
        dbutils.getOrCreateProject("p1")
        self._assertOneObject(Project.selectBy(name="p1"))

        # !interactive
        dbutils.getOrCreateProject("p2", interactive=False)
        self._assertOneObject(Project.selectBy(name="p2"))
예제 #2
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)
예제 #3
0
파일: taskcmd.py 프로젝트: ryanakca/yokadi
    def do_t_remove(self, line):
        parser = self.parser_t_remove()
        options, args = parser.parse_args(line)
        task=dbutils.getTaskFromId(' '.join(args))
        if not options.force:
            if not tui.confirm("Remove task '%s'" % task.title):
                return
        projectId = task.project.id
        task.destroySelf()
        print "Task '%s' removed" % (task.title)

        # Delete project with no associated tasks
        if Task.select(Task.q.projectID == projectId).count() == 0:
            Project.delete(projectId)
예제 #4
0
    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))
예제 #5
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)
예제 #6
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)
예제 #7
0
파일: taskcmd.py 프로젝트: ryanakca/yokadi
    def do_t_reorder(self, line):
        """Reorder tasks of a project.
        It works by starting an editor with the task list: you can then change
        the order of the lines and save the list. The urgency field will be
        updated to match the order.
        t_reorder <project_name>"""
        project = Project.byName(projectName)
        taskList = Task.select(AND(Task.q.projectID == project.id,
                                   Task.q.status    != 'done'),
                               orderBy=-Task.q.urgency)
        lines = [ "%d,%s" % (x.id, x.title) for x in taskList]
        text = tui.editText("\n".join(lines))

        ids = []
        for line in text.split("\n"):
            line = line.strip()
            if not "," in line:
                continue
            id = int(line.split(",")[0])
            ids.append(id)

        ids.reverse()
        for urgency, id in enumerate(ids):
            task = Task.get(id)
            task.urgency = urgency
예제 #8
0
파일: yical.py 프로젝트: mathstuf/yokadi
def generateCal():
    cal = icalendar.Calendar()
    cal.add("prodid", '-//Yokadi calendar //yokadi.github.com//')
    cal.add("version", "2.0")
    # Add projects
    for project in Project.select(Project.q.active == True):
        todo = icalendar.Todo()
        todo.add("summary", project.name)
        todo["uid"] = PROJECT_UID % project.id
        cal.add_component(todo)
    # Add tasks
    for task in Task.select(Task.q.status != "done"):
        todo = icalendar.Todo()
        todo["uid"] = TASK_UID % task.id
        todo["related-to"] = PROJECT_UID % task.project.id
        todo.add("dtstamp", task.creationDate)
        todo.add("priority", task.urgency)
        todo.add("summary", "%s (%s)" % (task.title, task.id))
        todo.add("dtstart", task.creationDate)
        if task.dueDate:
            todo.add("due", task.dueDate)
        if task.description:
            todo.add("description", task.description)
        categories = [task.project, ] # Add project as a keyword
        if task.keywords:
            categories.extend([k.name for k in task.keywords])
        todo.add("categories", categories)
        cal.add_component(todo)

    return cal
예제 #9
0
def create_project():
    body = json.loads(request.data)
    if (body.get('title') == None or body.get('description') == None):
        return failure_response('One or more fields is missing.')
    else:
        new_project = Project(title=body.get('title'),
                              description=body.get('description'))
        db.session.add(new_project)
        db.session.commit()
        formatted_project = new_project.serialize()
        formatted_project['tasks'] = [
            t.serialize() for t in Task.query.filter_by(
                project_id=formatted_project.get('id')).all()
        ]
        formatted_project['users'] = [u.serialize() for u in new_project.users]
        return success_response(formatted_project, 201)
예제 #10
0
def upload_file(url, user):
    try:
        # S3 Save
        conn = boto.connect_s3(AWS_ACCESS_KEY, AWS_SECRET_KEY)
        bucket = conn.get_bucket(BUCKET_NAME)
        k = Key(bucket)
        k.key = RE_GET_FILE.match(url).group(5)
        file_object = urllib2.urlopen(url)
        fp = StringIO.StringIO(file_object.read())
        k.set_contents_from_file(fp)
        k.make_public()
        # Save S3 url to user
        url_to_save = 'https://s3-us-west-2.amazonaws.com/'+ BUCKET_NAME + '/' + k.key

        project = Project.create(url=url_to_save, project_user_id=user.user_id, status='pre')
        if not user.team_id:
            user.project_id = project.proj_id
            user.save()
        else:
            project.team_id = user.team_id
            project.save()
            users = User.update(project_id=project.proj_id).where(User.team_id == user.team_id)
            users.execute()

        return True
    except:
        return False
예제 #11
0
 def do_p_add(self, line):
     """Add new project. Will prompt to create keywords if they do not exist.
     p_add <projectName> [@<keyword1>] [@<keyword2>]"""
     if not line:
         print "Give at least a project name !"
         return
     projectName, garbage, keywordDict = parseutils.parseLine(line)
     if garbage:
         raise YokadiException("Cannot parse line, got garbage (%s)" % garbage)
     try:
         project = Project(name=projectName)
     except DuplicateEntryError:
         raise YokadiException("A project named %s already exists. Please find another name" % projectName)
     print "Added project '%s'" % projectName
     if not dbutils.createMissingKeywords(keywordDict.keys()):
         return None
     project.setKeywordDict(keywordDict)
예제 #12
0
def front():
    user = get_user()
    projects = Project.select().order_by(Project.updated.desc())

    def local_is_admin(proj):
        return is_admin(user, proj)
    return render_template('index.html', user=user, projects=projects,
                           admin=is_admin(user), is_admin=local_is_admin)
예제 #13
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')
예제 #14
0
 def do_p_list(self, line):
     """List all projects."""
     for project in Project.select():
         if project.active:
             active = ""
         else:
             active = "(inactive)"
         print "%s %s %s" % (project.name, project.getKeywordsAsString(), active)
예제 #15
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)})
예제 #16
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))
예제 #17
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)
예제 #18
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'))
예제 #19
0
def getProjectFromName(name, parameterName="project_name"):
    """
    Helper function which returns a project given its name, or raise a
    YokadiException if it does not exist.
    """
    name = name.strip()
    if len(name) == 0:
        raise YokadiException("Missing <%s> parameter" % parameterName)

    try:
        return Project.byName(name)
    except SQLObjectNotFound:
        raise YokadiException("Project '%s' not found. Use p_list to see all projects." % name)
예제 #20
0
def check_project_handler(user):
    project = Project.select().where(Project.proj_id == user.project_id).get()
    state = project.status
    if state == 'pre':
        text_to_send = 'Your project has been submitted, we\'ll let you know when the first round starts!'
    elif state == 'round1':
        text_to_send = 'You\'ve been assigned '+ project.assignment + '.'
    elif state == 'final':
        text_to_send = 'Congratulations! You\'ve made it to the final round! You\'ve been assigned ' + project.assignment + '.'
    else:
        # "sorry" state
        text_to_send = 'Sorry you did not make it to the final round! Thank you for participating in HackATL!'

    return bot_messages.project_status_message(user, text_to_send)
예제 #21
0
def create_user(user):
    #user = body
    user["api_key"] = uuid.uuid4()
    user["pwd"] = pbkdf2_sha256.using(rounds=200000,
                                      salt_size=16).hash(user["pwd"])
    if ("username" in user and len(user["username"])
            == 0) or not "username" in user and "email" in user:
        user["username"] = user["email"].split("@")[0]
    print(user)
    created_user, code = model.post(Model, user)
    if 'X-Api-Key' in request.headers and request.headers[
            'X-Api-Key'] is not None:
        from_anon = request.headers['X-Api-Key']
        anon_user = db_session.query(User).filter(
            User.api_key == from_anon).one_or_none()
        if anon_user:
            print('deleting user')
            db_session.execute(
                "update submissions set user_id='{1}' where user_id='{0}'".
                format(anon_user.id, created_user.id))
            db_session.query(User).filter(User.id == anon_user.id).delete()
            db_session.commit()
    if code == 201:
        if (created_user.info is not None
                and created_user.info['anonymous'] is False):
            user_project = {
                'name': created_user.username,
                'description':
                'Default space for {}'.format(created_user.username),
                'active': True,
                'owned_by': created_user.id
            }
            p = Project(**user_project)
            created_user.member_of.append(p)
            db_session.add(created_user)
            db_session.commit()
            db_session.refresh(created_user)
        return created_user.dump(), code
    else:
        return created_user, 409
예제 #22
0
파일: dbutils.py 프로젝트: mathstuf/yokadi
def getOrCreateProject(projectName, interactive=True, createIfNeeded=True):
    """Get a project by its name. Create it if needed
    @param projectName: project name as a string
    @param interactive: Ask user before creating project (this is the default)
    @type interactive: Bool
    @param createIfNeeded: create project if it does not exist (this is the default)
    @type createIfNeeded: Bool
    @return: Project instance or None if user cancel creation or createIfNeeded is False"""
    result = Project.selectBy(name=projectName)
    result = list(result)
    if len(result):
        return result[0]

    if not createIfNeeded:
        return None

    if interactive and not tui.confirm("Project '%s' does not exist, create it" % projectName):
        return None

    project = Project(name=projectName)
    print "Added project '%s'" % projectName
    return project
예제 #23
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)
        })
예제 #24
0
def project_submission_handler(receiver, user, type_of_sub):
    if type_of_sub == 'file':
        return bot_messages.project_file_failure_message(user)
    else:
        url = receiver.get_text()
        if '.com' not in url:
            return bot_messages.project_file_failure_message(user)
        project = Project.create(url=url, project_user_id=user.user_id, status='pre')
        if not user.team_id:
            user.project_id = project.proj_id
            user.save()
        else:
            project.project_team_id = user.team_id
            project.save()
            users = User.update(project_id=project.proj_id).where(User.team_id == user.team_id)
            users.execute()
            user.project_id = project.proj_id
            user.save()

        return bot_messages.project_file_success_message(user)

    return bot_messages.project_file_failure_message(user)
예제 #25
0
파일: taskcmd.py 프로젝트: mathstuf/yokadi
    def do_t_list(self, line):

        def selectRendererClass():
            if options.format != "auto":
                return gRendererClassDict[options.format]

            defaultRendererClass = TextListRenderer
            if not options.output:
                return defaultRendererClass

            ext = os.path.splitext(options.output)[1]
            if not ext:
                return defaultRendererClass

            return gRendererClassDict.get(ext[1:], defaultRendererClass)

        #BUG: completion based on parameter position is broken when parameter is given
        parser = self.parser_t_list()
        options, args = parser.parse_args(line)
        if len(args) > 0:
            projectName, keywordFilters = parseutils.extractKeywords(u" ".join(args))
        else:
            projectName = ""
            keywordFilters = []

        if self.kFilters:
            # Add keyword filter
            keywordFilters.extend(self.kFilters)

        if not projectName:
            if self.pFilter:
                # If a project filter is defined, use it as none was provided
                projectName = self.pFilter
            else:
                # Take all project if none provided
                projectName = "%"

        if projectName.startswith("!"):
            projectName = projectName[1:]
            projectList = Project.select(NOT(LIKE(Project.q.name, projectName)))
        else:
            projectList = Project.select(LIKE(Project.q.name, projectName))

        if projectList.count() == 0:
            tui.error("Found no project matching '%s'" % projectName)
            return

        # Check keywords exist
        parseutils.warnIfKeywordDoesNotExist(keywordFilters)

        # Filtering and sorting according to parameters
        filters = []

        # Filter on keywords
        for keywordFilter in keywordFilters:
            filters.append(keywordFilter.filter())

        order = -Task.q.urgency, Task.q.creationDate
        limit = None
        if options.done:
            filters.append(Task.q.status == 'done')
            if options.done != "all":
                filters.append(parseutils.createFilterFromRange(options.done))
        elif not options.all:
            filters.append(Task.q.status != 'done')
        if options.topUrgent:
            order = -Task.q.urgency
            limit = 5
        if options.topDue:
            filters.append(Task.q.dueDate != None)
            order = Task.q.dueDate
            limit = 5
        if options.overdue:
            filters.append(Task.q.dueDate < datetime.now())
            order = Task.q.dueDate
        if options.search:
            for word in options.search:
                filters.append(OR(LIKE(Task.q.title, "%" + word + "%"),
                                  LIKE(Task.q.description, "%" + word + "%")))

        # Define output
        if options.output:
            out = open(options.output, "w")
        else:
            out = tui.stdout

        # Instantiate renderer
        rendererClass = selectRendererClass()
        renderer = rendererClass(out)

        # Fill the renderer
        if options.keyword:
            if options.keyword.startswith("@"):
                options.keyword = options.keyword[1:]
            for keyword in Keyword.select(LIKE(Keyword.q.name, options.keyword)):
                if unicode(keyword.name).startswith("_") and not options.keyword.startswith("_"):
                    #BUG: cannot filter on db side because sqlobject does not understand ESCAPE needed whith _
                    continue
                taskList = Task.select(AND(TaskKeyword.q.keywordID == keyword.id,
                                           *filters),
                                       orderBy=order, limit=limit, distinct=True,
                                       join=LEFTJOINOn(Task, TaskKeyword, Task.q.id == TaskKeyword.q.taskID))
                taskList = list(taskList)
                if projectList:
                    taskList = [x for x in taskList if x.project in projectList]
                if len(taskList) == 0:
                    continue

                renderer.addTaskList(unicode(keyword), taskList)
            # Call renderer
            renderer.end()
        else:
            hiddenProjectNames = []
            for project in projectList:
                if not project.active:
                    hiddenProjectNames.append(project.name)
                    continue
                taskList = Task.select(AND(Task.q.projectID == project.id, *filters),
                                       orderBy=order, limit=limit, distinct=True,
                                       join=LEFTJOINOn(Task, TaskKeyword, Task.q.id == TaskKeyword.q.taskID))
                taskList = list(taskList)

                if len(taskList) == 0:
                    continue

                renderer.addTaskList(unicode(project), taskList)
            renderer.end()

            if len(hiddenProjectNames) > 0:
                tui.info("hidden projects: %s" % ", ".join(hiddenProjectNames))
예제 #26
0
파일: taskcmd.py 프로젝트: ryanakca/yokadi
    def do_t_list(self, line):
        doneRangeList= ["today", "thisweek", "thismonth"]

        def keywordDictIsSubsetOf(taskKeywordDict, wantedKeywordDict):
            # Returns true if taskKeywordDict is a subset of wantedKeywordDict
            # taskKeywordDict is considered a subset of wantedKeywordDict if:
            # 1. All wantedKeywordDict keys are in taskKeywordDict
            # 2. All wantedKeywordDict valued keywords have the same value
            #    in taskKeywordDict
            for wantedKeyword, wantedValue in wantedKeywordDict.items():
                if not wantedKeyword in taskKeywordDict:
                    return False
                if wantedValue and taskKeywordDict[wantedKeyword] != wantedValue:
                    return False
            return True

        def taskHasWantedKeywordDict(task, wantedKeywordDict):
            """
            @param task: task object
            @param wantedKeywordDict: dict of name/value of wanted keyword
            # a task is considered a subset of wantedKeywordDict if:
            # 1. All wantedKeywordDict keys are in task or project keywords
            # 2. All wantedKeywordDict valued keywords have the same value
            #    in task or project keyword"""
            for wantedKeyword, wantedValue in wantedKeywordDict.items():
                taskFilters=[Task.q.id==task.id,
                         TaskKeyword.q.taskID==task.id,
                         TaskKeyword.q.keywordID==Keyword.q.id,
                         LIKE(Keyword.q.name, wantedKeyword)]

                projectFilters=[Project.q.id==task.projectID,
                                ProjectKeyword.q.projectID==Project.q.id,
                                ProjectKeyword.q.keyword==Keyword.q.id,
                                LIKE(Keyword.q.name, wantedKeyword)]

                if wantedValue:
                    taskFilters.append(TaskKeyword.q.value==wantedValue)
                    projectFilters.append(ProjectKeyword.q.value==wantedValue)

                if Task.select(AND(*taskFilters)).count()==0 and Task.select(AND(*projectFilters)).count()==0:
                    return False
            # All critera were met, return ok
            return True

        def createFilterFromRange(_range):
            # Parse the _range string and return an SQLObject filter
            minDate = date.today()
            if _range == "today":
                pass
            elif _range == "thisweek":
                minDate -= timedelta(minDate.weekday())
            elif _range == "thismonth":
                minDate = minDate.replace(day = 1)
            else:
                raise YokadiException("Invalid range value '%s'" % _range)

            return Task.q.doneDate>=minDate

        def selectRendererClass():
            if options.format != "auto":
                return gRendererClassDict[options.format]

            defaultRendererClass = TextListRenderer
            if not options.output:
                return defaultRendererClass

            ext = os.path.splitext(options.output)[1]
            if not ext:
                return defaultRendererClass

            return gRendererClassDict.get(ext[1:], defaultRendererClass)

        #BUG: completion based on parameter position is broken when parameter is given
        parser = self.parser_t_list()
        options, args = parser.parse_args(line)
        if len(args) > 0:
            projectName, keywordDict = parseutils.extractKeywords(u" ".join(args))
        else:
            projectName = ""
            keywordDict = {}

        if not projectName:
            # Take all project if none provided
            projectName="%"

        projectList = Project.select(LIKE(Project.q.name, projectName))

        if projectList.count()==0:
            tui.error("Found no project matching '%s'" % projectName)
            return

        # Check keywords exist
        for keyword in keywordDict.keys():
            if Keyword.select(LIKE(Keyword.q.name, keyword)).count()==0:
                tui.error("Keyword %s is unknown." % keyword)

        # Filtering and sorting according to parameters
        filters=[]
        order=-Task.q.urgency, Task.q.creationDate
        limit=None
        if options.done:
            filters.append(Task.q.status=='done')
            if options.done != "all":
                filters.append(createFilterFromRange(options.done))
        elif not options.all:
            filters.append(Task.q.status!='done')
        if options.topUrgent:
            order=-Task.q.urgency
            limit=5
        if options.topDue:
            filters.append(Task.q.dueDate!=None)
            order=Task.q.dueDate
            limit=5
        if options.search:
            for word in options.search:
                filters.append(OR(LIKE(Task.q.title, "%"+word+"%"),
                                  LIKE(Task.q.description, "%"+word+"%")))

        # Define output
        if options.output:
            out = open(options.output, "w")
        else:
            out = tui.stdout

        # Instantiate renderer
        rendererClass = selectRendererClass()
        renderer = rendererClass(out)

        # Fill the renderer
        if options.keyword:
            if options.keyword.startswith("@"):
                options.keyword = options.keyword[1:]
            for keyword in Keyword.select(LIKE(Keyword.q.name, options.keyword)):
                if unicode(keyword.name).startswith("_") and not options.keyword.startswith("_"):
                    #BUG: cannot filter on db side because sqlobject does not understand ESCAPE needed whith _
                    continue
                taskList = Task.select(AND(TaskKeyword.q.taskID == Task.q.id,
                                           TaskKeyword.q.keywordID == keyword.id,
                                           *filters),
                                        orderBy=order, limit=limit)
                taskList = list(taskList)
                if keywordDict:
                    # FIXME: factorize (see project oriented rendering below)
                    taskList = [x for x in taskList if taskHasWantedKeywordDict(x, keywordDict)]
                if projectList:
                    taskList = [x for x in taskList if x.project in projectList]
                if len(taskList) == 0:
                    continue

                renderer.addTaskList(unicode(keyword), taskList)
            # Call renderer
            renderer.end()
        else:
            hiddenProjectNames = []
            for project in projectList:
                if not project.active:
                    hiddenProjectNames.append(project.name)
                    continue
                taskList = Task.select(AND(Task.q.projectID == project.id, *filters),
                                       orderBy=order, limit=limit)

                if keywordDict:
                    taskList = [x for x in taskList if taskHasWantedKeywordDict(x, keywordDict)]
                else:
                    taskList = list(taskList)
    
                if len(taskList) == 0:
                    continue

                renderer.addTaskList(unicode(project), taskList)
            renderer.end()
    
            if len(hiddenProjectNames) > 0:
                tui.info("hidden projects: %s" % ", ".join(hiddenProjectNames))
예제 #27
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)
예제 #28
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))
예제 #29
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'))
예제 #30
0
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 10 16:11:37 2017

@author: Frank
"""
import os
from db import ProjectInfo, Finance, Company, Project, HumanResource

project_info = ProjectInfo()
company = Company(os.path.join(os.getcwd(), 'db\\公司.xlsx'))
human = HumanResource(os.path.join(os.getcwd(), 'db\\员工.xlsx'))
finance = Finance(os.path.join(os.getcwd(), 'db\\财务.xlsx'))
projects_done = Project(os.path.join(os.getcwd(), 'db\\往期工程.xlsx'))
projects_being = Project(os.path.join(os.getcwd(), 'db\\正在建设项目.xlsx'))

db = {}
db['project_info'] = project_info
db['company'] = company
db['project_members'] = {}
db['human'] = human
db['finance'] = finance
db['projects_done'] = projects_done
db['projects_being'] = projects_being
db['公司信息路径'] = os.path.join(os.getcwd(), 'db')
db['人员证件路径'] = os.path.join(os.getcwd(), 'img\\证件\\人员')
db['公司证件路径'] = os.path.join(os.getcwd(), 'img\\证件\\公司')

PATH = ['公司信息路径', '人员证件路径', '公司证件路径']

POSITION = [