index.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * Copyright 2021-2024 Avaiga Private Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  5. * the License. You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  10. * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11. * specific language governing permissions and limitations under the License.
  12. */
  13. import { toZonedTime, getTimezoneOffset, formatInTimeZone } from "date-fns-tz";
  14. import { format } from "date-fns";
  15. import { sprintf } from "sprintf-js";
  16. import { FormatConfig } from "../context/taipyReducers";
  17. declare global {
  18. interface Window {
  19. taipyConfig: {
  20. darkMode: boolean;
  21. themes: Record<string, Record<string, unknown>>;
  22. timeZone: string;
  23. extensions: Record<string, string[]>;
  24. stylekit?: StyleKit;
  25. baseURL: string;
  26. };
  27. taipyVersion: string;
  28. [key: string]: unknown;
  29. }
  30. }
  31. interface StyleKit {
  32. // Primary and secondary colors
  33. colorPrimary: string;
  34. colorSecondary: string;
  35. // Contextual color
  36. colorError: string;
  37. colorWarning: string;
  38. colorSuccess: string;
  39. // Background and elevation color for LIGHT MODE
  40. colorBackgroundLight: string;
  41. colorPaperLight: string;
  42. // Background and elevation color for DARK MODE
  43. colorBackgroundDark: string;
  44. colorPaperDark: string;
  45. // DEFINING FONTS
  46. // Set main font family
  47. fontFamily: string;
  48. // DEFINING ROOT STYLES
  49. // Set root margin
  50. rootMargin: string;
  51. // DEFINING SHAPES
  52. // Base border radius in px
  53. borderRadius: number;
  54. // DEFINING MUI COMPONENTS STYLES
  55. // Height in css size unit for inputs and buttons
  56. inputButtonHeight: string;
  57. }
  58. // return date with right time and tz
  59. export const getTimeZonedDate = (d: Date, tz: string, withTime: boolean): Date => {
  60. const newDate = d;
  61. // dispatch new date which offset by the timeZone differences between client and server
  62. const hours = getClientServerTimeZoneOffset(tz) / 60;
  63. const minutes = getClientServerTimeZoneOffset(tz) % 60;
  64. newDate.setSeconds(0);
  65. newDate.setMilliseconds(0);
  66. if (withTime) {
  67. // Parse data with selected time if it is a datetime selector
  68. newDate.setHours(newDate.getHours() + hours);
  69. newDate.setMinutes(newDate.getMinutes() + minutes);
  70. } else {
  71. // Parse data with 00:00 UTC time if it is a date selector
  72. newDate.setHours(hours);
  73. newDate.setMinutes(minutes);
  74. }
  75. return newDate;
  76. };
  77. export const dateToString = (d: Date, withTime: boolean = true): string => {
  78. return withTime ? d.toISOString() : d.toDateString();
  79. };
  80. // return client server timeZone offset in minutes
  81. export const getClientServerTimeZoneOffset = (tz: string): number =>
  82. (getTimezoneOffset(TIMEZONE_CLIENT) - getTimezoneOffset(tz)) / 60000;
  83. export const getDateTime = (value: string | null | undefined, tz?: string, withTime = true): Date | null => {
  84. if (value === null || value === undefined) {
  85. return null;
  86. }
  87. try {
  88. return tz && tz !== "Etc/Unknown" && withTime ? toZonedTime(value, tz) : new Date(value);
  89. } catch (e) {
  90. return null;
  91. }
  92. };
  93. export const getDateTimeString = (
  94. value: string,
  95. datetimeformat: string | undefined,
  96. formatConf: FormatConfig,
  97. tz?: string,
  98. withTime: boolean = true
  99. ): string => {
  100. const dateVal = getDateTime(value);
  101. try {
  102. if (withTime) {
  103. return formatInTimeZone(
  104. dateVal || "",
  105. formatConf.forceTZ || !tz ? formatConf.timeZone : tz,
  106. datetimeformat || formatConf.dateTime,
  107. { useAdditionalDayOfYearTokens: true }
  108. );
  109. }
  110. return format(dateVal || 0, datetimeformat || formatConf.date, { useAdditionalDayOfYearTokens: true });
  111. } catch (e) {
  112. console.warn("Invalid date format:", (e as Error).message || e);
  113. return `${dateVal}`;
  114. }
  115. };
  116. export const getNumberString = (value: number, numberformat: string | undefined, formatConf: FormatConfig): string => {
  117. try {
  118. return numberformat || formatConf.number
  119. ? sprintf(numberformat || formatConf.number, value)
  120. : value.toLocaleString();
  121. } catch (e) {
  122. console.warn("Invalid number format:", (e as Error).message || e);
  123. return (
  124. (typeof value === "number" && value.toLocaleString()) ||
  125. (typeof value === "string" && (value as string)) ||
  126. ""
  127. );
  128. }
  129. };
  130. export const getTypeFromDf = (dataType?: string) => {
  131. switch (dataType) {
  132. case "datetime.datetime":
  133. case "datetime.date":
  134. case "datetime.time":
  135. case "date":
  136. case "time":
  137. case "datetime":
  138. return "date";
  139. case "int":
  140. case "float":
  141. return "number";
  142. case "bool":
  143. return "boolean";
  144. }
  145. return dataType;
  146. };
  147. export const formatWSValue = (
  148. value: string | number,
  149. dataType: string | undefined,
  150. dataFormat: string | undefined,
  151. formatConf: FormatConfig
  152. ): string => {
  153. dataType = dataType || typeof value;
  154. switch (dataType) {
  155. case "datetime.datetime":
  156. case "datetime.time":
  157. case "datetime":
  158. case "time":
  159. if (value == "") {
  160. return "";
  161. }
  162. return getDateTimeString(value.toString(), dataFormat, formatConf);
  163. case "datetime.date":
  164. case "date":
  165. if (value == "") {
  166. return "";
  167. }
  168. return getDateTimeString(value.toString(), dataFormat, formatConf, undefined, false);
  169. case "int":
  170. case "float":
  171. case "number":
  172. if (typeof value === "string") {
  173. if (dataType === "float") {
  174. value = parseFloat(value);
  175. } else {
  176. value = parseInt(value, 10);
  177. }
  178. }
  179. return getNumberString(value, dataFormat, formatConf);
  180. }
  181. return value ? value.toString() : "";
  182. };
  183. export const getInitials = (value: string, max = 2): string =>
  184. (value || "")
  185. .split(" ", max)
  186. .map((word) => (word.length ? word.charAt(0) : ""))
  187. .join("")
  188. .toUpperCase();
  189. export const TIMEZONE_CLIENT = Intl.DateTimeFormat().resolvedOptions().timeZone;
  190. export const getBaseURL = (): string => {
  191. return window.taipyConfig?.baseURL || "/";
  192. };
  193. export const emptyArray = [];