@stoker-platform/web-app 0.5.123 → 0.5.125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @stoker-platform/web-app
2
2
 
3
+ ## 0.5.125
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: improve mobile collection transitions
8
+
9
+ ## 0.5.124
10
+
11
+ ### Patch Changes
12
+
13
+ - feat: use inclusive dates for all day events
14
+
3
15
  ## 0.5.123
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/web-app",
3
- "version": "0.5.123",
3
+ "version": "0.5.125",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "scripts": {
package/src/App.css CHANGED
@@ -1,5 +1,11 @@
1
1
  html,
2
2
  body {
3
+ background-color: #ffffff !important;
4
+ background-image: none !important;
5
+ }
6
+
7
+ html[data-mode="app"],
8
+ html[data-mode="app"] body {
3
9
  background-color: #000000 !important;
4
10
  background-image: none !important;
5
11
  }
package/src/Calendar.tsx CHANGED
@@ -85,6 +85,21 @@ import { useConnection } from "./providers/ConnectionProvider"
85
85
  import { SortingState } from "@tanstack/react-table"
86
86
  import { cn } from "./lib/utils"
87
87
 
88
+ function getExclusiveEnd(inclusiveEnd: Date, timezone: string): Date {
89
+ return DateTime.fromJSDate(inclusiveEnd).setZone(timezone).startOf("day").plus({ days: 1 }).toJSDate()
90
+ }
91
+
92
+ function getInclusiveEnd(exclusiveEnd: Date, timezone: string): Date {
93
+ return DateTime.fromJSDate(exclusiveEnd).setZone(timezone).startOf("day").minus({ days: 1 }).toJSDate()
94
+ }
95
+
96
+ function isAllDayEvent(record: StokerRecord, calendarConfig: CalendarConfig): boolean {
97
+ if (calendarConfig.allDayField !== undefined) {
98
+ return !!record[calendarConfig.allDayField]
99
+ }
100
+ return !!(calendarConfig.fullCalendarLarge?.defaultAllDay || calendarConfig.fullCalendarSmall?.defaultAllDay)
101
+ }
102
+
88
103
  function Row({
89
104
  collection,
90
105
  record,
@@ -655,10 +670,13 @@ export function Calendar({
655
670
  resourceEditable: !isPendingServer && !isUpdateDisabled && hasReourceUpdateAccess,
656
671
  }
657
672
  if (calendarConfig.endField && record[calendarConfig.endField]) {
658
- event.end = record[calendarConfig.endField].toDate()
673
+ const rawEnd = record[calendarConfig.endField].toDate()
674
+ event.end = isAllDayEvent(record, calendarConfig) ? getExclusiveEnd(rawEnd, timezone) : rawEnd
659
675
  }
660
676
  if (calendarConfig.allDayField !== undefined) {
661
677
  event.allDay = record[calendarConfig.allDayField]
678
+ } else if (isAllDayEvent(record, calendarConfig)) {
679
+ event.allDay = true
662
680
  }
663
681
  if (calendarConfig.resourceField && record[calendarConfig.resourceField] !== undefined) {
664
682
  const resource = getResource(labels.collection, record, calendarConfig.resourceField)
@@ -722,6 +740,7 @@ export function Calendar({
722
740
  hasEndUpdateAccess,
723
741
  hasReourceUpdateAccess,
724
742
  isGlobalLoading,
743
+ timezone,
725
744
  ])
726
745
 
727
746
  const updateEvent = useCallback(
@@ -733,10 +752,23 @@ export function Calendar({
733
752
 
734
753
  const updatedFields: Partial<StokerRecord> = {}
735
754
  if (calendarConfig.startField && info.event.start) {
736
- updatedFields[calendarConfig.startField] = Timestamp.fromDate(info.event.start)
755
+ const startDate = info.event.allDay
756
+ ? DateTime.fromJSDate(info.event.start).setZone(timezone).startOf("day").toJSDate()
757
+ : info.event.start
758
+ updatedFields[calendarConfig.startField] = Timestamp.fromDate(startDate)
737
759
  }
738
760
  if (calendarConfig.endField && info.event.start) {
739
- updatedFields[calendarConfig.endField] = Timestamp.fromDate(info.event.end || info.event.start)
761
+ let endDate: Date
762
+ if (info.event.allDay) {
763
+ if (info.event.end) {
764
+ endDate = getInclusiveEnd(info.event.end, timezone)
765
+ } else {
766
+ endDate = DateTime.fromJSDate(info.event.start).setZone(timezone).startOf("day").toJSDate()
767
+ }
768
+ } else {
769
+ endDate = info.event.end ?? info.event.start
770
+ }
771
+ updatedFields[calendarConfig.endField] = Timestamp.fromDate(endDate)
740
772
  }
741
773
  if (calendarConfig.allDayField !== undefined) {
742
774
  updatedFields[calendarConfig.allDayField] = info.event.allDay
@@ -816,7 +848,7 @@ export function Calendar({
816
848
  })
817
849
  }
818
850
  },
819
- [calendarConfig, list, unscheduledRecords, recordTitleField, recordTitle],
851
+ [calendarConfig, list, unscheduledRecords, recordTitleField, recordTitle, timezone],
820
852
  )
821
853
 
822
854
  const createEvent = useCallback(
@@ -1021,7 +1053,14 @@ export function Calendar({
1021
1053
  createEvent({ start: info.date })
1022
1054
  },
1023
1055
  select(info: DateSelectArg) {
1024
- createEvent({ start: info.start, end: info.end })
1056
+ if (info.allDay && info.end) {
1057
+ createEvent({
1058
+ start: info.start,
1059
+ end: getInclusiveEnd(info.end, timezone),
1060
+ })
1061
+ } else {
1062
+ createEvent({ start: info.start, end: info.end })
1063
+ }
1025
1064
  },
1026
1065
  eventInteractive: true,
1027
1066
  height: "auto",
@@ -1687,20 +1687,23 @@ function Collection({
1687
1687
  [recordTitle],
1688
1688
  )
1689
1689
 
1690
- const [showCollection, setShowCollection] = useState(window.innerWidth > 1280)
1691
- useEffect(() => {
1692
- if (isInitialized) {
1693
- setTimeout(() => {
1694
- setShowCollection(true)
1695
- }, 150)
1696
- }
1697
- }, [isInitialized])
1690
+ const willHaveRangeRow = useMemo(() => {
1691
+ return (
1692
+ !formList &&
1693
+ !relationList?.loadAll &&
1694
+ tab !== "calendar" &&
1695
+ (hasRangeFilter ||
1696
+ (isPreloadCacheEnabled && !!preloadCache?.range) ||
1697
+ filters.some((filter) => filter.type === "range") ||
1698
+ (Array.isArray(collection.admin?.filters) &&
1699
+ collection.admin.filters.some((filter) => filter.type === "range")))
1700
+ )
1701
+ }, [formList, relationList, tab, hasRangeFilter, isPreloadCacheEnabled, filters, collection])
1698
1702
 
1699
1703
  if (!permissions.collections?.[labels.collection]) return null
1700
1704
 
1701
1705
  return (
1702
- !collection.singleton &&
1703
- showCollection && (
1706
+ !collection.singleton && (
1704
1707
  <>
1705
1708
  <div
1706
1709
  ref={mainContentRef}
@@ -1826,7 +1829,9 @@ function Collection({
1826
1829
  <Tabs defaultValue="list" onValueChange={onTabChange} value={tab}>
1827
1830
  <div
1828
1831
  className={cn(
1829
- "flex flex-col items-center print:hidden select-none",
1832
+ "flex flex-col items-center justify-between print:hidden select-none",
1833
+ willHaveRangeRow ? "h-[116px]" : "h-[72px]",
1834
+ "lg:h-auto",
1830
1835
  relationList ? "xl:flex-row" : "lg:flex-row",
1831
1836
  )}
1832
1837
  >
@@ -2545,17 +2550,17 @@ function Collection({
2545
2550
  ) : (
2546
2551
  !relationList &&
2547
2552
  (tab === "list" ? (
2548
- <div className="pb-2 pt-[88px] lg:py-2">
2549
- <Card className="min-h-[calc(100vh-88px)] lg:min-h-full lg:h-[calc(100vh-250px)]"></Card>
2553
+ <div className="py-2">
2554
+ <Card className="min-h-screen lg:min-h-full lg:h-[calc(100vh-250px)]"></Card>
2550
2555
  </div>
2551
2556
  ) : tab === "map" ? (
2552
- <div className="pb-2 pt-[88px] lg:py-2">
2553
- <Card className="min-h-[calc(100vh-88px)] lg:min-h-full lg:h-[calc(100vh-204px)]"></Card>
2557
+ <div className="py-2">
2558
+ <Card className="min-h-screen lg:min-h-full lg:h-[calc(100vh-204px)]"></Card>
2554
2559
  </div>
2555
2560
  ) : (
2556
2561
  tab === "calendar" && (
2557
- <div className="pb-2 pt-[44px] lg:py-2">
2558
- <Card className="min-h-[calc(100vh-44px)] lg:min-h-full lg:h-[calc(100vh-204px)]"></Card>
2562
+ <div className="py-2">
2563
+ <Card className="min-h-screen lg:min-h-full lg:h-[calc(100vh-204px)]"></Card>
2559
2564
  </div>
2560
2565
  )
2561
2566
  ))
package/src/Tenant.tsx CHANGED
@@ -60,7 +60,7 @@ import { getFunctions, httpsCallable } from "firebase/functions"
60
60
  import { getApp } from "firebase/app"
61
61
  import { useTheme } from "./components/theme-provider"
62
62
 
63
- const MOBILE_SHEET_CLOSE_MS = 400
63
+ const MOBILE_SHEET_CLOSE_MS = 320
64
64
 
65
65
  function Tenant() {
66
66
  const [dialogContent, setDialogContent] = useDialog()
@@ -290,9 +290,9 @@ function Tenant() {
290
290
 
291
291
  const navigateFromSidebar = useCallback(
292
292
  (path: string) => {
293
- runViewTransition(() => navigate(path))
293
+ setSidebarOpen(false)
294
294
  window.setTimeout(() => {
295
- setSidebarOpen(false)
295
+ runViewTransition(() => navigate(path))
296
296
  }, MOBILE_SHEET_CLOSE_MS)
297
297
  },
298
298
  [navigate],
package/src/main.tsx CHANGED
@@ -89,6 +89,15 @@ function Main() {
89
89
  const [, setDialogContent] = useDialog()
90
90
  const { toast } = useToast()
91
91
 
92
+ useEffect(() => {
93
+ const root = document.documentElement
94
+ if (mode === "app" && !maintenance) {
95
+ root.dataset.mode = "app"
96
+ } else {
97
+ delete root.dataset.mode
98
+ }
99
+ }, [mode, maintenance])
100
+
92
101
  useEffect(() => {
93
102
  if (mode === "maintenance") return
94
103
  const getRoutes = () => {