Когда-то, помыкавшись в поисках онлайн системы управления задачами было решено писать свой «велосипед». Но с уклоном в ту область, которая, к примеру, мне более важна — учет будущих и повторяющихся задач, а грамотного подхода к этому вопросу я не увидел ни у одного существующего сервиса.
Похожие системы пишет под себя огромное количество разработчиков, даже прослеживаются некоторые тенденции:
- большинство тяготеют к управлению проектами, т.е. уклон в область совместной работы, постановки задач другим пользователям и прочим видам collaboration
- подходы к определенным вопросам очень сильно похожи на лидеров рынка (Google calendar с его принципами установки повторения задач, к примеру). Мало кто делает нормальное древовидное представление задач, т.к. коли это не особо распространено, то значит и не особо востребовано. Но я почему-то всегда попадаю в ту группу пользователей, которым не хватает возможности что-то подкрутить, порыться в настройках. Отдельная песня – идеология Apple, где в большинстве случаев настройки программы сводятся к паре галочек. Иногда такой подход даже обижает.
Вкратце сразу сообщу ключевые функции системы (т.е. те, которые либо мало распространены у аналогов, либо вообще не встречаются у них):
- подзадачи, папки, подпапки, неограниченная вложенность
- повторяющиеся задачи (несколько методов повторения)
- односторонняя и двусторонняя синхронизация с Google Tasks
- триггеры (определяемые действия на создание, изменение, удаление задач, наступление времени и т.п.)
- пользовательские фильтры (настраиваемые практически до SQL запроса)
Итак, в наличии было небольшое количество выделенных серверов в ДЦ Hetzner (Германия), арендованных по рабочим нуждам, но слабо используемых (основное назначение – хранение данных, поэтому нагрузки мало). Также имелся опыт разработки на T-SQL, Delphi, Visual C, .NET. Крайне мало опыта было в Javascript, пришлось наверстывать.
Мы – это полтора разработчика и много подчиненных пользователей – тестеров. Система активно используется в повседневной работе, никак не связанной с разработкой софта. Специфика работы такова, что задач однотипных много, много из них еще не наступили, но нужно иметь возможность их видеть и делать заранее.
К примеру, учет доверенностей. Основная задача – не пропустить срок ее истечения и заблаговременно предпринимать действия по ее продлению. Для этого использовались следующие фичи:
- за месяц до окончания доверенности шло уведомление по почте (триггер)
- за неделю до окончания доверенности задача по ее продлению помечалась как важная и, соответственно, отображалась в списке самых важных дел (триггер)
- отдельным фильтром отображались все доверенности, истекающие в течение месяца
- отдельным фильтром отображались все доверенности, истекающие в следующие три месяца
Прежде всего некий disclaimer. Мы не пытались сделать очередной “комбайн”, наш сервис не является системой для, к примеру, багтрекинга, т.к. это абсолютно другая специфика. Сервис прежде всего ориентирован на обычных “продвинутых” пользователей, которым нужно чуть больше от систем управления задачами, область применения – учет личных задач (купить, отследить, напомнить и т.п.) с возможностью совместного использования с другими пользователями (пускай, родственники, коллеги).
Что реализовать даже не пытались:
- таймтрекинг
- аналоги багтрекинга
- общение, всякие социальные кнопки
- строгого соответствия канонам GTD. Точнее все необходимое вроде для этого есть (поле «Контекст», тэги с неограниченной вложенностью), но особо на методику GTD не ориентировались.
А нужно мне было от управления задачами следующее (список, конечно, неполный, но показательный):
- Cписок задач принципиально в древовидном виде, с папками и подпапками, вложенность должна быть неограничена (чтобы там ни говорили про то, что три уровня вложенности хватит всем – враки)
- добавление задач по электронной почте, причем при направлении по разным адресам — в разные подпапки
- учет домашних дел (оплата по квитанциям, проверка масла в машине, отслеживание сроков окончания оплаты и т.п. с разной степенью периодичности, автоповторения и настраивания уведомлений обо всем этом абсолютно разными способами — хотел чтобы об оплате я предупреждал сам себя три раза, а о некоторых событиях — предупреждал о просрочке более чем на неделю)
- по работе — тут сложность в количестве — нужно было отслеживать сроки окончания доверенностей, договоров, сертификатов и т.п., причем также нужно было настроить уведомления о пропуске сроков. Количество этих задач — сотни, поэтому ни один из существующих менеджеров задач с этим либо не справился, либо реализация всего этого была неудобной
- просмотр повестки дня (списка актуальных дел) кроме сегодняшнего еще и на любой произвольный период, причем с навороченной фильтрацией, к примеру в одном списке нужно было выводить текущие задачи, задачи которые начнутся в ближайшую неделю плюс все домашние задачи, кроме неважных задач (с небольшим приоритетом)
- давать доступ Read-only кому нужно на все это
- давать write доступ кому нужно, причем с правами изменения только определенных полей задачи (к примеру, работнику, который может только менять статус задачи)
- использование временных зон, т.к. коллеги работают с теми же данными, но в других часовых поясах, поэтому все используемые даты должны корректироваться в нужную временную зону
- система меток (тэгов) – обязательно древовидная, с возможностью совместного использования (т.е. чтобы определенные метки были видны другим пользователям, а другие – только мне)
- возможность временного сокрытия некоторых задач (к примеру – мозолит глаза какая-то задача – скрываем ее на 2 дня, после этого она опять появится). К слову такой механизм можно и так реализовать еще другими способами
Ну и, понятно, что также нужны распространенные базовые функции:
- вывод и отсылка на почту повестки дня (настраивается как простой вариант – просто список на почту ежедневно в назначенное время, так и в виде триггера по расписанию – высылаются нужные ветки задач путем редактирования текста письма)
- настраиваемые пользовательские поля (настраиваемость, правда, заключается только в изменении названия, смена типа данных не реализована, пока не видел необходимости)
- настраиваемый внешний вид задач (шрифт, иконка, цвета)
- произвольная сортировка подзадач каждой задачи по трем критериям (задач, повторюсь, много, поэтому без сортировки никак)
- RSS канал с настраиваемыми уведомлениями (ну люблю я лежа полистать feedly, заодно поглядеть и свою ленту уведомлений)
- Поле «Прогресс» с графическим отображением (на самом деле, мало кому действительно нужно)
- Приоритеты задач
4 месяца работы и в итоге получился некий «движок» для учета задач, все что хотел — реализовал.
Вкратце о получившемся.
Основная единица информации – задача. Задача имеет дату начала и дату конца (due date). Если с due date все понятно, то с датой начала стоит объяснить, т.к. далеко не во всех аналогичных системах она есть. По сути, это дата, с которой задача считается актуальной. Т.е. присвоив задаче дату, она не будет выводиться в списке задач до тех пор, пока не наступит эта дата.
В основе группировки задач и разделения доступа — понятие «Список задач». Т.е. некий набор задач, к примеру, «Дом», «Работа», «Компьютер» и пр. В других системах это может называться тасклистом, проектом, календарем, workspace и т.п. Также функция такого деления – каждый список имеет свои настройки прав доступа при совместном использовании и свои настройки временной зоны.
Отдельно про временные зоны. Мне кажется, на практике это мало кому нужно, но нам это нужно было просто критически. Несколько наших работников и лиц, которым предоставлен доступ, работают в совершенно разных временных зонах, редактируя и просматривая задачи из одинаковых списков. Если при установке даты задачи указывать конкретно время особо и не нужно, то при настройке уведомлений, триггеров иногда необходимо указывать конкретное время, к примеру, ежедневно сменять статус задачи в 20-00. Т.е. смена статуса должна происходить именно в 20-00 временной зоны пользователя, поставившего триггер. Для корректной реализации этого устанавливается временная зона каждого пользователя и конкретного списка задач.
Что касается прав доступа, то пришли к следующему решению. Пользователь может делегировать право на просмотр/редактирование определенного списка задач другому пользователю.
Могут быть установлены следующие права:
- Только просмотр
- Только добавление задач
- Только редактирование задач
- Только удаление задач
- Редактирование и удаление задач
- Редактирование и добавление задач
- Добавление и удаление задач
- Полный доступ
Дополнительно при условии права на редактирование устанавливается список полей, которые запрещено редактировать пользователю. Это позволяет реализовать такой механизм взаимодействия пользователей при совместной работе – кто-то, владеющий правами ставит задачи, а кто-то другой, имеющий только ограниченный набор прав может только помечать задачи как выполненные. Т.е. можно ставить задачи, не волнуясь, что кто-то сотрет саму задачу или что-то в ней подправит. Понятно, что в системах управления проектами все это реализовано на более высоком уровне, но мы не пытались объять необъятное и реализовали базовый набор.
Просмотр дерева задач возможен на любую дату, как прошлую, так и будущую. Т.к. информация о задачах хранится безотносительно к текущей дате, можно ткнуть какую-либо будущую дату и увидеть состояние выполнения задач на эту дату. К примеру, частенько, когда есть лишнее время, хочется сделать что-то заранее, но коли время еще не подошло, то и будущие задачи еще не показываются, т.к. они в будущем. Тыкаем будущую дату – и видим что можно сделать из будущих задач.
Фильтрация
С помощью настраиваемых фильтров можно реализовать следующие пожелания:
- список задач только из определенной папки (к примеру, либо с подпапками либо без них)
- список задач только на следующую неделю
- в одном списке – задачи из определенного списка задач на следующую неделю, из другого списка – только просроченные на 1 месяц
Фильтры — вещь достаточно удобная и гибкая, но мало кто ее прикручивал хорошо. Чтобы это действительно было удобно, нужна возможность группировки критериев, это реализовано (спасибо DevExpress, тут львиная доля заслуг у них).
В дальнейшем оказалось, что пользы от фильтров гораздо больше – с их помощью можно определить набор повестки дня, рассылаемой пользователю ежедневно, плюс определить задачи, которые необходимо синхронизировать с google tasks. Но о google tasks лучше напишем отдельно.
Мобильная версия.
Сам я 80% процентов своего свободного времени провожу за iPad, поэтому вопрос создания приложения под iOS/Android не стоял – оно было необходимо. И было решено его не разрабатывать. Совсем. Пошли другим путем – путем гибкой синхронизации с Google Tasks можно основную часть повседневной работы (основное редактирование задач, просмотр и отметки о выполнении, т.е. основной функционал tasks) перенести именно в Google Tasks, а всю информацию периодически синхронизировать (двусторонним или односторонним путем) с сервисом. Точнее синхронизация автоматическая, точнее периодическая (push Google Tasks не поддерживает). Приложений для Google Tasks более чем достаточно, некоторые просто шедевры. Почему бы хотя бы в этой части не изобретать велосипед, а использовать чужие наработки :)
Техническая сторона.
Сервис написан на ASP.NET, крутится на одном дедике. БД – PostgreSQL, крутится на другом.
Изначально писалось на MSSQL, но потом стало понятно, что постгрес подходит больше. Тяжеловато было переписывать все на постгрес, но оно того стоило.
80% бизнес-логики реализованы в БД, так оно как-то быстрее работает.
Использованы серверные компоненты DevExpress – основная нагрузка лежит на ASPxTreeList. Да, пришлось использовать именно серверные компоненты, пускай это лишний трафик для клиента, но иначе не реализовать работу с тысячами задач и некоторыми функциями. Да, это ведет к некой инертности работы “дерева”, но “отклик” порядка 200-300 мс практически незаметен, поэтому устроил. Из аналогичных компонентов пробовал и телериковские, но там очень неприятные тормоза при сворачивании/разворачивании дерева, некомфортно работать.
Используется ASP.NET WebForms, знаю, что немного устаревшая технология, но практически вся работа сосредоточена на одной странице и постоянных коллбэках одного элемента, поэтому переход на MVC мало что бы дал. А вечную проблему излишнего размера ViewState вроде минимизировал.
В два отдельных приложения вынесены операции с почтой (прием задач по почте и отправка) и синхронизация с Google Tasks. Их писал на Delphi.
Опять disclaimer
- Ради убыстрения разработки многие относительно нечасто используемые части интерфейса (редактирование списков задач, триггеров) написаны с применением готовых элементов управления от DevExpress, поэтому чуть тяжеловаты
- Поддерживаются все распространенные браузеры, но со старыми версиями могут быть проблемы. IE8 иногда выдает ошибки, но т.к. под рукой чистого IE8 нет, руки пока до исправления ошибок не дошли.
- Синхронизация с Google Tasks работает, но злобный Google недостаточно пока увеличил квоту на запросы к их API, поэтому теоретически в случае притока пользователей, которые настроят эту фичу, возможна остановка синхронизации в ночное время на первых порах. Долблю их саппорт как могу.
Монетизация и сохранность данных
Монетизация в обозримом будущем, разумеется, не планируется. Если она и будет, то только в случае постоянного роста активных пользователей и увеличения потребности в мощностях. На данный момент ресурсов у нас достаточно, чтобы без напряга выделить пару серверов под этот проект, тем более по hetzner`овским ценам. В случае чего — можно и увеличить количество. Если какие-либо платные аккаунты будут вводиться, то правильной практикой будет то, что зарегистрировавшиеся ранее пользователи получат пожизненный бесплатный «premium» аккаунт. Про сохранность данных — в случае закрытия сервиса все пользователи будут уведомлены и будет не менее двух месяцев на перенос данных. Если кто-то знает как лучше предложить пользователям резервировать данные — сообщите, пожалуйста. Мне пока кроме синхронизации в Google Tasks ничего на ум не приходит. Можно и экспорт прикрутить, к примеру, в csv.
Планы
- Интеграция с google calendar. В процессе. Пока нет четкого понимания в каком виде это красиво реализовать, т.к. аналогов нет.
- Оптимизация, оптимизация, оптимизация. Особенно использования клиентского трафика. Плюс под старые браузеры.
- SSL
- Добавить временных вариантов повторения и планирования задач (пока реализованы базовые периодичности)
- Кинулся было писать календарное представление задач, написал, но потом решил сосредоточиться на стандартном древовидном, т.к. не стоит сразу за все хвататься, не сделав безглючным уже реализованное.
Ну и чуть позже опубликую пост поподробнее про триггеры и синхронизацию с Google Tasks, там есть что рассказать.
Ссылка на сам сервис — betasked.ru
UPD По-моему много кто испугался первого скрина, но ничто не мешает убрать ненужные поля, выбрать тему оформления и работать так:
или так: