Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Calendar): revert period #3415

Merged
merged 17 commits into from
Jun 5, 2024
Merged

fix(Calendar): revert period #3415

merged 17 commits into from
Jun 5, 2024

Conversation

zhzz
Copy link
Member

@zhzz zhzz commented Apr 25, 2024

Проблема

В #3258 были добавлены пропы для периода дат и проведен некоторый рефакторинг.

Пропы для периода планируется использовать только внутри отдельного компонента PeriodPicker, но они значительно усложняют устройство самого Calendar. PeriodPicker может реализовать ту же функциональность внутри себя самостоятельно, используя более общий проп renderDay. Это не задача самого календаря. Он может оставаться простым. Поэтому считаю, что пропы для периода в Calendar не нужны. Их стоит откатить.

Проведенная в #3258 замена пропа onMonthChange на onStuckMonth и onMonthSelect кажется нецелесообразной. onMonthChange решает ту же задачу, но является более общим. Он не зависит от реализации смены месяцев (с залипанием или без). Возможно, его стоит переименовать на onVisibleMonthChange для большей интуитивности.

В #3258 также был добавлен debounce на вызов onStuckMonth. Его тоже предлагаю откатить. Во-первых, вызовов происходит не очень много. Debounce уменьшает количество вызовов на единицы. Что не очень существенно (но добавляет немного сложности). Во-вторых, не факт, что пользователю не будут интересны все вызовы. Среди них нет лишних или дублирующих. Они все отражают факт смены месяца. Так что, думаю, их не стоит debounce-ить.

Решение

Откачено

  1. Удалил пропы periodStartDate и periodEndDate
  2. Удалил тесты на период
  3. Вернул onMonthChange вместо onStuckMonth и onMonthSelect
  4. Убрал debounce для onMonthChange
  5. Откатил темные скриншоты Calendar и DatePicker, изменившиеся в feat(Calendar): added period #3258

Переделано

  1. Поменял сигнатуру пропа renderDay. Теперь он опирается на публичный компонент CalendarDay
  2. Переделал примеры с периодом и с кастомным днем

Добавлено новое

  1. Публичный компонент CalendarDay
  2. Хелперы для конвертации дат в CalendarDateShape lib/date/comparison. Они понадобятся в разработке PeriodPicker. CalendarDateShape признан легаси. От него будем избавляться.
  3. Оптимизировал рендер дня через memo. Так как с добавлением CalendarContext сильно просел перфоманс анимации скролла из-за тысяч ререндеров дней.

Переделано дополнительно

  1. Упростил верстку ячеек дней, с вынесением общих стилей
    • Избавился от динамических inline-стилей в пустых ячейках
    • Поменял .today2022 .todayCaption на .todayCaption2022

Удалено дополнительно

  1. Скриншот на onMonthChange. Он был добавлен давно. Проблем с ним не было, за исключением того, что тест был неочевидный. Тот же функционал тестируется юнитами. Чтобы не переделывать в нем renderDay, я удалил его за ненадобностью.

Ссылки

IF-1702

Чек-лист перед запросом ревью

  1. Добавлены тесты на все изменения
    ✅ unit-тесты для логики
    ✅ скриншоты для верстки и кросс-браузерности
    ⬜ нерелевантно

  2. Добавлена (обновлена) документация
    ✅ styleguidist для пропов и примеров использования компонентов
    ⬜ jsdoc для утилит и хелперов
    ⬜ комментарии для неочевидных мест в коде
    ⬜ прочие инструкции (README.md, contributing.md и др.)
    ⬜ нерелевантно

  3. Изменения корректно типизированы
    ✅ без использования any (см. PR 2856)
    ⬜ нерелевантно

  4. Прочее
    ✅ все тесты и линтеры на CI проходят
    ✅ в коде нет лишних изменений
    ✅ заголовок PR кратко и доступно отражает суть изменений (он попадет в changelog)

@zhzz zhzz changed the title fix(Calendar): update period fix(Calendar): revert period Apr 25, 2024
@zhzz zhzz mentioned this pull request Apr 25, 2024
@zhzz zhzz marked this pull request as ready for review April 27, 2024 08:53
@zhzz zhzz requested a review from lossir April 27, 2024 11:32
packages/react-ui/components/Calendar/Calendar.md Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/CalendarDay.tsx Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/CalendarDay.tsx Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/CalendarDay.tsx Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/CalendarDay.tsx Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/Calendar.tsx Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/DayCellView.tsx Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/Month.tsx Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/Calendar.tsx Outdated Show resolved Hide resolved
@zhzz zhzz requested a review from mshatikhin May 3, 2024 08:28
@zhzz
Copy link
Member Author

zhzz commented May 15, 2024

По поводу CalendarDateShape и InternalDate отпишу тут, в одном месте.

У нас наблюдаются два пересекающийхся по функционалу механизма для работы с датами. Это CalendarDateShape и InternalDate. Я не в курсе всей истории и замыслов их создания. Но по косвенным признакам могу предположить следующее.

InternalDate - это внутренний подкапотный механизм. Он содержит кучу логики, о которой пользователю знать нет нужды. И вроде бы он нигде не торчит наружу.

CalendarDateShape - это публичный механизм. Он явным образом экспортируется из календаря. Он доступен пользователю и ограничен теми функциями, которые могут ему реально понадобиться для манипуляции с датами там, где строки не удобны. Например, для работы с периодами.

Поэтому предлагаю считать CalendarDateShape публичным API, описать его в доке и использовать в примерах только его.

InternalDate лучше оставить только для внутренних нужд компонентов и, когда-нибудь, навести в нем порядок.

@zhzz
Copy link
Member Author

zhzz commented May 15, 2024

По поводу формата месяцев.

Их тоже в компонентах наблюдается два: человеческий и нативный (начинающий отсчет с 0). До сих пор все даты, которые передавал или получал пользователь из контрола, мы старались предлагать исключительно в человеческом формате. Нативный же используется во внутрянке.

В этом ПР появляется еще одно место соприкосновения пользователя с датой. Это проп date в CalendaDay. Изначально я не сильно раздумывал и оставил его в нативном формате. Но после ревью и составления всей картины выше стала очевидна непоследовательность этого API для пользователя.

В итоге, предлагаю CalendaDay, как публичный компонент, тоже перевести на человеческий формат. Это позволяет также совсем избавиться от работы с форматами внутри CalendarDateShape и не заставлять пользователя вообще знать про нативный формат.

@zhzz zhzz requested a review from lossir May 15, 2024 10:10
@lossir
Copy link
Member

lossir commented May 20, 2024

InternalDate появился как альтернатива Moment.js, способная в интернациализацию описанную тут #1277 и в фичи из Гайда.
Тогда большой рефакторинг касался только компонента DateInput и InputLikeText, поэтому в DatePicker и Calendar остались старые решения.

CalendarDateShape это самая первая реализация даты в пакете. В этих хелперах дата представлена совсем абстрактно - буквально объект чисел. Тут нет понятия "нативный формат месяца", или "человеческое отображение даты".

Эти хелперы экспортируется из корня Календаря, и после его опубличивания они тоже стали публичными:

import { isEqual, comparator } from '@skbkontur/react-ui';

В своё время мы отбились от вопросов "почему строка, а не Moment/Date", и теперь могут возникнут вопросы "почему объект, а не Moment/Date".
По-моему правильным решением будет научить InternalDate сравнивать даты для внутреннего использования, и задеприкейтить хэлперы CalendarDateShape.

В идеале будет отрефачить и сам InternakDate, перейдя на нативную дату и Internationalization API.


Если в CalendarDay проп дата будет объектом чисел, то пользователь может сам их сравнивать без каких-либо хелперов.
Если же мы предлагаем ему хэлперы, то думаю не правильно делать в них АПИ отличное от компонентов DateInput, DatePicker и Calendar.

Т.е. я бы предложил проп date в CalendarDay сделать строкой, как и в других компонентах.
И не предоставлять никаких хэлперов пока не будет запроса.

@zhzz
Copy link
Member Author

zhzz commented Jun 5, 2024

Переделал CalendarDay на работу со строкой.

Но публичные функции для сравнения дат уже нужны, т.к. без них выбор периода не сделать, а мы предлагаем такую возможность.

Тогда, чтобы не публичить старый CalendarDateShape, и также не публичить сложный InternalDate, предлагаю завести новый простой набор функций: lib/date/comparison. Под капотом у него пока старый механизм, но его легко можно будет перевести на новый, когда дойдут руки навести порядок.

Совсем отказываться от CalendarDateShape в этом ПРе не стал, потому что он еще используется в нескольких местах. Думаю, лучше это сделать отдельно.

Copy link
Member

@lossir lossir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Согласен, что CalendarDateShape сейчас трогать не надо.

У нас сейчас такая ситуация, что разные общие хэлперы по работе с датами раскиданы по куче файлов:

  1. InternalDate
  2. CalendarDateShape
  3. CalendarUtils
  4. DatePickerHelpers
  5. comparison

Некоторые хэлперы дублируются, некоторые перемешались со специфичными функциями для конкретных компонентов.

Думаю стоит это как-нибудь обсудить и завести задачу по наведению тут порядка.

packages/react-ui/lib/date/InternalDateTransformer.ts Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/CalendarDay.md Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/CalendarDay.md Outdated Show resolved Hide resolved
packages/react-ui/components/Calendar/CalendarDay.tsx Outdated Show resolved Hide resolved
packages/react-ui/lib/date/__tests__/comparison.test.ts Outdated Show resolved Hide resolved
@zhzz
Copy link
Member Author

zhzz commented Jun 5, 2024

Все поправил. И завет задачу на наведение порядка: IF-1781.

@zhzz zhzz requested a review from lossir June 5, 2024 10:25
@zhzz zhzz merged commit f32c251 into 4.17.0/datepicker Jun 5, 2024
7 checks passed
@zhzz zhzz deleted the revert-period-2 branch June 5, 2024 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants