index.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. if (withTime) {
  101. return formatInTimeZone(
  102. getDateTime(value) || "",
  103. formatConf.forceTZ || !tz ? formatConf.timeZone : tz,
  104. datetimeformat || formatConf.dateTime
  105. );
  106. }
  107. return format(getDateTime(value) || 0, datetimeformat || formatConf.date);
  108. };
  109. export const getNumberString = (value: number, numberformat: string | undefined, formatConf: FormatConfig): string => {
  110. try {
  111. return numberformat || formatConf.number
  112. ? sprintf(numberformat || formatConf.number, value)
  113. : value.toLocaleString();
  114. } catch (e) {
  115. console.warn("getNumberString: " + (e as Error).message || e);
  116. return (
  117. (typeof value === "number" && value.toLocaleString()) ||
  118. (typeof value === "string" && (value as string)) ||
  119. ""
  120. );
  121. }
  122. };
  123. export const getTypeFromDf = (dataType?: string) => {
  124. switch (dataType) {
  125. case "datetime.datetime":
  126. case "datetime.date":
  127. case "datetime.time":
  128. case "date":
  129. case "time":
  130. case "datetime":
  131. return "date";
  132. case "int":
  133. case "float":
  134. return "number";
  135. case "bool":
  136. return "boolean";
  137. }
  138. return dataType;
  139. };
  140. export const formatWSValue = (
  141. value: string | number,
  142. dataType: string | undefined,
  143. dataFormat: string | undefined,
  144. formatConf: FormatConfig
  145. ): string => {
  146. dataType = dataType || typeof value;
  147. switch (dataType) {
  148. case "datetime.datetime":
  149. case "datetime.time":
  150. case "datetime":
  151. case "time":
  152. if (value == "") {
  153. return "";
  154. }
  155. try {
  156. return getDateTimeString(value.toString(), dataFormat, formatConf);
  157. } catch (e) {
  158. console.error(`wrong dateformat "${dataFormat || formatConf.dateTime}"`, e);
  159. }
  160. return getDateTimeString(value.toString(), undefined, formatConf);
  161. case "datetime.date":
  162. case "date":
  163. if (value == "") {
  164. return "";
  165. }
  166. try {
  167. return getDateTimeString(value.toString(), dataFormat, formatConf, undefined, false);
  168. } catch (e) {
  169. console.error(`wrong dateformat "${dataFormat || formatConf.date}"`, e);
  170. }
  171. return getDateTimeString(value.toString(), undefined, formatConf, undefined, false);
  172. case "int":
  173. case "float":
  174. case "number":
  175. if (typeof value === "string") {
  176. if (dataType === "float") {
  177. value = parseFloat(value);
  178. } else {
  179. value = parseInt(value, 10);
  180. }
  181. }
  182. return getNumberString(value, dataFormat, formatConf);
  183. }
  184. return value ? value.toString() : "";
  185. };
  186. export const getInitials = (value: string, max = 2): string =>
  187. (value || "")
  188. .split(" ", max)
  189. .map((word) => (word.length ? word.charAt(0) : ""))
  190. .join("")
  191. .toUpperCase();
  192. export const TIMEZONE_CLIENT = Intl.DateTimeFormat().resolvedOptions().timeZone;
  193. export const getBaseURL = (): string => {
  194. return window.taipyConfig?.baseURL || "/";
  195. };
  196. export const emptyArray = [];