Уже сильно не хватает. Минимально необходимо по дефолту фильтровать закрытые задачи, а если они не отфильтрованы, сортировать по is_closed. Здесь бы надо подумать как
Связана tndt-32 - если получится быстро её решить, можно в рамках этой сделать. А может вобще пока убрать эти поля, смысла в них нет и не будет еще долгие месяцы пока я один автор и работник в проекте
upd В дашборде проекта отображать закрытые задачи. сделано в tndt-13
upd Сразу сделать dto с фильтрами и сортировкой и сохранять в сессию пользователя
upd Еще не редактировавшиеся задачи не имеют даты редактирования и поэтому не сортируются корректно в списке задач сделано в tndt-65
Вне зависимости от того, сделаем мы множественную сортировку или нет, здесь надо сделать редизайн кнопок смены сортировки, чтобы они не наползали на заголовок, и чтобы были заметны и понятны.
На данный момент план видится таким.
Model/Table/TableQuery, FilterQuery, SortQuery, PageQuery, - готово, хотя пока до сих пор сомнительно что нужны все три
1.2 Service/Table/SpecByTableQueryBuilder - обошлись без него …Query классы сами строят запросыService/Table/TableQueryByRequestBuilder,{{ table_filter_link(TableView $tableView) }} (сейчас фактически просто линк на текущий набор фильтров), {{ table_sort_link(TableView $tableView) }}, {{ table_page_link(TableView $tableView) }}Амсей который день пытаюсь сделать ревью, поправить мелкие ошики и наконец закрыть, а нахожу всякое большое ,что хочется отрефакторить и как итог еще пяток коммитов
Возможно нам будет удобнее обратный порядок сортировок, сначала по убыванию, потом по возрастанию. Но это несколько нестандартно, так что уж не будет делать. Если это и дальше будет меня триггерить, поправим в отдельной задаче.
Пагинацию по умолчанию тоже надо бы унести в TableSettings. И таки подумать о внесении данных из этих мелких подобъектов квери, которые все равно отдельно от неё не используются.
Любопытно, что симфони сама использует serialize вместо своего сериализатора. Видимо простота и отсутствие лишних зависимостей здесь удобнее гибкости и понятности сериализованного
Почему-то объект в сессии терял выбраную страницу, поэтому пришлось его сериализовать. Честно говоря, хотя бы для дампа кажется более красивым использовать json_encode или даже symfony/serializer, чтобы и в дампе сессии было понятно что хранится. но это куда сложнее, требует новые зависимости, а в json_decode непонятно как восстановить типы объектов. так что наверное оставим так, когда будет более сложная система хранения в настройках. наверное переделаем.
Кстати, src/Model/Enum/Table лежит криво, ведь там не enum. С другой стороны там классы конфигурации, о которых мы давно думаем, как например, шаблоны справочников. Может в src/Model/Templates или src/Model/Config, и там будут и шаблоны таблиц, и шаблоны справочников и прочее подобное. Об имени стоит еще подумать.
Ну все, последний пункт, сохранение в сессии тоже выполнен. Кажется это был самый простой пункт. Хотя он почему-то забывает пагинацию. Остальное помнит, а про просто инт - забывает.
Отладили, все работает совместно. Заодно появилоь решение, как переместить логику изменения query в query из роутера. И мы продолжаем думать над тем, чтобы сделать TableQuery плоским. Деление по разным областям нам постояно только мешают
А, ну и все ж пересмотреть и либо перенести FilterQuery, PageQuery, SortQuery обратно в Table, или пересмотреть его геттеры, чтобы не было ликих $query->getPage()->setPage() и $query->getFilters()->addFilter()
УРА! Мы. наконец сдвинули сие с мертвой точки. Оно работает. Да, это все надо еще причесать, убрать более не нужные viewModel, посмотреть как бы подключать компоненты фильтров динамически (чтобы в будущем увеличить их количество), подумать над расположением что где. Но в целом оно работает ровно как мы хотели.
Ну, мы наконец вроде продвинулись. осталось сделать хоть сколь-нибудь работающий прототип
что-то мы весь ходим ,всякое вокруг доделали. Но самое главное, на чем и прошлый раз тормознулись, с подклеиванием существующего query к query создаваемому фильтрами
сделали tndt-161, обновили vue до версии 3, теперь можно это имплементировать сюда и доделать таки фильтры
Не успел. Уже каникулы за середину перевалили, а я только привел в какое-то подобие порядка минимальную реализацию фильтров, но саму их работу так и не сделал. Не уверен, даже, что vue контрол запускается. Мы же на второй версии без dev-tools, и даже документацию найти становится сложно.
Что-то мне подсказывает, что в этом году я её уже не успею. Но хотя бы нарисовать план фильтров надо. И из этого плана вытащить реализацию минимум, чтобы убрать закрытые/открытые задачи из списка. А остальные фильтры, и пусть даже остальная полиморфность в другой задаче. Которая просто отложится к весеннему релизу.
Надо бы это дело нарисовать. Но в целом главная проблема в том, что вся основаная логика, ради которой мы и думали привлечь vue, в том, чтобы в кнпоку применить добаивть все текущие парметры запроса, плюс те, что натыкали в фильтрах.
Да, что-то мы уткнулись в непонимание как реализовать фильтры. Даже в минимальной реализации. В целом мы какой-то фильтр подключаем, может на этом и остановимся, явно в шаблоне указывая все данные.
Может быть даже stage уберем, ну реально не часто им пользуемся.
Да, фильтры будут такой жирной финалочкой задаче, даже в минимальном варианте сильно его увеличив. так что фильтров нужно прям самый минимум. Вот мы страдали без возможности убрать закрытые, вот на этом фильтре и остановимся, остальные доделаем потом.
Ну, данные выводятся, что осталось? Фильтры, сохранение в сессии? Пожалуй, что и все, остальное отдельными задачами. Мы на это оставили заделы, но постараемся по минимуму затягивать.
Что-то, мы сначала положили ProjectTraskSettings в query, а теперь по факту и не пользуемся. Точнее положили мы туда entityClass, но сервис принимет его на вход, так как ему нужны настройки отображения, которых в query не должно быть.
вот мы и подошли к тому, чтобы стилизовать таблицу не Stylizer, и можно бы его и переделать, но не хочется раздувать задачу. Там кстати уже стоит ссылка на tndt-84, который даже не рефакторинг, а исследоание на рефакторинг, которое мы начали, даже попробовали, о красивого решения не сделали.
Так что может это то же отложить, пока мешает не сильно.
Чтоже, вот и фильтры появились, точнее начали, и трансформер имеет представление о особеностях вывода. Минимлаьно осталось собственно выводить данные согласно настройкам. И минимлаьный фильтр, вроже отображать закрытые. Кода и так много, остальное можно в отдельные задачи.
Кстати TableSettings можно позже убрать в TableQuery, он будет хранить значения по умолчанию, например, а потом они будут перемещаться в Query и однозначной в нем все определять. Все равно Query нельзя применить для другого Settings
Пока делаем максимлаьно итеративно, не соблюдая жестко план. Так как часть этих полиморфных билдеров может быть и не пригодится. Давайте не плодить море однострочных сервисов без четкого понимания чем они лучше.
Сейчас мы создали объект TaskTableSetting, назвать его лучше иначе, но пока не знаю как, в нем буду аккумулировать логику связанную с задачами. Что за сущность, как с ней работать, какие фильтры в ней возможны.
Чтобы это все не продолжало затягиваться, давайте здесь реализуем сначала задачу минимум
но теперь без knp и с запоминанием в сессии, преднастроенная вроде сортировки задач.
последующие итерации
up. Берем в первую очередь, сколько еще её ждать
Ибо обещанного три года ждут. Вот, три года наступило
Ну что очередная попытка сесть за эту задачу
Кстати если в списке задач задача вмещается в одну строчку (что бывает не часто), список получается дико плотным, что неудобно. Надо бы сделать его всегда в две строки на задачу.
давайте все таки сделаем его
TableQuery по определению универсальные контейнер настройки таблицы. Фабрики должны быть способны собрать любой TableQuery на заказ, хоть задач, хоть документов, хоть чего угодно, требующего таблицу с фильтрами и пагинацией. Вопрос, кто отвечает за конкретную таблицу?
Что-то дофига у нас билдеров. Давайте корневые сервисы назовем фабриками, а внутренние, отвечающие за небольшую часть - билдерами.
Причем билдеры в теории могут быть одними и теми же, главное ,чтобы они поддерживали подходящий интерфейс билдера. Factory так же может их искать итератором по тегу.
UserFilterFormBuilder здесь указан для примера, в этой задаче достаточно реализвать минимально необходимые фильтры, по справочникам задачи.
Затем нужно создать задачу на распространение этой системы и на документы. Тут сразу стоит сделать фильтр на статус документа, в виде набора флажков. Затем добавить низкоприоритетную задачу на сложные фильтры (на заголовок поиск по вхождению строки или слов), на пользователя в поле автор, ответственный и т.д.
И она продолжает ждать какого-нибудь релиза.
А это точно едет в ближайший релиз, может не первой задачей, но вобще, она уже очень давно в разработке
Чтобы эта задача не представлялась такой пугающе огромной, её стоит распилить на этапы. Что нам нужно прямо сейчас и наиболее сильно? Запомнить в какую сторону сортировать задачи. И переработать нашу таблицу под будущую систему поэтому:
Для релиза 0.3 мы выберем только первые два пункта, остальные будем делать в 0.3.1, 0.3.2 и т.д. вперемежку с другими мелочами, что долго уже ждут.
Ниже проскакивала идея делать фильтры и сортировки на vue, чтобы не морочиться с мегаформой подставляющей в себя инфу из очень разных контролов, ссылок, селектов. Это конечно хорошо, но мы все еще за классический список, а не ajax в spa, а значит заполняться этот контрол будет твигом. Надо понять как.
Не забываем про эту задачу, она в этом релизе, сразу за перераспределением файлов сервисов.
она конечно приостановлена, но все еще висит дамкловым мечом
Сейчас мы уже используем треккер с нескольких устройств (например этот комментариц я пишу с мобилки). Если мы будем хранить настройки таблицы в сессии, заходя с нового устройства не имеющего куку SESSIONID, мы сбросим сессию.
В этой же задаче реализовывать устройства пользователя такое себе, такчто давайте реализуем настройки пользователя и будем хранить его там.
Не забываем об изюминке лбого грядущего релиза (надеюсь все же v0.3), пока, наконец, не сделаем.
Думается надо начать 0.3 с этой задачи, сделать непрезентационную часть по новому, без всяких форм и форм билдеров, затем переключиться на tndt-37, освоить немного vue и дорисовать фильтры и сортировки на нем
Что-то кажется, что проще написать эти фильтры на vue.js, или jQuery, чем страдать по объединению в форме и фильтров, и сортировок и пагинации с другого конца страницы.
up. Я склоняюсь к тому, чтобы написать её заного. может просто копируя куски старого кода, но не ведя историю от прежней ветки.
Так же мы не будем делать свою form и её уникальный formBuilder. Вместо этого будет TableService, который по TableSettings построит viewModel/TaskTable, в которой будут и фильтры, и сортировка, и пагинация, и сами задачи, и стили для строк и чего-угодно. Естественно не богическим классом, он viewmodel будет заполнять пользуясь разными сервисами Stylizer, Form, Paginator (свой или knp), Repository.
Тут кстати надо сразу писать полиморфно, чтобы потом быстро распространить функционал и на документы. Т.е. TableService -> TaskTableService, DocTableService (если у них сильно различаться логика будет, может будет достаточно передать другой класс entity и тип Settings)
Давайте разобьем задачу. В отдельной добавим спецификации и переведем на них наши репозитории. Потому что мы параллельно фильтрации будем еще что-то делать, вряд ли большое, но все же.
Думаю, мы попробуем вытянуть уже сделанное, просто пойдем с другой стороны.
В итоге с прошлого комментария (в котором сказано, что задача приостановлена вместе с проектом) прошло 9 месяцев. Надо восстановить на бумаге весь текущий алгоритм и подумать можем мы его понять и доделать, или стоит его создать заного с учетом новых знаний. (например стоит по максимуму отвязать логику от представления в виде symfony-form), предполагая, что фильтры и сортировки могут быть отданы в api, для внешних систем, или например если мы решим переделать фронт на spa на vue))
Лето, сезон фестов, посему все стоит ждет последнего рывка. Ибо и он не на один вечер. Ждем середины июля
Переделал на третий вариант. Со стороны формы и фронта то вроде ок работает. А вот со стороны модели очень слоно пересчитать приоритеты, понять когда удалять, а когда добавлять сортировку. Может стоит там вернуть хранения по первому варианту, просто в маппере обращаться не к SortItem, а к Collection (обогатив её необзодимыми функциями). В конце концов для этого мы и добавили DataMapper, а не Transformer, чтобы иметь доступ к полном объекту.
sort[stage]=asc&sort[type]=desc
sort[1]=stage:asc&sort[2]=type:desc
sort[type]=2:desc&sort[stage]=1:asc
И так, у нас есть 3 варианта способа записывать сортировки в реквест:
sort[stage]=asc&sort[type]=descsort[1]=stage:asc&sort[2]=type:descsort[type]=2:desc&sort[stage]=1:ascsubmit формы все равно пересортирует поля сортировки в том порядке, в котором они набиты в форму. Так что либо в handleRequest (и других функциях установки значений) пересоздавать субформу сортировки, либо уже отказаться от текущего формата query и делать sort[1]=priority-asc
Поскольку форма отправляет только свои данные все же придется в неё дублировать актуальную сортировку. (А в сортировку надо дублировать актуальную форму)
И так, мы сделали сортировку, пробросили сквозь эту систему пагинацию (решив сам пагинатор пока оставить). И начали делать фильтры. Базовый фильтр по справочникам вроде успешно работает. Но проблема в том, что форма перезатирает сортировку, сортировка форму.
Теперь он и порядок сохраняет. Осталось имплементировать её в квери. Затем обогатить форму пагинацией и отказаться от knp-paginator. Останется сохранение в сессии и фильтры. В общем весьма огроменная задача. Надо быстрее делать связи задач, чтобы иметь возможность подобные задачи декомпозировать.
И так, сортировка готова к подаче в query. Правда прорабатывая коллекцию сортировок, я сразу начал реализовывать множественную сортировку, но проблема в том, что он не сохраняет её порядок
Так, и что в этой матрешке нам дает TableForm? Особой полиморфности у нас нет. Контролер точно знает какая форма ему нужна, нет смысла вызывать общий билдер. Билдер знает какие данные нужны для строительства формы, он не может быть общим.
Фактически наша система повторяет систему форм, но специализированно. Так что как вариант:
Ну, как-то продолжили. Хотя опять гора неясностей как делать
Если фильтры явно станут формой симфони (правда их набор все же динамичен, зависит от настроек проекта) То сортировка. Превращать коллекцию актуальных сортировок в массив возможных, чтобы создать фейковый контрол из которойго инфа будет перезалита в ссылку (иил надо вметсо ссылки делать дроп-довн с тремя вариантами? В общем тут лучше без symfony form. Тогда и объект из реквеста будет сложным образом собираться.
Вместо Object есть смысл называть такие разноплановые и сложные объекты Model’ями
Пока застопорилось на проектировнаии структуры этих dto.
Решили хранить в дто классах для форм. Все же основная цель данного объекта относится к формам. Для этого переименовали src\Form\DTO в src\Form\Object показывая, что там не только dto, но и более сложные объекты
Где хранить объект с фильтрами?
Form/DTO/Task
Object\Task
С другой стороны мы часто переходим на список задач по перенаправлению из разных действий, например при закрытии задачи. И попадать на первые задачи такое себе. Так что наверное страница без фильтров в квери все же должна иметь фильтры (дефолтные, либо из сессии если пользователь уже что-то настроил себе). Чтобы не запутаться можно поставить кнопку сбросить фильтры, которая вновь перепишет на дефолтные настройки.
Кстати, как план по интуитивно понятному сохранению фильтров выборки, - кнопка “сохранить настройки страницы”, сохраняет в сессии (или в сущности), и кнопка список задач/документов получают запрос из этого сохраненного состояния. (Для этого объект должен иметь метод toUrl())
Можно просто ссылку из меню делать с преднастроенной сортировкой. Это решит текущие проблемы, как я решил их сохранением в закладки ссылки с сортировкой. Тогда в рамках этой задачи просто добавить фильтры и поправить настройку сортировок? А от knp-paginator все же отказаться?
Фильтры и сортировки у нас лежат в get. Оттуда же они забираются для отображения. Допустим мы сохраняем их в сессии, вот человек заходит на список по урлу без всяких фильтров, как он поймет, что они применены? Как это поймут контролы на странице (ну им передадут объекты), а если он сохранит это как страницу в закладки, фильтры туда не сохранятся. Ну, в целом и логично, решить мы это можем мгновенным редиректом на туже страницу, но с фильтрами в get
На моем кухонном тв разрещение не очень, и таблица так себе влезает в экран, там я бы скрыл часть не нужных полей, вопрос сессия на нем и рабочем ноуте будет одна или разные? Если разные то, ок и настройки будут разные, а если одна будет ли ок копирование настроек между устройствами? (А ведь мы еще и на мобиле смотрим).
Это стоит проверить, и если не сложно разнести по разным устройствам. В конце концов три раза настроить список не сложно (мы это делаем каждый раз), а везде иметь наиболее удобный вид будет полезно.
Мультисортировка по нескольким полям, стоит попробовать, если быстро не выйдет, выделить в отдельную задачу.
Так же при сортировке по updated надо добавлять сортировку по created, чтобы свежесозданные задачи без updated оказывались в начале списка.
И, что то же очень хотелось бы здесь видеть, - это сохранение в сессии текущих фильтраций и сортировок, чтобы не натыкивать их каждый раз.
Со стороны бека это не сложно. Главная сложность сделать не очень мудреный и удобный в использовании фронт.
Очень бы хотелось сортировку по нескольким полям. Чтобы в частности сортировать по этапы, и внутри него по дате.
У нас в ближайшем релизе приедут справочники. А значит ко времени реализации уже стоит ввести фильтрацию по этапу, приоритету, типу и сложности. И сортировку по этим полям.
Тогда сам вопрос с сортировкой по флагу закрыта отпадет. Правда фильтрация по нему может быть полезна, но нужно увязать её с фильтрацией по этапу
Кстати длинна списка оптимальная нами таки не подобрана. Сейчас это 50, и есть подозрение, что это великовато. Но если дать возможность выбирать длину, надо бы и её то же сохранять в сессии пользователя
Скорее всего это все приведет к необходимости отказаться от knp/paginator и сделать свой, принимающий этот объект настроек списка в явном виде из сессии, сущности пользователя или реквеста.
От системы фильтрации нам сейчас не столько сама фильтрация нужна (там единственная полезная галочка “показывать закрытые”, остальное скорее должно быть в багтреккере, но на проде не будет использоваться). Сколько возможность гибко настроить сортировку и набор полей и сохранить настроенное
Может стоит вобще отказаться от JsonEntity, а перейти к symfony\serializer Его можно выполнить и без реализации tndt-4, а потом использовать и в оной задаче.
Так как [tntd-4] уже давно в разработке, и как-то так себе вешать её дополнительной тяжелой задачей, просто откладываем.
А каких фильтров сейчас не хватает? По автору? По дате (здесь точная дата не подойдет, нужно задавать интервал)
Заодно кстати стоит разрешить в дашборде закрытые задачи. Собственно почему их там нет? Старые мешать не будут, так как уйдут за границу по времени обновления. А новые будут греть душу видимым прогрессом.
Ну, спустя два года, и три попытки реализовать, я таки это сделал. Дальше будем улучшать