Skip to content

Commit 2a79973

Browse files
committed
handle btn disable and itemsCount
1 parent ca3b94f commit 2a79973

4 files changed

Lines changed: 102 additions & 22 deletions

File tree

lib/public/models/DataExportModel.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ export class DataExportModel extends Observable {
2222
/**
2323
* Constructor
2424
* @param {ObservableData<RemoteData<object[]>>} items$ observable data used as source for export
25+
* @param {function} onNoDataAction
2526
*/
26-
constructor(items$) {
27+
constructor(items$, onNoDataAction) {
2728
super();
2829

2930
/** @type {ObservableData<RemoteData<object[]>>} */
@@ -42,6 +43,37 @@ export class DataExportModel extends Observable {
4243
this._exportName = 'data';
4344

4445
this.columnFormats = null;
46+
this._onNoDataAction = onNoDataAction;
47+
48+
this._disabled = null;
49+
50+
this._totalExistingItemsCount = null;
51+
}
52+
53+
get totalExistingItemsCount() {
54+
return this._totalExistingItemsCount;
55+
}
56+
57+
setTotalExistingItemsCount(totalExistingItemsCount) {
58+
this._totalExistingItemsCount = totalExistingItemsCount;
59+
}
60+
61+
get disabled() {
62+
return this._disabled;
63+
}
64+
65+
setDisabled(value) {
66+
this._disabled = value;
67+
}
68+
69+
/**
70+
*
71+
*/
72+
askForData() {
73+
this.items.match({
74+
NotAsked: () => this._onNoDataAction(),
75+
Other: () => null,
76+
});
4577
}
4678

4779
/**

lib/public/models/OverviewModel.js

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,19 @@ export class OverviewPageModel extends Observable {
5656
this._dataSource = new PaginatedRemoteDataSource();
5757
this._dataSource.pipe(dataSourceObservable);
5858

59-
this._observableItems = ObservableData.builder().initialValue(RemoteData.loading()).build();
60-
this._observableItems.bubbleTo(this);
59+
this._item$ = ObservableData.builder().initialValue(RemoteData.loading()).build();
60+
this._item$.bubbleTo(this);
61+
62+
{
63+
const allDataSourceObservable = ObservableData.builder().initialValue(RemoteData.loading()).build();
64+
allDataSourceObservable.observe(() => this.parseAllApiRemoteData(allDataSourceObservable.getCurrent()));
65+
66+
this._allDataSource = new PaginatedRemoteDataSource();
67+
this._allDataSource.pipe(allDataSourceObservable);
68+
69+
this._allItems$ = ObservableData.builder().initialValue(RemoteData.loading()).build();
70+
this._allItems$.bubbleTo(this);
71+
}
6172

6273
/**
6374
* @type {ObservableData<TableConfiguration>}
@@ -84,7 +95,7 @@ export class OverviewPageModel extends Observable {
8495
* @returns {void}
8596
*/
8697
reset() {
87-
this._observableItems.setCurrent(RemoteData.notAsked());
98+
this._item$.setCurrent(RemoteData.notAsked());
8899
this._pagination.reset();
89100
}
90101

@@ -102,8 +113,8 @@ export class OverviewPageModel extends Observable {
102113
const keepExisting = this._pagination.currentPage > 1 && this._pagination.isInfiniteScrollEnabled;
103114

104115
remoteData.match({
105-
NotAsked: () => this._observableItems.setCurrent(RemoteData.notAsked()),
106-
Loading: () => this._pagination.isInfiniteScrollEnabled ? null : this._observableItems.setCurrent(RemoteData.loading()),
116+
NotAsked: () => this._item$.setCurrent(RemoteData.notAsked()),
117+
Loading: () => this._pagination.isInfiniteScrollEnabled ? null : this._item$.setCurrent(RemoteData.loading()),
107118
Success: ({ items, totalCount }) => {
108119
const concatenateWith = keepExisting ? this.items.match({
109120
Success: (payload) => payload,
@@ -112,9 +123,26 @@ export class OverviewPageModel extends Observable {
112123
Failure: () => [],
113124
}) : [];
114125
this._pagination.itemsCount = totalCount;
115-
this._observableItems.setCurrent(RemoteData.success([...concatenateWith, ...this.processItems(items)]));
126+
this._item$.setCurrent(RemoteData.success([...concatenateWith, ...this.processItems(items)]));
116127
},
117-
Failure: (error) => this._observableItems.setCurrent(RemoteData.failure(error)),
128+
Failure: (error) => this._item$.setCurrent(RemoteData.failure(error)),
129+
});
130+
}
131+
132+
/**
133+
* Parse the API remote data to extract the list of items
134+
*
135+
* @param {RemoteData<{items: T[], totalCount: number}, *>} remoteData the API remote data
136+
* @return {void}
137+
*/
138+
parseAllApiRemoteData(remoteData) {
139+
remoteData.match({
140+
NotAsked: () => this._allItems$.setCurrent(RemoteData.notAsked()),
141+
Loading: () => this._allItems$.setCurrent(RemoteData.loading()),
142+
Success: ({ items }) => {
143+
this._allItems$.setCurrent(RemoteData.success(this.processItems(items)));
144+
},
145+
Failure: (error) => this._allItems$.setCurrent(RemoteData.failure(error)),
118146
});
119147
}
120148

@@ -130,14 +158,26 @@ export class OverviewPageModel extends Observable {
130158

131159
/**
132160
* Fetch all the relevant items from the API
161+
* it takes into account pagination parameters
133162
*
134163
* @return {Promise<void>} void
135164
*/
136165
async load() {
137166
const params = await this.getLoadParameters();
167+
this._allItems$.setCurrent(RemoteData.notAsked());
138168
await this._dataSource.fetch(buildUrl(this.getRootEndpoint(), params));
139169
}
140170

171+
/**
172+
* Fetch all the relevant items from the API
173+
* it does not take into account pagincation parameters
174+
*
175+
* @return {Promise<void>} void
176+
*/
177+
async loadAll() {
178+
await this._allDataSource.fetch(this.getRootEndpoint());
179+
}
180+
141181
/**
142182
* Return the query params to use to get load the overview data
143183
*
@@ -163,7 +203,7 @@ export class OverviewPageModel extends Observable {
163203
* @return {RemoteData<T[]>} the items
164204
*/
165205
get items() {
166-
return this._observableItems.getCurrent();
206+
return this._item$.getCurrent();
167207
}
168208

169209
/**
@@ -200,4 +240,8 @@ export class OverviewPageModel extends Observable {
200240
get sortModel() {
201241
return this._sortModel;
202242
}
243+
244+
hasAnyData() {
245+
return this._item$.getCurrent().match({ Success: ({ length = 0 } = {}) => length > 0, Other: () => false });
246+
}
203247
}

lib/public/views/Runs/Overview/RunsOverviewModel.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,11 @@ export class RunsOverviewModel extends OverviewPageModel {
100100
this._debouncedLoad = debounce(this.load.bind(this), model.inputDebounceTime);
101101
};
102102

103-
this._exportModel = new DataExportModel(this._observableItems);
103+
this._exportModel = new DataExportModel(this._allItems$, () => this.loadAll());
104+
this._item$.observe(() => {
105+
this._exportModel.setDisabled(!this.hasAnyData());
106+
this._exportModel.setTotalExistingItemsCount(this._pagination.itemsCount);
107+
});
104108

105109
model.appConfiguration$.observe(() => updateDebounceTime());
106110
updateDebounceTime();

lib/public/views/Runs/Overview/exportTriggerAndModal.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,17 @@ const errorDisplay = () => h('.danger', 'Data fetching failed');
101101
* @param {ModalHandler} modalHandler The modal handler, used to dismiss modal after export
102102
* @return {Component} Return the view of the inputs
103103
*/
104-
const exportModal = (exportModel, modalHandler) => h('div#export-runs-modal', [
105-
h('h2', 'Export Runs'),
106-
exportModel.items.match({
107-
NotAsked: () => errorDisplay(),
108-
Failure: () => errorDisplay(),
109-
Other: () => exportForm(exportModel, modalHandler),
110-
}),
111-
]);
104+
const exportModal = (exportModel, modalHandler) => {
105+
exportModel.askForData();
106+
return h('div#export-runs-modal', [
107+
h('h2', 'Export data'),
108+
exportModel.items.match({
109+
NotAsked: () => errorDisplay(),
110+
Failure: () => errorDisplay(),
111+
Other: () => exportForm(exportModel, modalHandler),
112+
}),
113+
]);
114+
};
112115

113116
/**
114117
* Builds a button which will open popover for data export
@@ -121,9 +124,6 @@ const exportModal = (exportModel, modalHandler) => h('div#export-runs-modal', [
121124
*/
122125
export const exportTriggerAndModal = (exportModel, modalModel, { autoMarginLeft = true } = {}) =>
123126
h(`button.btn.btn-primary${autoMarginLeft ? '.mlauto' : ''}#export-runs-trigger`, {
124-
disabled: exportModel.items.match({
125-
Success: (payload) => payload.length === 0,
126-
Other: () => true,
127-
}),
127+
disabled: exportModel.disabled,
128128
onclick: () => modalModel.display({ content: (modalModel) => exportModal(exportModel, modalModel), size: 'medium' }),
129129
}, 'Export data');

0 commit comments

Comments
 (0)