@adaptabletools/adaptable-plugin-ipushpull 22.0.1-canary.3 → 22.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptabletools/adaptable-plugin-ipushpull",
3
- "version": "22.0.1-canary.3",
3
+ "version": "22.0.2",
4
4
  "description": "",
5
5
  "homepage": "http://www.adaptabletools.com/",
6
6
  "author": {
@@ -9,12 +9,10 @@
9
9
  },
10
10
  "typings": "src/index.d.ts",
11
11
  "dependencies": {
12
- "ipushpull-js": "^2.25.0",
13
12
  "react": "^18.0.0 || ^19.0.0",
14
13
  "react-redux": "^9.2.0",
15
14
  "redux": "^5.0.1",
16
15
  "styled-components": "^4.4.1",
17
- "tinycolor2": "^1.4.2",
18
16
  "tslib": "^2.8.1"
19
17
  },
20
18
  "type": "module",
@@ -1,8 +1,9 @@
1
1
  import { ApiBase } from '@adaptabletools/adaptable/src/Api/Implementation/ApiBase';
2
2
  import { IPushPullDomain, IPushPullReport, IPushPullSchedule } from '@adaptabletools/adaptable/src/AdaptableState/IPushPullState';
3
3
  import { IPushPullApi } from '@adaptabletools/adaptable/src/Api/IPushPullApi';
4
- import { IPushPullPluginOptions } from '@adaptabletools/adaptable/src/AdaptableOptions/IPushPullPluginOptions';
4
+ import { IPushPullPluginOptions } from './IPushPullPluginOptions';
5
5
  import { IAdaptable } from '@adaptabletools/adaptable/src/AdaptableInterfaces/IAdaptable';
6
+ import { IPushPullClient } from './ipushpull-client';
6
7
  export declare class IPushPullApiImpl extends ApiBase implements IPushPullApi {
7
8
  private ippInstance;
8
9
  private ippService;
@@ -14,8 +15,8 @@ export declare class IPushPullApiImpl extends ApiBase implements IPushPullApi {
14
15
  getIPushPullPassword(): string | undefined;
15
16
  getAutoLogin(): boolean;
16
17
  getCurrentLiveIPushPullReport(): IPushPullReport | undefined;
17
- setIPushPullInstance(ippInstance: any): void;
18
- getIPushPullInstance(): any;
18
+ setIPushPullInstance(ippInstance: IPushPullClient): void;
19
+ getIPushPullInstance(): IPushPullClient | null;
19
20
  sendSnapshot(iPushPullReport: IPushPullReport): void;
20
21
  startLiveData(iPushPullReport: IPushPullReport): void;
21
22
  stopLiveData(): void;
@@ -4,7 +4,7 @@ import * as IPushPullRedux from './Redux/ActionReducers/IPushPullRedux';
4
4
  import ArrayExtensions from '@adaptabletools/adaptable/src/Utilities/Extensions/ArrayExtensions';
5
5
  import Helper from '@adaptabletools/adaptable/src/Utilities/Helpers/Helper';
6
6
  export class IPushPullApiImpl extends ApiBase {
7
- ippInstance;
7
+ ippInstance = null;
8
8
  ippService = null;
9
9
  options;
10
10
  constructor(_adaptable, options) {
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Connection config for the ipushpull REST API.
3
+ *
4
+ * Only `api_key` and `api_secret` are required -- `api_url` defaults to the
5
+ * ipushpull test environment (`https://test.ipushpull.com/api/1.0`).
6
+ */
7
+ export interface IPushPullConfig {
8
+ /**
9
+ * Base URL for the ipushpull REST API
10
+ *
11
+ * @defaultValue 'https://test.ipushpull.com/api/1.0'
12
+ */
13
+ api_url?: string;
14
+ /** OAuth Client ID */
15
+ api_key: string;
16
+ /** OAuth Client Secret */
17
+ api_secret: string;
18
+ }
19
+ /**
20
+ * Options available in ipushpull plugin; allows users to collaborate and share data in powerful ways
21
+ */
22
+ export interface IPushPullPluginOptions {
23
+ /**
24
+ * The config required to run ipushpull; use your ipushpull credentials
25
+ */
26
+ ippConfig?: IPushPullConfig;
27
+ /**
28
+ * User's ipushpull user name (usually email address); if supplied, pre-populates the login screen's username textbox
29
+ */
30
+ username?: string;
31
+ /**
32
+ * The user's ipushpull password; if supplied, pre-populates the login screen's password textbox
33
+ */
34
+ password?: string;
35
+ /**
36
+ * How many miliseconds AdapTable should throttle when sending data updates to ipushpull
37
+ *
38
+ * @defaultValue 2000
39
+ */
40
+ throttleTime?: number;
41
+ /**
42
+ * Whether AdapTable should try log in to ipushpull automatically at start-up
43
+ *
44
+ * @defaultValue false
45
+ */
46
+ autoLogin?: boolean;
47
+ /**
48
+ * Whether AdapTable will include System Reports (e.g. 'All Data', 'Selected Cells' etc) in the ipushpull toolbar dropdown
49
+ *
50
+ * @defaultValue true
51
+ */
52
+ includeSystemReports?: boolean;
53
+ /**
54
+ * The color theme to use when styling data pushed to ipushpull pages
55
+ *
56
+ * @defaultValue derived from Adaptable's current theme (lightTheme or darkTheme)
57
+ */
58
+ cellStyles?: 'lightTheme' | 'darkTheme';
59
+ }
@@ -16,60 +16,58 @@ export class PushPullModule extends AdaptableModuleBase {
16
16
  setTimeout(() => {
17
17
  this.throttledRecomputeAndSendLiveDataEvent = throttle(() => this.sendNewLiveData(), this.getThrottleTimeFromState());
18
18
  }, 1000);
19
- if (this.getIPPApi().isIPushPullRunning()) {
20
- // if a piece of data has updated then update any live reports except cell or row selected where the data change is relevant
21
- // currently we DONT send deltas - we simply send everything to ipushpull every time a relevant change happens
22
- this.api.internalApi
23
- .getDataService()
24
- .on('CellDataChanged', (cellDataChangedInfo) => {
25
- const api = this.getIPPApi();
26
- const exportApi = this.api.exportApi;
27
- if (api.isIPushPullLiveDataRunning()) {
28
- let currentLiveIPushPullReport = api.getCurrentLiveIPushPullReport();
29
- if (currentLiveIPushPullReport &&
30
- currentLiveIPushPullReport.ReportName !== SELECTED_DATA_REPORT &&
31
- exportApi.internalApi.isDataChangeInReport(cellDataChangedInfo, this.getCurrentReport())) {
32
- this.throttledRecomputeAndSendLiveDataEvent();
33
- }
34
- }
35
- });
36
- // if the grid has refreshed then update all live reports
37
- this.adaptable._on('GridRefreshed', () => {
38
- if (this.getIPPApi().isIPushPullLiveDataRunning()) {
19
+ // if a piece of data has updated then update any live reports except cell or row selected where the data change is relevant
20
+ // currently we DONT send deltas - we simply send everything to ipushpull every time a relevant change happens
21
+ this.api.internalApi
22
+ .getDataService()
23
+ .on('CellDataChanged', (cellDataChangedInfo) => {
24
+ const api = this.getIPPApi();
25
+ const exportApi = this.api.exportApi;
26
+ if (api.isIPushPullLiveDataRunning()) {
27
+ let currentLiveIPushPullReport = api.getCurrentLiveIPushPullReport();
28
+ if (currentLiveIPushPullReport &&
29
+ currentLiveIPushPullReport.ReportName !== SELECTED_DATA_REPORT &&
30
+ exportApi.internalApi.isDataChangeInReport(cellDataChangedInfo, this.getCurrentReport())) {
39
31
  this.throttledRecomputeAndSendLiveDataEvent();
40
32
  }
41
- });
42
- // if the grid filters have changed then update any live reports except cell or row selected
43
- this.adaptable._on('AdapTableFiltersApplied', () => {
44
- // Rerun all reports except selected cells / rows when filter changes
45
- if (this.getIPPApi().isIPushPullLiveDataRunning()) {
46
- let currentLiveIPushPullReport = this.getIPPApi().getCurrentLiveIPushPullReport();
47
- if (currentLiveIPushPullReport &&
48
- currentLiveIPushPullReport.ReportName !== SELECTED_DATA_REPORT) {
49
- this.throttledRecomputeAndSendLiveDataEvent();
50
- }
33
+ }
34
+ });
35
+ // if the grid has refreshed then update all live reports
36
+ this.adaptable._on('GridRefreshed', () => {
37
+ if (this.getIPPApi().isIPushPullLiveDataRunning()) {
38
+ this.throttledRecomputeAndSendLiveDataEvent();
39
+ }
40
+ });
41
+ // if the grid filters have changed then update any live reports except cell or row selected
42
+ this.adaptable._on('AdapTableFiltersApplied', () => {
43
+ // Rerun all reports except selected cells / rows when filter changes
44
+ if (this.getIPPApi().isIPushPullLiveDataRunning()) {
45
+ let currentLiveIPushPullReport = this.getIPPApi().getCurrentLiveIPushPullReport();
46
+ if (currentLiveIPushPullReport &&
47
+ currentLiveIPushPullReport.ReportName !== SELECTED_DATA_REPORT) {
48
+ this.throttledRecomputeAndSendLiveDataEvent();
51
49
  }
52
- });
53
- // if grid selection has changed and the ipushpull Live report is 'Selected Cells' or 'Selected Rows' then send updated data
54
- this.api.eventApi.on('CellSelectionChanged', () => {
55
- if (this.getIPPApi().isIPushPullLiveDataRunning()) {
56
- let currentLiveIPushPullReport = this.getIPPApi().getCurrentLiveIPushPullReport();
57
- if (currentLiveIPushPullReport &&
58
- currentLiveIPushPullReport.ReportName === SELECTED_DATA_REPORT) {
59
- this.throttledRecomputeAndSendLiveDataEvent();
60
- }
50
+ }
51
+ });
52
+ // if grid selection has changed and the ipushpull Live report is 'Selected Cells' or 'Selected Rows' then send updated data
53
+ this.api.eventApi.on('CellSelectionChanged', () => {
54
+ if (this.getIPPApi().isIPushPullLiveDataRunning()) {
55
+ let currentLiveIPushPullReport = this.getIPPApi().getCurrentLiveIPushPullReport();
56
+ if (currentLiveIPushPullReport &&
57
+ currentLiveIPushPullReport.ReportName === SELECTED_DATA_REPORT) {
58
+ this.throttledRecomputeAndSendLiveDataEvent();
61
59
  }
62
- });
63
- this.api.eventApi.on('RowSelectionChanged', () => {
64
- if (this.getIPPApi().isIPushPullLiveDataRunning()) {
65
- let currentLiveIPushPullReport = this.getIPPApi().getCurrentLiveIPushPullReport();
66
- if (currentLiveIPushPullReport &&
67
- currentLiveIPushPullReport.ReportName === SELECTED_DATA_REPORT) {
68
- this.throttledRecomputeAndSendLiveDataEvent();
69
- }
60
+ }
61
+ });
62
+ this.api.eventApi.on('RowSelectionChanged', () => {
63
+ if (this.getIPPApi().isIPushPullLiveDataRunning()) {
64
+ let currentLiveIPushPullReport = this.getIPPApi().getCurrentLiveIPushPullReport();
65
+ if (currentLiveIPushPullReport &&
66
+ currentLiveIPushPullReport.ReportName === SELECTED_DATA_REPORT) {
67
+ this.throttledRecomputeAndSendLiveDataEvent();
70
68
  }
71
- });
72
- }
69
+ }
70
+ });
73
71
  });
74
72
  }
75
73
  getViewAccessLevel() {
@@ -0,0 +1,39 @@
1
+ import { IAdaptable } from '@adaptabletools/adaptable/src/AdaptableInterfaces/IAdaptable';
2
+ import { IIPushPullService } from './Interface/IIPushPullService';
3
+ import { IPushPullDomain } from '@adaptabletools/adaptable/src/AdaptableState/InternalState';
4
+ import { IPushPullPluginOptions } from '../../IPushPullPluginOptions';
5
+ export declare enum ServiceStatus {
6
+ Unknown = "Unknown",
7
+ Disconnected = "Disconnected",
8
+ Connected = "Connected",
9
+ Error = "Error"
10
+ }
11
+ export declare class IPushPullService implements IIPushPullService {
12
+ adaptable: IAdaptable;
13
+ private client;
14
+ private status;
15
+ private cellStylesOption;
16
+ private pages;
17
+ private pageNameToId;
18
+ private folderNameToId;
19
+ constructor(adaptable: IAdaptable, cellStyles?: IPushPullPluginOptions['cellStyles']);
20
+ getIPushPullStatus(): ServiceStatus;
21
+ private getIPPApi;
22
+ /**
23
+ * Derives the IPushPull theme from Adaptable's current theme at call-time,
24
+ * respecting the 'os' theme by checking `prefers-color-scheme`.
25
+ */
26
+ private deriveDefaultTheme;
27
+ /**
28
+ * Returns the resolved IPushPull theme, honouring the `cellStyles` option.
29
+ * If `cellStyles` is a string, it's used directly.
30
+ * If not set, the theme is derived from Adaptable's current theme.
31
+ */
32
+ private getResolvedTheme;
33
+ login(login: string, password: string): Promise<any>;
34
+ getDomainPages(): Promise<IPushPullDomain[]>;
35
+ loadPage(folderIPP: string, pageIPP: string): Promise<void>;
36
+ unloadPage(page: string): void;
37
+ addNewPage(folderId: number, page: string): Promise<any>;
38
+ pushData(page: string, data: any[]): Promise<void>;
39
+ }
@@ -0,0 +1,202 @@
1
+ import StringExtensions from '@adaptabletools/adaptable/src/Utilities/Extensions/StringExtensions';
2
+ import { buildPageContentPayload, getThemeStyles, } from '../../ipushpull-client';
3
+ export var ServiceStatus;
4
+ (function (ServiceStatus) {
5
+ ServiceStatus["Unknown"] = "Unknown";
6
+ ServiceStatus["Disconnected"] = "Disconnected";
7
+ ServiceStatus["Connected"] = "Connected";
8
+ ServiceStatus["Error"] = "Error";
9
+ })(ServiceStatus || (ServiceStatus = {}));
10
+ export class IPushPullService {
11
+ adaptable;
12
+ client = null;
13
+ status = ServiceStatus.Unknown;
14
+ cellStylesOption;
15
+ pages = new Map();
16
+ pageNameToId = new Map();
17
+ folderNameToId = new Map();
18
+ constructor(adaptable, cellStyles) {
19
+ this.adaptable = adaptable;
20
+ this.adaptable = adaptable;
21
+ this.cellStylesOption = cellStyles;
22
+ this.adaptable.api.eventApi.on('AdaptableReady', async () => {
23
+ this.getIPPApi().clearIPushPullInternalState();
24
+ this.getIPPApi().setIPushPullAvailableOff();
25
+ if (!this.client) {
26
+ let instance = this.getIPPApi().getIPushPullInstance();
27
+ if (instance) {
28
+ this.client = instance;
29
+ this.getIPPApi().setIPushPullAvailableOn();
30
+ let autoLogin = this.getIPPApi().getAutoLogin();
31
+ if (autoLogin) {
32
+ let userName = this.getIPPApi().getIPushPullUsername();
33
+ let password = this.getIPPApi().getIPushPullPassword();
34
+ if (StringExtensions.IsNotNullOrEmpty(userName) &&
35
+ StringExtensions.IsNotNullOrEmpty(password)) {
36
+ try {
37
+ this.getIPPApi().loginToIPushPull(userName, password);
38
+ }
39
+ catch (err) {
40
+ this.getIPPApi().setIPushPullRunningOff();
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ });
47
+ }
48
+ getIPushPullStatus() {
49
+ if (!this.client) {
50
+ return ServiceStatus.Error;
51
+ }
52
+ return this.status;
53
+ }
54
+ getIPPApi() {
55
+ return this.adaptable.api.pluginsApi.getipushpullPluginApi();
56
+ }
57
+ /**
58
+ * Derives the IPushPull theme from Adaptable's current theme at call-time,
59
+ * respecting the 'os' theme by checking `prefers-color-scheme`.
60
+ */
61
+ deriveDefaultTheme() {
62
+ const themeName = this.adaptable.api.themeApi.getCurrentTheme();
63
+ if (themeName === 'os') {
64
+ const preferred = this.adaptable.api.themeApi.internalApi.getDOMPreferredColorScheme();
65
+ return preferred === 'dark' ? 'darkTheme' : 'lightTheme';
66
+ }
67
+ const themeObj = this.adaptable.api.themeApi.getCurrentThemeObject();
68
+ if (themeObj?.Variant === 'dark') {
69
+ return 'darkTheme';
70
+ }
71
+ if (themeName === 'dark') {
72
+ return 'darkTheme';
73
+ }
74
+ return 'lightTheme';
75
+ }
76
+ /**
77
+ * Returns the resolved IPushPull theme, honouring the `cellStyles` option.
78
+ * If `cellStyles` is a string, it's used directly.
79
+ * If not set, the theme is derived from Adaptable's current theme.
80
+ */
81
+ getResolvedTheme() {
82
+ const defaultCellStyles = this.deriveDefaultTheme();
83
+ if (!this.cellStylesOption) {
84
+ return defaultCellStyles;
85
+ }
86
+ return this.cellStylesOption;
87
+ }
88
+ async login(login, password) {
89
+ if (!this.client) {
90
+ return Promise.reject('No ipushpull instance found!');
91
+ }
92
+ try {
93
+ const result = await this.client.login(login, password);
94
+ this.status = ServiceStatus.Connected;
95
+ this.adaptable.logger.success('Logged in to ipushpull.');
96
+ return result;
97
+ }
98
+ catch (err) {
99
+ this.status = ServiceStatus.Error;
100
+ const message = err.data ? err.data.error_description || err.message : err.message;
101
+ this.getIPPApi().setIPushPullLoginErrorMessage(message);
102
+ throw message;
103
+ }
104
+ }
105
+ async getDomainPages() {
106
+ if (!this.client) {
107
+ return Promise.reject('No ipushpull instance found.');
108
+ }
109
+ try {
110
+ const domains = await this.client.getDomainsAndPages();
111
+ this.adaptable.logger.success('Retrieved ipushpull folder and page info.');
112
+ this.folderNameToId.clear();
113
+ this.pageNameToId.clear();
114
+ const result = domains.map((domain) => {
115
+ this.folderNameToId.set(domain.name, domain.id);
116
+ const writablePages = domain.pages
117
+ .filter((page) => page.special_page_type == 0 && page.write_access)
118
+ .map((page) => {
119
+ this.pageNameToId.set(`${domain.name}/${page.name}`, page.id);
120
+ return page.name;
121
+ });
122
+ return {
123
+ Name: domain.name,
124
+ FolderId: domain.id,
125
+ Pages: writablePages,
126
+ };
127
+ });
128
+ return result;
129
+ }
130
+ catch (error) {
131
+ this.adaptable.logger.error('Failed to retrieve folders and pages from ipushpull.', error);
132
+ throw error.message ?? error;
133
+ }
134
+ }
135
+ async loadPage(folderIPP, pageIPP) {
136
+ if (!this.client) {
137
+ return Promise.reject('No ipushpull instance found.');
138
+ }
139
+ const folderId = this.folderNameToId.get(folderIPP);
140
+ const pageId = this.pageNameToId.get(`${folderIPP}/${pageIPP}`);
141
+ if (folderId == null || pageId == null) {
142
+ throw new Error(`Could not resolve IDs for folder "${folderIPP}" / page "${pageIPP}".`);
143
+ }
144
+ await this.client.getPageContent(folderId, pageId);
145
+ this.pages.set(pageIPP, { folderId, pageId });
146
+ this.adaptable.logger.info(`Page ready: "${pageIPP}".`);
147
+ }
148
+ unloadPage(page) {
149
+ if (this.pages.has(page)) {
150
+ this.pages.delete(page);
151
+ this.adaptable.logger.info(`Page unloaded: "${page}".`);
152
+ }
153
+ }
154
+ async addNewPage(folderId, page) {
155
+ if (!this.client) {
156
+ return Promise.reject('No ipushpull instance found.');
157
+ }
158
+ try {
159
+ await this.client.createPage(folderId, page);
160
+ let message = `Page "${page}" created successfully.`;
161
+ this.adaptable.api.alertApi.showAlertSuccess('ipushpull', message);
162
+ this.adaptable.api.internalApi.hidePopupScreen();
163
+ return this.getIPPApi().retrieveIPushPullDomainsFromIPushPull();
164
+ }
165
+ catch (err) {
166
+ this.adaptable.logger.error(`Failed to create page "${page}": ${err}`);
167
+ }
168
+ }
169
+ async pushData(page, data) {
170
+ const pageRef = this.pages.get(page);
171
+ if (!pageRef || !this.client) {
172
+ throw new Error(`Page "${page}" is not loaded or client is not available.`);
173
+ }
174
+ const themeStyles = getThemeStyles(this.getResolvedTheme());
175
+ const cellData = data.map((row, rowIndex) => row.map((cell) => {
176
+ let style;
177
+ if (rowIndex === 0) {
178
+ style = themeStyles.headerStyle;
179
+ }
180
+ else if (rowIndex % 2 === 1) {
181
+ style = themeStyles.rowStyle;
182
+ }
183
+ else {
184
+ style = themeStyles.altRowStyle;
185
+ }
186
+ return {
187
+ value: cell,
188
+ formatted_value: cell,
189
+ style,
190
+ };
191
+ }));
192
+ const payload = buildPageContentPayload(cellData);
193
+ try {
194
+ await this.client.updatePageContent(pageRef.folderId, pageRef.pageId, payload);
195
+ this.adaptable.logger.success(`Data pushed for ipushpull page "${page}".`);
196
+ }
197
+ catch (err) {
198
+ this.adaptable.logger.error(`Failed to push data for ipushpull page "${page}".`);
199
+ throw err;
200
+ }
201
+ }
202
+ }
@@ -1,6 +1,6 @@
1
- import { ServiceStatus } from '../PushPullService';
1
+ import { ServiceStatus } from '../IPushPullService';
2
2
  import { IPushPullDomain } from '@adaptabletools/adaptable/src/AdaptableState/InternalState';
3
- export interface IPushPullService {
3
+ export interface IIPushPullService {
4
4
  login(login: string, password: string): Promise<any>;
5
5
  getDomainPages(): Promise<IPushPullDomain[]>;
6
6
  loadPage(folderIPP: string, pageIPP: string): Promise<void>;
@@ -6,7 +6,6 @@ import { StringExtensions } from '@adaptabletools/adaptable/src/Utilities/Extens
6
6
  import FormLayout, { FormRow } from '@adaptabletools/adaptable/src/components/FormLayout';
7
7
  import Input from '@adaptabletools/adaptable/src/components/Input';
8
8
  import SimpleButton from '@adaptabletools/adaptable/src/components/SimpleButton';
9
- import FlexWithFooter from '@adaptabletools/adaptable/src/components/FlexWithFooter';
10
9
  import { PanelWithImage } from '@adaptabletools/adaptable/src/View/Components/Panels/PanelWithImage';
11
10
  import { usePopupContext } from '@adaptabletools/adaptable/src/View/Components/Popups/AdaptablePopup/PopupContext';
12
11
  import ErrorBox from '@adaptabletools/adaptable/src/components/ErrorBox';
@@ -60,20 +59,11 @@ const IPushPullAddPageComponent = (props) => {
60
59
  value: iPushPullDomain.Name,
61
60
  };
62
61
  });
63
- return (React.createElement(PanelWithImage, { header: "Add ipushpull Page", glyphicon: "newpage", variant: "primary", style: { height: '100%' } },
64
- React.createElement(FlexWithFooter, { as: "form", onSubmit: (e) => {
62
+ return (React.createElement(PanelWithImage, { header: "Add ipushpull Page", glyphicon: "newpage", variant: "primary" },
63
+ React.createElement("form", { onSubmit: (e) => {
65
64
  e.preventDefault();
66
65
  onSubmit();
67
- }, footerProps: {
68
- className: 'twa:text-4',
69
- }, footer: React.createElement(React.Fragment, null,
70
- React.createElement(SimpleButton, { tone: "neutral", variant: "text", tooltip: "Close", onClick: (e) => {
71
- e.stopPropagation();
72
- hidePopup();
73
- } }, "CLOSE"),
74
- React.createElement("div", { style: { flex: 1 } }),
75
- React.createElement(SimpleButton, { tone: "accent", variant: "raised", type: "submit", disabled: StringExtensions.IsNullOrEmpty(state.Folder) ||
76
- StringExtensions.IsNullOrEmpty(state.Page), icon: 'check' }, "Add Page")) },
66
+ } },
77
67
  React.createElement(Flex, { flexDirection: "column", className: "twa:p-2 twa:m-2" },
78
68
  React.createElement(HelpBlock, { className: "twa:mb-1" }, "Select a folder and then choose the name of the new ipushpull page it should contain."),
79
69
  React.createElement(FormLayout, { className: "twa:m-3" },
@@ -82,7 +72,14 @@ const IPushPullAddPageComponent = (props) => {
82
72
  React.createElement(FormRow, { label: "Page" },
83
73
  React.createElement(Input, { className: "twa:w-1/2", type: "text", placeholder: "Page Name", value: state.Page, onChange: onPageNameChange })),
84
74
  state.ErrorMessage ? (React.createElement(FormRow, { label: "" },
85
- React.createElement(ErrorBox, null, state.ErrorMessage))) : null)))));
75
+ React.createElement(ErrorBox, null, state.ErrorMessage))) : null)),
76
+ React.createElement(Flex, { className: "twa:p-2", justifyContent: "space-between" },
77
+ React.createElement(SimpleButton, { tone: "neutral", variant: "outlined", tooltip: "Close", onClick: (e) => {
78
+ e.stopPropagation();
79
+ hidePopup();
80
+ } }, "CLOSE"),
81
+ React.createElement(SimpleButton, { tone: "accent", variant: "raised", type: "submit", disabled: StringExtensions.IsNullOrEmpty(state.Folder) ||
82
+ StringExtensions.IsNullOrEmpty(state.Page), icon: 'check' }, "Add Page")))));
86
83
  };
87
84
  function mapStateToProps(state) {
88
85
  return {
@@ -7,7 +7,6 @@ import { StringExtensions } from '@adaptabletools/adaptable/src/Utilities/Extens
7
7
  import FormLayout, { FormRow } from '@adaptabletools/adaptable/src/components/FormLayout';
8
8
  import Input from '@adaptabletools/adaptable/src/components/Input';
9
9
  import SimpleButton from '@adaptabletools/adaptable/src/components/SimpleButton';
10
- import FlexWithFooter from '@adaptabletools/adaptable/src/components/FlexWithFooter';
11
10
  import { PanelWithImage } from '@adaptabletools/adaptable/src/View/Components/Panels/PanelWithImage';
12
11
  import { usePopupContext } from '@adaptabletools/adaptable/src/View/Components/Popups/AdaptablePopup/PopupContext';
13
12
  import ErrorBox from '@adaptabletools/adaptable/src/components/ErrorBox';
@@ -32,19 +31,11 @@ const IPushPullLoginComponent = (props) => {
32
31
  const e = event.target;
33
32
  setState({ ...state, Password: e.value });
34
33
  };
35
- return (React.createElement(PanelWithImage, { header: "ipushpull Login Details", glyphicon: "login", variant: "primary", style: { height: '100%' } },
36
- React.createElement(FlexWithFooter, { as: "form", onSubmit: (e) => {
34
+ return (React.createElement(PanelWithImage, { header: "ipushpull Login Details", glyphicon: "login", variant: "primary" },
35
+ React.createElement("form", { onSubmit: (e) => {
37
36
  e.preventDefault();
38
37
  onSubmit();
39
- }, footerProps: {
40
- className: 'twa:text-4',
41
- }, footer: React.createElement(React.Fragment, null,
42
- React.createElement(SimpleButton, { tone: "neutral", variant: "text", tooltip: "Close", onClick: (e) => {
43
- e.stopPropagation();
44
- hidePopup();
45
- } }, "CLOSE"),
46
- React.createElement("div", { style: { flex: 1 } }),
47
- React.createElement(SimpleButton, { tone: "accent", variant: "raised", type: "submit", disabled: StringExtensions.IsNullOrEmpty(state.Password), icon: 'check' }, "Login")) },
38
+ } },
48
39
  React.createElement(Flex, { flexDirection: "column", className: "twa:p-2 twa:m-2" },
49
40
  React.createElement(HelpBlock, { className: "twa:mb-1" }, "Login to ipushpull using your login (email address) and password."),
50
41
  React.createElement(FormLayout, { className: "twa:m-3" },
@@ -53,7 +44,13 @@ const IPushPullLoginComponent = (props) => {
53
44
  React.createElement(FormRow, { label: "ipushpull password:" },
54
45
  React.createElement(Input, { className: "twa:w-full", type: "password", placeholder: "Password", value: state.Password, onChange: onPasswordChange })),
55
46
  props.pushpullLoginErrorMessage ? (React.createElement(FormRow, { label: "" },
56
- React.createElement(ErrorBox, null, props.pushpullLoginErrorMessage))) : null)))));
47
+ React.createElement(ErrorBox, null, props.pushpullLoginErrorMessage))) : null)),
48
+ React.createElement(Flex, { className: "twa:p-2", justifyContent: "space-between" },
49
+ React.createElement(SimpleButton, { tone: "neutral", variant: "outlined", tooltip: "Close", onClick: (e) => {
50
+ e.stopPropagation();
51
+ hidePopup();
52
+ } }, "CLOSE"),
53
+ React.createElement(SimpleButton, { tone: "accent", variant: "raised", type: "submit", disabled: StringExtensions.IsNullOrEmpty(state.Password), icon: 'check' }, "Login")))));
57
54
  };
58
55
  function mapStateToProps(state) {
59
56
  return {
@@ -109,7 +109,7 @@ const IPushPullViewPanelComponent = (props) => {
109
109
  : 'Select Page')),
110
110
  React.createElement(Flex, { className: "twa:min-w-[148px]" },
111
111
  React.createElement(ButtonExport, { className: `ab-${elementType}__IPushPull__export twa:ml-1`, onClick: () => onIPushPullSendSnapshot(), tooltip: "Send Snapshot to ipushpull", disabled: isLiveIPushPullReport || !isCompletedReport, accessLevel: props.accessLevel }),
112
- true ? (React.createElement(ButtonPause, { className: `ab-${elementType}__IPushPull__pause twa:ml-1 twa:fill-red-500`, onClick: () => props.onIPushPullStopLiveData(), tooltip: "Stop sync with ipushpull", disabled: !isLiveIPushPullReport, accessLevel: props.accessLevel })) : (React.createElement(ButtonPlay, { className: `ab-${elementType}__IPushPull__play twa:ml-1`, onClick: () => onIPushPullStartLiveData(), tooltip: "Start sync with ipushpull", disabled: isLiveIPushPullReport || !isCompletedReport, accessLevel: props.accessLevel })),
112
+ isLiveIPushPullReport ? (React.createElement(ButtonPause, { className: `ab-${elementType}__IPushPull__pause twa:ml-1 twa:fill-red-500`, onClick: () => props.onIPushPullStopLiveData(), tooltip: "Stop sync with ipushpull", disabled: !isLiveIPushPullReport, accessLevel: props.accessLevel })) : (React.createElement(ButtonPlay, { className: `ab-${elementType}__IPushPull__play twa:ml-1`, onClick: () => onIPushPullStartLiveData(), tooltip: "Start sync with ipushpull", disabled: isLiveIPushPullReport || !isCompletedReport, accessLevel: props.accessLevel })),
113
113
  isCompletedReport && (React.createElement(Flex, { className: join(props.accessLevel == 'ReadOnly' ? GeneralConstants.READ_ONLY_STYLE : '', `ab-${elementType}__IPushPull__controls`), alignItems: "stretch" }, props.api.entitlementApi.isModuleFullEntitlement('Schedule') && (React.createElement(ButtonSchedule, { className: `ab-${elementType}__IPushPull__schedule twa:ml-1`, onClick: () => onNewIPushPullSchedule(), tooltip: "Schedule", disabled: isLiveIPushPullReport || !isCompletedReport, accessLevel: props.accessLevel })))),
114
114
  ' ',
115
115
  React.createElement(ButtonNewPage, { className: `ab-${elementType}__IPushPull__newpage twa:ml-1`, onClick: () => props.onShowAddIPushPullPage(), tooltip: "New Page", disabled: isLiveIPushPullReport, accessLevel: props.accessLevel }),
package/src/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { AdaptablePlugin } from '@adaptabletools/adaptable';
1
+ import { AdaptablePlugin } from '@adaptabletools/adaptable/types';
2
2
  import type { Middleware } from 'redux';
3
3
  import * as Redux from 'redux';
4
4
  import { IPushPullState } from '@adaptabletools/adaptable/src/AdaptableState/IPushPullState';
5
5
  import { IPushPullApi } from '@adaptabletools/adaptable/src/Api/IPushPullApi';
6
- import { IPushPullPluginOptions } from '@adaptabletools/adaptable/src/AdaptableOptions/IPushPullPluginOptions';
6
+ import { IPushPullPluginOptions } from './IPushPullPluginOptions';
7
7
  import { IAdaptable } from '@adaptabletools/adaptable/src/AdaptableInterfaces/IAdaptable';
8
8
  declare class IPushPullPlugin extends AdaptablePlugin {
9
9
  options: IPushPullPluginOptions;
@@ -13,10 +13,11 @@ declare class IPushPullPlugin extends AdaptablePlugin {
13
13
  constructor(options?: IPushPullPluginOptions);
14
14
  afterInitApi(adaptable: IAdaptable): void;
15
15
  rootReducer: (rootReducer: any) => {
16
- System: (state: IPushPullState, action: Redux.Action) => IPushPullState;
16
+ Internal: (state: IPushPullState, action: Redux.Action) => IPushPullState;
17
17
  };
18
18
  reduxMiddleware: (adaptable: IAdaptable) => Middleware;
19
19
  afterInitStore(adaptable: IAdaptable): void;
20
20
  }
21
+ export type { IPushPullPluginOptions, IPushPullConfig } from './IPushPullPluginOptions';
21
22
  declare const _default: (options?: IPushPullPluginOptions) => IPushPullPlugin;
22
23
  export default _default;