Ejemplo n.º 1
0
def _workspace():
    action = request.form.get("action")
    if action == "create":
        w = Workspace(sanitize_workspacename(request.form.get("name")), request.user)
        c = Context(unicode(_("Unsorted")))
        w.contexts.append(c)
        db.session.add(w)
        try:
            db.session.commit()
        except IntegrityError:
            return jsonify({"message": unicode(_("Workspace '%s' already exists!", w.name))})
        return jsonify({"url": url_for('index_workspace', workspace=w.name)})
    return jsonify({})
Ejemplo n.º 2
0
def preferences():
    edittitle = unicode(_("Preferences"))
    if not request.form:
        form = PreferencesForm(obj=request.user)
        return jsonify({"title": edittitle, "body": render_template("edit.html", form=form, type="prefs")})
    form = PreferencesForm(request.form, obj=request.user)
    if form.validate():
        form.populate_obj(request.user)
        if form.pwd1.data:
            request.user.set_password(form.pwd1.data)
        have_workspace = not not getattr(request, "workspace")
        if have_workspace:
            flash(_("Saved preferences"))
        db.session.commit()
        return jsonify({"status": "LOCALECHANGE" if request.changed_locale else ("" if have_workspace else "NOWORKSPACE")})
    return jsonify({"status": "AGAIN", "title": edittitle, "body": render_template("edit.html", form=form, type="prefs")})
Ejemplo n.º 3
0
    def fire(self, is_first_run):
        if is_first_run:
            return
        from dtg.model import User
        from dtg.transtools import _

        today = date.today()
        tomorrow = today + timedelta(days=1)

        for user in User.query.filter_by(do_notify=True).all():
            if not user.email:
                continue
            request.user = user
            for workspace in user.workspaces:
                contexts = []
                request.workspace = workspace
                for context in workspace.contexts:
                    tasks = []
                    for task in context.tasks:
                        if not task.completed and not (task.recur_procedure or task.recur_data) and task.notify and task.due is not None and task.due < tomorrow \
                                and (task.visible_from is None or task.visible_from < tomorrow):
                            tasks.append({"name": task.summary, "id": task.id, "due_marker": task.due_marker, "is_recurring": task.master_task is not None,
                                  "body": markdown.markdown(task.description, safe_mode="escape"),
                                  "tags": ", ".join(tag.name for tag in task.tags)})
                    if tasks:
                        contexts.append({"name": context.name, "tasks": tasks})
                if contexts:
                    mail_body = render_template("mail.html", contexts=contexts, workspace_name=workspace.name)
                    send_html_message(u"⌚ DTG – " + workspace.name + _(u" – Upcoming tasks"), "DTG <" + user.email + ">", user.email, mail_body, [], "localhost")
Ejemplo n.º 4
0
Archivo: forms.py Proyecto: xoraxax/dtg
def is_recur_proc(form, field):
    from dtg.model import Task
    t = Task("", "")
    t.recur_procedure = field.data
    try:
        t.rrule
    except RecurInfoException, e:
        raise ValidationError(_(e.args[0][0], e.args[0][1]))
Ejemplo n.º 5
0
def login():
    if session.get("username") is not None:
        flash(_("You are already logged in!"))
        db.session.commit()
        return redirect(url_for("index"))
    if request.method == 'POST':
        username = request.form['username']
        password = request.form["password"]
        user = User.query.filter_by(username=username).first()
        if not user or user.password != get_password_hash(user.salt, password):
            return render_error(_("Invalid credentials."))
        session['username'] = username
        if request.args.get('url'):
            return redirect(request.args['url'].encode("ascii"))
        else:
            return redirect(url_for('index'))
    return render_template("login.html")
Ejemplo n.º 6
0
Archivo: model.py Proyecto: xoraxax/dtg
 def reschedule(self, flash=True):
     from dtg.webapp import flash
     next = self.compute_next_date()
     assert next, "Can only schedule master tasks"
     self.recur_last = next
     self.create_slave_task(next)
     if flash:
         flash(_("Rescheduled task"))
Ejemplo n.º 7
0
Archivo: forms.py Proyecto: xoraxax/dtg
def is_recur_info(form, field):
    from dtg.model import Task
    t = Task("", "")
    t.recur_data = field.data
    try:
        t.rrule
    except RecurInfoException, e:
        raise ValidationError(_(e.message[0], e.message[1]))
Ejemplo n.º 8
0
def workspace_rename(workspace):
    name = request.form.get("name")
    name = sanitize_workspacename(name)
    workspace.name = name
    try:
        db.session.commit()
    except IntegrityError:
        return jsonify({"message": unicode(_("Workspace '%s' already exists!", name))})
    return jsonify({"name": name})
Ejemplo n.º 9
0
def workspace_tags(workspace):
    action = request.form.get("action")
    if not action:
        return jsonify({"data": [{"name": tag.name, "id": tag.id} for tag in workspace.tags], "seqid": workspace.seqid})
    else:
        tag = Tag.query.filter_by(id=int(request.form.get("id")), workspace=workspace).first()
        edittitle = _("Edit tag") if tag else _("Add tag")
        if action == "move":
            previous_tag = Tag.query.filter_by(id=int(request.form.get("previous_id")), workspace=workspace).first()
            old_index = workspace.tags.index(tag)
            if previous_tag is None:
                new_index = 0
            else:
                new_index = workspace.tags.index(previous_tag) + 1
                if old_index < new_index:
                    new_index -= 1
            workspace.tags.pop(old_index)
            workspace.tags.insert(new_index, tag)
        elif action == "editinitial":
            form = TagForm(obj=tag)
            return jsonify({"title": edittitle, "body": render_template("edit.html", form=form, type="tag")})
        elif action == "edit":
            form = TagForm(request.form, obj=tag)
            try:
                if form.validate():
                    if tag is None:
                        tag = Tag(form["name"].data)
                        workspace.tags.append(tag)
                    else:
                        form.populate_obj(tag)
                    flash(_("Saved tag '%s'", tag.name))
                    db.session.commit()
                    return jsonify({"id": tag.id})
            except IntegrityError:
                form["name"].errors.append(_("Duplicate name"))
            return jsonify({"status": "AGAIN", "title": edittitle, "body": render_template("edit.html", form=form, type="tag")})
        elif action == "delete":
            flash(_("Deleted tag '%s'", tag.name))
            tag.delete()
        else:
            return jsonify({"error": "Invalid action"})
        db.session.commit()
        return jsonify({"result": "OK"})
Ejemplo n.º 10
0
Archivo: model.py Proyecto: xoraxax/dtg
        def due_marker(self):
            if not self.due:
                return
            days = (self.due - date.today()).days
            if days < 0:
                days_text = _("Overdue for %i days", (-days, ))
                klass = "overdue"
            elif days == 0:
                days_text = _("Due today")
                klass = "duetoday"
            elif days > 0:
                if days == 1:
                    days_text = _("Due tomorrow")
                else:
                    days_text = _("Due in %i days", (days, ))
                if days > 7:
                    klass = "duefuture"
                else:
                    klass = "duesoon"

            return days, unicode(days_text), klass
Ejemplo n.º 11
0
def get_filtered_tasks(workspace, tasks, form):
    ignore_tag_flt = False
    if form.get("tagexcl") is None:
        ignore_tag_flt = True
        timefilter = "fltall"
        kindfilter = "flttodo"
    else:
        tagexcl = bool(int(form.get("tagexcl")))
        timefilter = form.get("timefilter")
        kindfilter = form.get("kindfilter")
    today = date.today()
    tomorrow = today + timedelta(days=1)
    dayaftertomorrow = tomorrow + timedelta(days=1)
    inaweek = tomorrow + timedelta(days=7)
    if kindfilter == "flttodo":
        def fltr(item):
            return not item.completed and not (item.recur_procedure or item.recur_data)
    elif kindfilter == "fltdone":
        def fltr(item):
            return item.completed
    elif kindfilter == "fltinvisible":
        def fltr(item):
            return not item.completed and not (item.recur_procedure or item.recur_data)
    elif kindfilter == "flttmpl":
        def fltr(item):
            return not item.completed and (item.recur_procedure or item.recur_data)

    if timefilter == "fltall":
        def fltr2(item):
            if kindfilter == "flttmpl":
                return True
            return (item.visible_from is not None and item.visible_from > today) if kindfilter == "fltinvisible" else (item.visible_from is None or item.visible_from <= today)
    elif timefilter == "flttoday":
        def fltr2(item):
            return not item.completed and (item.due is None or item.due < tomorrow) and (item.visible_from is None or item.visible_from < tomorrow)
    elif timefilter == "fltplus1":
        def fltr2(item):
            return not item.completed and (item.due is None or item.due < dayaftertomorrow) and (item.visible_from is None or item.visible_from < dayaftertomorrow)
    elif timefilter == "fltplus7":
        def fltr2(item):
            return not item.completed and (item.due is None or item.due < inaweek) and (item.visible_from is None or item.visible_from < inaweek)
    elif timefilter == "fltnodate":
        def fltr2(item):
            return not item.completed and not item.due and (item.visible_from is None or item.visible_from < tomorrow)
    else:
        return render_error(_("Invalid filter name."), True)
    tags = set(Tag.query.filter_by(id=int(key), workspace=workspace).first() for key in form.getlist("selected_tags[]"))
    if ignore_tag_flt:
        func = lambda x: True
    else:
        func = tags.__ge__ if tagexcl else lambda tasktags: not tags or (tags & tasktags)
    return [task for task in tasks if fltr(task) and fltr2(task) and func(set(task.tags))]
Ejemplo n.º 12
0
def workspace_contexts(workspace):
    action = request.form.get("action")
    if not action:
        return jsonify({"data": [{"name": context.name, "id": context.id, "total": len([t for t in context.tasks if not t.completed]),
                                  "count": len(get_filtered_tasks(workspace, context.tasks, request.form))} for context in workspace.contexts],
                        "seqid": workspace.seqid})
    else:
        context = Context.query.filter_by(id=int(request.form.get("id")), workspace=workspace).first()
        edittitle = unicode(_("Edit context") if context else _("Add context"))
        if action == "move":
            previous_context = Context.query.filter_by(id=int(request.form.get("previous_id")), workspace=workspace).first()
            old_index = workspace.contexts.index(context)
            if previous_context is None:
                new_index = 0
            else:
                new_index = workspace.contexts.index(previous_context) + 1
                if old_index < new_index:
                    new_index -= 1
            workspace.contexts.pop(old_index)
            workspace.contexts.insert(new_index, context)
        elif action == "move_task":
            task = Task.query.filter_by(id=int(request.form.get("task_id"))).first()
            if task.context.workspace != workspace:
                return render_error(_("Wrong workspace"), True)
            task.context.tasks.remove(task)
            context.tasks.insert(0, task)
        elif action == "editinitial":
            form = ContextForm(obj=context)
            return jsonify({"title": edittitle, "body": render_template("edit.html", form=form, type="context")})
        elif action == "edit":
            form = ContextForm(request.form, obj=context)
            try:
                if form.validate():
                    if context is None:
                        context = Context(form["name"].data)
                        workspace.contexts.append(context)
                    else:
                        form.populate_obj(context)
                    flash(_("Saved context '%s'", context.name))
                    db.session.commit()
                    return jsonify({})
            except IntegrityError:
                form["name"].errors.append(_("Duplicate name"))
            return jsonify({"status": "AGAIN", "title": edittitle, "body": render_template("edit.html", form=form, type="context")})
        elif action == "delete":
            if len(workspace.contexts) == 1:
                return render_error(_("Last context cannot be deleted"), True)
            context.delete()
            flash(_("Deleted context '%s'", context.name))
        else:
            return jsonify({"error": "Invalid action"})
        db.session.commit()
        return jsonify({"result": "OK"})
Ejemplo n.º 13
0
Archivo: model.py Proyecto: xoraxax/dtg
 def rrule(self):
     _ = lambda x: x
     kwargs = {}
     if self.recur_data:
         values = self.recur_data.split(";")
         if values[0] not in ("Y", "M", "W", "D"):
             raise RecurInfoException(
                 (_("Invalid recurrence type"), {}))
         for i, value in enumerate(values[1:]):
             if i <= self.recur_last_arg_field:
                 field_name = self.recur_fields[i]
                 kwargs[field_name] = int(value)
             else:
                 try:
                     kwargname, value = value.split("=", 1)
                 except ValueError:
                     raise RecurInfoException((_(
                         "Invalid token '%(field)s', expected parameter name"
                     ), {
                         "field": value
                     }))
                 try:
                     value = json.loads(value)
                 except ValueError, e:
                     raise RecurInfoException(
                         (_("Invalid data in field '%(field)s'"), {
                             "field": kwargname
                         }))
                 kwargs[kwargname] = value
         kwargs.update(self.get_default_rrule_args())
         freq = {
             "Y": YEARLY,
             "M": MONTHLY,
             "W": WEEKLY,
             "D": DAILY
         }[values[0]]
         return rrule(freq, **kwargs)
Ejemplo n.º 14
0
Archivo: model.py Proyecto: xoraxax/dtg
    class Task(CreationTimeMixin, db.Model):
        """ A task can have one of three types: single event, master task, slave task.
        A master task contains the recurrence pattern (either as a procedure or a data field) and creates many slave tasks
        as long as it is not completed yet.
        Deleting and completing a slave task whose master task is not hard-scheduled forces a new slave task to be created immediately.
        Disabling hard-scheduling for a master task creates a slave task if there is no non-completed one.
        Creating a non-hard-scheduled master task creates a slave task.
        """
        id = db.Column(db.Integer, primary_key=True)
        position = db.Column(db.Integer, nullable=False)
        summary = db.Column(db.String(255), nullable=False)
        description = db.Column(db.Text(), nullable=False)
        visible_from = db.Column(db.Date)
        due = db.Column(db.Date)
        notify = db.Column(db.Boolean, nullable=False)
        completed = db.Column(db.Boolean, nullable=False)
        context_id = db.Column(db.Integer,
                               db.ForeignKey("context.id"),
                               nullable=False)
        context = db.relationship(
            "Context",
            backref=db.backref("tasks",
                               collection_class=ordering_list("position"),
                               order_by=[position]))
        master_task_id = db.Column(db.Integer, db.ForeignKey("task.id"))
        master_task = db.relationship("Task",
                                      backref=db.backref("slaves",
                                                         remote_side=[id],
                                                         uselist=True),
                                      remote_side=[master_task_id],
                                      uselist=False)
        tags = db.relationship('Tag',
                               secondary=tasks2tags,
                               backref=db.backref('tasks'),
                               order_by=[Tag.position])
        completion_time = db.Column(db.DateTime)

        recur_data = db.Column(db.String(1024))
        recur_procedure = db.Column(db.String(256))
        recur_last = db.Column(db.Date)
        recur_hardschedule = db.Column(db.Boolean)
        recur_fields = [
            "interval", "setpos", "bymonth", "bymonthday", "byyearday",
            "byweekno", "byweekday", "byeaster"
        ]
        recur_last_arg_field = 0
        recur_reschedule_this = False

        def __init__(self,
                     summary,
                     description,
                     context=None,
                     visible_from=None,
                     due=None,
                     notify=True,
                     completed=False,
                     master_task=None,
                     tags=None):
            self.summary = summary
            self.description = description
            if context is not None:  # set via context.tasks
                self.context = context
            self.visible_from = visible_from
            self.due = due
            self.notify = notify
            self.completed = completed
            self.master_task = master_task
            if tags is None:
                self.tags = []
            else:
                self.tags = tags

        def create_slave_task(self, newduedate):
            if self.visible_from is None:
                visfrom = None
            else:
                visfrom = newduedate - (self.due - self.visible_from)
            task = Task(self.summary, self.description, None, visfrom,
                        newduedate, self.notify, self.completed, self,
                        self.tags)
            self.context.tasks.insert(0, task)
            return task

        def compute_next_date(self):
            due_set = self.due is not None
            if (self.recur_last is None
                    and not due_set) or not self.recur_hardschedule:
                self.recur_last = date.today()
            elif due_set and self.recur_last is None:
                return self.due
            rrule = self.rrule
            if not rrule:
                return None
            next, next2 = rrule[:2]
            next = next.date()
            next2 = next2.date()
            if next == self.recur_last:
                next = next2
            return next

        def reschedule(self, flash=True):
            from dtg.webapp import flash
            next = self.compute_next_date()
            assert next, "Can only schedule master tasks"
            self.recur_last = next
            self.create_slave_task(next)
            if flash:
                flash(_("Rescheduled task"))

        def delete(self):
            if self.master_task and not self.master_task.recur_hardschedule:
                self.master_task.reschedule()
            db.session.delete(self)

        @property
        def recur_next(self):
            if not (self.recur_data or self.recur_procedure):
                return
            return self.compute_next_date().isoformat()

        def get_default_rrule_args(self):
            return {"dtstart": self.recur_last}

        @property
        def due_marker(self):
            if not self.due:
                return
            days = (self.due - date.today()).days
            if days < 0:
                days_text = _("Overdue for %i days", (-days, ))
                klass = "overdue"
            elif days == 0:
                days_text = _("Due today")
                klass = "duetoday"
            elif days > 0:
                if days == 1:
                    days_text = _("Due tomorrow")
                else:
                    days_text = _("Due in %i days", (days, ))
                if days > 7:
                    klass = "duefuture"
                else:
                    klass = "duesoon"

            return days, unicode(days_text), klass

        @classmethod
        def generate_recur_data(cls, type, **data):
            retval = [type]
            for i, kwargname in enumerate(cls.recur_fields):
                value = data[kwargname]
                if i <= self.recur_last_arg_field:
                    if value is None:
                        retval.append("")
                    else:
                        retval.append(str(value))
                elif value is not None:
                    retval.append("%s=%s" % (kwargname, value))
            return ";".join(retval)

        @property
        def rrule(self):
            _ = lambda x: x
            kwargs = {}
            if self.recur_data:
                values = self.recur_data.split(";")
                if values[0] not in ("Y", "M", "W", "D"):
                    raise RecurInfoException(
                        (_("Invalid recurrence type"), {}))
                for i, value in enumerate(values[1:]):
                    if i <= self.recur_last_arg_field:
                        field_name = self.recur_fields[i]
                        kwargs[field_name] = int(value)
                    else:
                        try:
                            kwargname, value = value.split("=", 1)
                        except ValueError:
                            raise RecurInfoException((_(
                                "Invalid token '%(field)s', expected parameter name"
                            ), {
                                "field": value
                            }))
                        try:
                            value = json.loads(value)
                        except ValueError, e:
                            raise RecurInfoException(
                                (_("Invalid data in field '%(field)s'"), {
                                    "field": kwargname
                                }))
                        kwargs[kwargname] = value
                kwargs.update(self.get_default_rrule_args())
                freq = {
                    "Y": YEARLY,
                    "M": MONTHLY,
                    "W": WEEKLY,
                    "D": DAILY
                }[values[0]]
                return rrule(freq, **kwargs)
            elif self.recur_procedure:
                try:
                    freq, args = get_rrule_args(localeEnglish,
                                                self.recur_procedure)
                except ValueError, e:
                    raise RecurInfoException(
                        (_("Invalid recurrence procedure, see examples"), ()))
Ejemplo n.º 15
0
Archivo: forms.py Proyecto: xoraxax/dtg
 def __call__(self, form, field):
     other_field = form[self.fieldname]
     if field.data and not other_field.data:
         raise ValidationError(_(self.message))
Ejemplo n.º 16
0
Archivo: forms.py Proyecto: xoraxax/dtg
 def __call__(self, form, field):
     other_field = form[self.smaller_than_fieldname]
     if field.data is not None and other_field.data is not None and not field.data <= other_field.data:
         raise ValidationError(
             _(self.message, {"otherfield": other_field.label}))
Ejemplo n.º 17
0
Archivo: forms.py Proyecto: xoraxax/dtg
 class PreferencesForm(PreferencesBaseForm):
     locale = SelectField(_("Language"), choices=locale_choices)
     pwd1 = PasswordField(
         _('New Password'),
         [EqualTo('pwd2', message=_('Passwords must match'))])
     pwd2 = PasswordField(_('Repeat Password'))
Ejemplo n.º 18
0
Archivo: forms.py Proyecto: xoraxax/dtg
def generate_forms(app, db):
    global _
    from dtg.model import Task, Context, Tag, User
    with app.app_context():

        def model_form_type(*args, **kwargs):
            kwargs['db_session'] = db.session
            kwargs['converter'] = DTGModelConverter(None)
            return model_form(*args, **kwargs)

        TaskFormBase = model_form_type(
            Task,
            exclude=to_exclude,
            field_args={
                "visible_from": {
                    "widget":
                    datepicker,
                    "validators": [
                        SmallerEqualThan(
                            "due",
                            _("Visible from date must be earlier than due date."
                              ))
                    ],
                    "description":
                    _("The task will be invisible until this day."),
                },
                "due": {
                    "widget": datepicker,
                    "description":
                    _("Until when should the task be completed"),
                },
                "recur_hardschedule": {
                    "label":
                    _("Hard scheduling"),
                    "description":
                    _("If ticked, tasks will be rescheduled regardless of the completion. If not ticked, rescheduling happens when a task is completed."
                      ),
                },
                "recur_data": {
                    "label":
                    _("Expert scheduling code"),
                    "description":
                    _("If you are an expert, you may compose a complex code that controls the schedule of this task."
                      ),
                    "validators": [
                        is_recur_info,
                        ExclusiveWith(
                            "recur_procedure",
                            _("Please enter either the easy or the expert string, but not both."
                              )),
                        IfSetRequiresOtherField(
                            "due",
                            _("Please set a due date before setting the recurrence interval!"
                              ))
                    ],
                },
                "recur_procedure": {
                    "label":
                    _("Recurrence procedure"),
                    "description":
                    _("Here you may use your English words to describe the recurrence pattern. Supported examples include 'Every month', 'Every 3 months', 'Every Monday', 'Every 3 years', 'Every 42 weeks'."
                      ),
                    "validators": [
                        is_recur_proc,
                        ExclusiveWith(
                            "recur_data",
                            _("Please enter either the easy or the expert string, but not both."
                              )),
                        IfSetRequiresOtherField(
                            "due",
                            _("Please set a due date before setting the recurrence interval!"
                              ))
                    ],
                },
                "notify": {
                    "description":
                    _("Whether reminders should be generated for this task"),
                },
                "description": {
                    "description":
                    _("Detailed information about this task. In Markdown syntax."
                      ),
                },
                "completed": {
                    "description":
                    _("Tick here if the task has been performed."),
                }
            })
        # get the field names into the gettext extractor
        _("Description"), _("Visible From"), _("Due"), _("Notify"), _(
            "Context"), _("Summary")

        @make_global
        class TaskForm(TaskFormBase):
            context = QuerySelectField(get_label="name")

        TaskForm.context.creation_counter = -1

        ContextForm = make_global(
            model_form_type(Context,
                            exclude=[
                                "id", "position", "workspace_id",
                                "created_datetime", "tasks", "workspace"
                            ]))
        TagForm = make_global(
            model_form_type(Tag,
                            exclude=[
                                "id", "position", "workspace_id",
                                "created_datetime", "tasks", "workspace"
                            ]))
        PreferencesBaseForm = make_global(
            model_form_type(
                User,
                exclude=[
                    "id", "username", "password", "salt", "created_datetime",
                    "feature_idx", "tutorial_idx", "workspaces"
                ],
                field_args={
                    "do_notify": {
                        "label":
                        _("Send nightly mail notifications"),
                        "validators": [
                            RequireField(
                                "email",
                                _("You need to supply your e-mail address to use this feature!"
                                  ))
                        ],
                    },
                    "email": {
                        "label": _("E-mail"),
                    },
                }))

        @make_global
        class PreferencesForm(PreferencesBaseForm):
            locale = SelectField(_("Language"), choices=locale_choices)
            pwd1 = PasswordField(
                _('New Password'),
                [EqualTo('pwd2', message=_('Passwords must match'))])
            pwd2 = PasswordField(_('Repeat Password'))

        from dtg.transtools import _
Ejemplo n.º 19
0
def workspace_tasks(workspace):
    action = request.form.get("action", None)
    if action is None:
        context = Context.query.filter_by(id=int(request.form.get("selected_context")), workspace=workspace).first()
        return jsonify({"data": get_filtered_task_dicts(workspace, context.tasks, request.form), "seqid": workspace.seqid})
    else:
        if action == "create":
            context = Context.query.filter_by(id=int(request.form.get("selected_context")), workspace=workspace).first()
            assert context is not None
            summary = request.form.get("summary") + " "
            tags = []

            if ":" in summary:
                contextname, suffix = summary.split(":", 1)
                newcontext = Context.query.filter_by(name=contextname, workspace=workspace).first()
                if newcontext is not None:
                    context = newcontext
                    summary = suffix.lstrip()
            if "#" in summary:
                for tag in Tag.query.filter_by(workspace=workspace).all():
                    search_for = ("#%s " % (tag.name, ))
                    if search_for in summary:
                        tags.append(tag)
                        summary = summary.replace(search_for, "")
            summary = summary.rstrip()

            task = Task(summary, "", tags=tags)
            context.tasks.insert(0, task)
            db.session.add(task)
            flash(_("Created task '%s'", task.summary))
            db.session.commit()
            return jsonify({"data": task.id})
        elif action == "typeahead":
            items = []
            prefix = request.form.get("summary")
            if " #" in prefix:
                start, end = prefix.rsplit(" #", 1)
                for tag in Tag.query.filter_by(workspace=workspace).all():
                    if tag.name.lower().startswith(end.lower()) and " #%s " % (tag.name, ) not in (prefix + " "):
                        items.append("%s #%s" % (start, tag.name))
            elif ":" not in prefix and prefix:
                for context in Context.query.filter_by(workspace=workspace).all():
                    if context.name.lower().startswith(prefix.lower()):
                        items.append("%s: " % (context.name, ))
            return jsonify({"list": items})

        task = Task.query.filter_by(id=int(request.form.get("id"))).first()
        if task.context.workspace != workspace:
            return render_error(_("Wrong workspace"), True)
        if action == "move":
            context = task.context
            previous_task = Task.query.filter_by(id=int(request.form.get("previous_id"))).first()
            old_index = context.tasks.index(task)
            if previous_task is None:
                new_index = 0
            else:
                if previous_task.context.workspace != workspace:
                    return render_error(_("Wrong workspace"), True)
                new_index = context.tasks.index(previous_task) + 1
                if old_index < new_index:
                    new_index -= 1
            context.tasks.pop(old_index)
            context.tasks.insert(new_index, task)
            db.session.commit()
            return jsonify({})
        query = Context.query.filter_by(workspace=workspace)
        edittitle = unicode(_("Edit task") if task else _("Add task"))
        if action == "editinitial":
            form = TaskForm(obj=task)
            form.context.query = query
            return jsonify({"title": edittitle, "body": render_template("edit.html", form=form, type="task", task=task)})
        elif action == "edit":
            form = TaskForm(request.form, obj=task)
            form.context.query = query
            if form.validate():
                form.populate_obj(task)
                if task.recur_reschedule_this:
                    task.reschedule()
                flash(_("Saved task '%s'", task.summary))
                db.session.commit()
                return jsonify({})
            return jsonify({"status": "AGAIN", "title": edittitle, "body": render_template("edit.html", form=form, type="task", task=task)})
        elif action == "delete":
            flash(_("Deleted task '%s'", task.summary))
            task.delete()
            db.session.commit()
            return jsonify({})
        elif action == "remove_tag":
            tag = Tag.query.filter_by(id=int(request.form.get("tag_id")), workspace=workspace).first()
            task.tags.remove(tag)
            db.session.commit()
            return jsonify({})
        elif action == "add_tag":
            tag = Tag.query.filter_by(id=int(request.form.get("tag_id")), workspace=workspace).first()
            task.tags.append(tag)
            db.session.commit()
            return jsonify({})
        elif action == "rename":
            task.summary = request.form.get("summary", "")
            flash(_("Changed summary to '%s'", (task.summary, )))
            db.session.commit()
            return jsonify({})
        elif action == "togglecomplete":
            task.completed = not task.completed
            if task.completed:
                flash(_("Marked task '%s' as completed", (task.summary, )))
            else:
                flash(_("Reopened task '%s'", (task.summary, )))
            db.session.commit()
            return jsonify({})
        elif action == "postpone":
            earliest_due = date.today()
            if not task.due:
                task_due = earliest_due
                flash(_("Set due date to tomorrow"))
            else:
                task_due = task.due
                flash(_("Postponed task by one day"))
            task.due = max(earliest_due, task_due + timedelta(days=1))
            db.session.commit()
            return jsonify({})

        return render_error(_("Unknown action"), True)
Ejemplo n.º 20
0
def translate():
    txt = request.form.get("txt")
    return jsonify({"txt": unicode(_(txt))})
Ejemplo n.º 21
0
 def innerfunc(workspace, *args, **kwargs):
     workspace = Workspace.query.filter_by(name=workspace, owner=request.user).first()
     if workspace is None:
         return render_error(_("Workspace not found")), 404
     request.workspace = workspace
     return func(workspace, *args, **kwargs)
Ejemplo n.º 22
0
Archivo: forms.py Proyecto: xoraxax/dtg
def __call__(self, text=None, **kwargs):
    from dtg.transtools import _
    kwargs['for'] = self.field_id
    attributes = widgets.html_params(**kwargs)
    return widgets.HTMLString(u'<label %s>%s</label>' %
                              (attributes, unicode(_(text or self.text))))