dataManager.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. export type ModuleData = Record<string, VarName>;
  2. export type VarName = Record<string, VarData>;
  3. export interface VarData {
  4. type: string;
  5. value: unknown;
  6. encoded_name: string;
  7. data_update: boolean;
  8. }
  9. type ColumnName = string;
  10. export type RequestDataOptions = {
  11. columns?: Array<ColumnName>;
  12. pagekey?: string;
  13. alldata?: boolean;
  14. start?: number;
  15. end?: number;
  16. filters?: Array<{ col: ColumnName; value: string | boolean | number; action: string }>;
  17. aggregates?: Array<ColumnName>;
  18. applies?: { [key: ColumnName]: string };
  19. infinite?: boolean;
  20. reverse?: boolean;
  21. orderby?: ColumnName;
  22. sort?: "asc" | "desc";
  23. styles?: { [key: ColumnName]: string };
  24. tooltips?: { [key: ColumnName]: string };
  25. handlenan?: boolean;
  26. compare_datas?: string;
  27. };
  28. type RequestDataEntry = {
  29. options: RequestDataOptions;
  30. receivedData: unknown;
  31. }
  32. export const getRequestedDataKey = (payload?: unknown) =>
  33. (!!payload && typeof payload == "object" && "pagekey" in payload && (payload["pagekey"] as string)) || undefined;
  34. // This class hold the information of variables and real-time value of variables
  35. export class DataManager {
  36. // key: encoded name, value: real-time value
  37. _data: Record<string, unknown>;
  38. // Initial data fetched from taipy-gui backend
  39. _init_data: ModuleData;
  40. // key: encodedName -> dataEventKey -> requeste data
  41. _requested_data: Record<string, Record<string, RequestDataEntry>>;
  42. constructor(variableModuleData: ModuleData) {
  43. this._data = {};
  44. this._init_data = {};
  45. this._requested_data = {};
  46. this.init(variableModuleData);
  47. }
  48. init(variableModuleData: ModuleData) {
  49. // Identify changes between the new and old data
  50. const changes: ModuleData = {};
  51. for (const context in this._init_data) {
  52. if (!(context in variableModuleData)) {
  53. changes[context] = this._init_data[context];
  54. continue;
  55. }
  56. for (const variable in this._init_data[context]) {
  57. if (!(variable in variableModuleData[context])) {
  58. if (!(context in changes)) {
  59. changes[context] = {};
  60. }
  61. changes[context][variable] = this._init_data[context][variable];
  62. }
  63. }
  64. }
  65. if (Object.keys(changes).length !== 0) {
  66. console.error("Unmatched data tree! Removed changes: ", changes);
  67. }
  68. // Reset the initial data
  69. this._init_data = variableModuleData;
  70. this._data = {};
  71. for (const context in this._init_data) {
  72. for (const variable in this._init_data[context]) {
  73. const vData = this._init_data[context][variable];
  74. this._data[vData["encoded_name"]] = vData.value;
  75. }
  76. }
  77. return changes;
  78. }
  79. getEncodedName(varName: string, module: string): string | undefined {
  80. if (module in this._init_data && varName in this._init_data[module]) {
  81. return this._init_data[module][varName].encoded_name;
  82. }
  83. return undefined;
  84. }
  85. // return [name, moduleName]
  86. getName(encodedName: string): [string, string] | undefined {
  87. for (const context in this._init_data) {
  88. for (const variable in this._init_data[context]) {
  89. const vData = this._init_data[context][variable];
  90. if (vData.encoded_name === encodedName) {
  91. return [variable, context];
  92. }
  93. }
  94. }
  95. return undefined;
  96. }
  97. get(encodedName: string, dataEventKey?: string): unknown {
  98. // handle requested data
  99. if (dataEventKey) {
  100. if (!(encodedName in this._requested_data)) {
  101. throw new Error(`Encoded name '${encodedName}' is not available in Taipy GUI`);
  102. }
  103. if (!(dataEventKey in this._requested_data[encodedName])) {
  104. throw new Error(`Event key '${dataEventKey}' is not available for encoded name '${encodedName}' in Taipy GUI`);
  105. }
  106. return this._requested_data[encodedName][dataEventKey].receivedData;
  107. }
  108. // handle normal data
  109. if (!(encodedName in this._data)) {
  110. throw new Error(`${encodedName} is not available in Taipy GUI`);
  111. }
  112. return this._data[encodedName];
  113. }
  114. addRequestDataOptions(encodedName: string, dataEventKey: string, options: RequestDataOptions) {
  115. if (!(encodedName in this._requested_data)) {
  116. this._requested_data[encodedName] = {};
  117. }
  118. // This would overrides object with the same key
  119. this._requested_data[encodedName][dataEventKey] = { options: options, receivedData: undefined };
  120. }
  121. getInfo(encodedName: string): VarData | undefined {
  122. for (const context in this._init_data) {
  123. for (const variable in this._init_data[context]) {
  124. const vData = this._init_data[context][variable];
  125. if (vData.encoded_name === encodedName) {
  126. return { ...vData, value: this._data[encodedName] };
  127. }
  128. }
  129. }
  130. return undefined;
  131. }
  132. getDataTree(): ModuleData {
  133. return this._init_data;
  134. }
  135. getAllData(): Record<string, unknown> {
  136. return this._data;
  137. }
  138. update(encodedName: string, value: unknown, dataEventKey?: string) {
  139. // handle requested data
  140. if (dataEventKey) {
  141. if (!(encodedName in this._requested_data)) {
  142. throw new Error(`Encoded name '${encodedName}' is not available in Taipy GUI`);
  143. }
  144. if (!(dataEventKey in this._requested_data[encodedName])) {
  145. throw new Error(`Event key '${dataEventKey}' is not available for encoded name '${encodedName}' in Taipy GUI`);
  146. }
  147. this._requested_data[encodedName][dataEventKey].receivedData = value;
  148. return;
  149. }
  150. // handle normal data
  151. if (!(encodedName in this._data)) {
  152. throw new Error(`${encodedName} is not available in Taipy Gui`);
  153. }
  154. this._data[encodedName] = value;
  155. }
  156. deleteRequestedData(encodedName: string, dataEventKey: string) {
  157. if (encodedName in this._requested_data && dataEventKey in this._requested_data[encodedName]) {
  158. delete this._requested_data[encodedName][dataEventKey];
  159. }
  160. }
  161. }