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"))
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)
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)
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))
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)
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)
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
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
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)
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
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)
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)
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')
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)
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)})
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))
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)
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'))
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)
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)
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
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
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) })
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)
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))
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))
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)
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))
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'))
# -*- 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 = [