Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New pagination #188

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions src/main/webui/src/app/components/content/group/GroupEdit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,14 @@

export default function GroupEdit() {
const [store, setStore] = useState({"type": "group", "constituents": []});
const [available, setAvailable] = useState([]);
const [state, setState] = useState({
available: [],
nextPage: ''
});
const location = useLocation();
const {packageType, name} = useParams();
const [avaiLoading, setAvaiLoading] = useState(true);
const [loading, setLoading] = useState(true);
const [page, setPage] = useState("");

Check warning on line 157 in src/main/webui/src/app/components/content/group/GroupEdit.jsx

View workflow job for this annotation

GitHub Actions / Run ES linters

'setPage' is assigned a value but never used
const {
register,
reset,
Expand All @@ -164,20 +168,26 @@
useEffect(() => {
const pkgType = mode === "edit" ? packageType : "all";
const fetchAvailable = async () => {
setAvaiLoading(true);
setLoading(true);
// get available Store data
const availableRes = await storeQueryRes.getEndpoints(pkgType);
const availableRes = await storeQueryRes.getEndpoints(pkgType, page);
let allAvailable = new Set();
let nextAvailablePage = "";
if (availableRes.success) {
let availableResult = availableRes.result.items;

if (availableRes.result.hasOwnProperty("next_page")) {

Check warning on line 179 in src/main/webui/src/app/components/content/group/GroupEdit.jsx

View workflow job for this annotation

GitHub Actions / Run ES linters

Do not access Object.prototype method 'hasOwnProperty' from target object
nextAvailablePage = availableRes.result.next_page;
}

Check warning on line 182 in src/main/webui/src/app/components/content/group/GroupEdit.jsx

View workflow job for this annotation

GitHub Actions / Run ES linters

Trailing spaces not allowed
availableResult.forEach(item => {
allAvailable.add(item.packageType + ':' + item.type + ':' + item.name);
});
} else {
Utils.logMessage(`Getting available constituents failed! Error reason: ${availableRes.error.message}`);
}
setAvaiLoading(false);
return allAvailable;
setLoading(false);
return {available: allAvailable, nextPage: nextAvailablePage};
};

if (mode === 'edit') {
Expand All @@ -188,7 +198,8 @@
const raw = res.result;
const storeView = Utils.cloneObj(raw);
storeView.disabled = raw.disabled === undefined ? false : raw.disabled;
let allAvailable = await fetchAvailable();
let newState = await fetchAvailable();
let allAvailable = newState.available;
raw.constituents.forEach(item => allAvailable.delete(item));
allAvailable.delete(raw.key);
// get Store disablement data
Expand All @@ -200,9 +211,10 @@
} else {
Utils.logMessage(`disable timeout getting failed! Error reason: ${timeoutRes.error.message}`);
}
newState.available = [...state.available, ...Array.from(allAvailable)];
// Change state and re-rendering
setStore(raw);
setAvailable(Array.from(allAvailable));
setState(newState);
reset(raw);
} else {
// TODO: find another way to do error handling
Expand All @@ -215,11 +227,11 @@

if (mode === "new") {
(async () => {
let allAvailable = await fetchAvailable();
setAvailable(Array.from(allAvailable));
let newState = await fetchAvailable();
setState(newState);
})();
}
}, [packageType, name, mode, reset]);
}, [packageType, name, mode, reset, page]);

Check warning on line 234 in src/main/webui/src/app/components/content/group/GroupEdit.jsx

View workflow job for this annotation

GitHub Actions / Run ES linters

React Hook useEffect has a missing dependency: 'state.available'. Either include it or remove the dependency array

const updatePackageType = newPackageType => {
let newStore = store;
Expand Down Expand Up @@ -294,9 +306,9 @@
</div>
<div className="fieldset-caption">Constituents</div>
{
avaiLoading?
loading?
<LoadingSpiner /> :
<EditConstituents store={store} currentAvailable={available} />
<EditConstituents store={store} currentAvailable={state.available} />
}
</div>
</div>
Expand Down
38 changes: 28 additions & 10 deletions src/main/webui/src/app/components/content/group/GroupList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,34 +52,51 @@
listing: [],
enableDebug: false,
message: "",
nextPage: ''
});
const [loading, setLoading] = useState(true);
const [page, setPage] = useState("");

const handleScroll = () => {
if (window.innerHeight + document.documentElement.scrollTop + 1
>= document.documentElement.scrollHeight) {
if (state.nextPage !== undefined) {
setPage(state.nextPage);
}
}
};

useEffect(()=>{
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});

useEffect(() => {
setLoading(true);
(async () => {
const res = await storeRes.getStores(packageType, "group");
const res = await storeRes.getStores(packageType, "group", page);
if (res.success) {
let data = res.result;
if (typeof data === "string") {
data = JSON.parse(data);
}
setState({
rawList: data.items,
listing: data.items
});
const newState = {
rawList: [...state.rawList, ...data.items],
listing: [...state.listing, ...data.items],
};

if (data.hasOwnProperty("next_page")) {

Check warning on line 88 in src/main/webui/src/app/components/content/group/GroupList.jsx

View workflow job for this annotation

GitHub Actions / Run ES linters

Do not access Object.prototype method 'hasOwnProperty' from target object
newState.nextPage = data.next_page;
}
setState(newState);
} else {
setState({
message: res.error.message,
});
}
setLoading(false);
})();
}, [packageType]);

if (loading) {
return <LoadingSpiner />;
}
}, [packageType, page]);

Check warning on line 99 in src/main/webui/src/app/components/content/group/GroupList.jsx

View workflow job for this annotation

GitHub Actions / Run ES linters

React Hook useEffect has missing dependencies: 'state.listing' and 'state.rawList'. Either include them or remove the dependency array

return (
<React.Fragment>
Expand All @@ -100,6 +117,7 @@
:
<div className="container-fluid">No content fetched!</div>
}
{loading && <LoadingSpiner />}
<ListJsonDebugger
enableDebug={state.enableDebug}
jsonObj={state.listing}
Expand Down
40 changes: 29 additions & 11 deletions src/main/webui/src/app/components/content/remote/RemoteList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,35 +52,52 @@
rawList: [],
listing: [],
enableDebug: false,
message: ''
message: '',
nextPage: ''
});
const [loading, setLoading] = useState(true);
const [page, setPage] = useState("");

const handleScroll = () => {
if (window.innerHeight + document.documentElement.scrollTop + 1
>= document.documentElement.scrollHeight) {
if (state.nextPage !== undefined) {
setPage(state.nextPage);
}
}
};

useEffect(()=>{
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});

useEffect(()=>{
setLoading(true);
(async ()=>{
const res = await storeRes.getStores(packageType, "remote");
const res = await storeRes.getStores(packageType, "remote", page);
if (res.success){
let data = res.result;
if(typeof data === 'string'){
data = JSON.parse(data);
}
setState({
rawList: data.items,
listing: data.items
});
const newState = {
rawList: [...state.rawList, ...data.items],
listing: [...state.listing, ...data.items],
};

if (data.hasOwnProperty("next_page")) {

Check warning on line 89 in src/main/webui/src/app/components/content/remote/RemoteList.jsx

View workflow job for this annotation

GitHub Actions / Run ES linters

Do not access Object.prototype method 'hasOwnProperty' from target object
newState.nextPage = data.next_page;
}
setState(newState);
}else{
setState({
message: res.error.message
});
}
setLoading(false);
})();
}, [packageType]);

if (loading) {
return <LoadingSpiner />;
}
}, [packageType, page]);

Check warning on line 100 in src/main/webui/src/app/components/content/remote/RemoteList.jsx

View workflow job for this annotation

GitHub Actions / Run ES linters

React Hook useEffect has missing dependencies: 'state.listing' and 'state.rawList'. Either include them or remove the dependency array

return (
<React.Fragment>
Expand All @@ -98,6 +115,7 @@
No content fetched!
</div>
}
{loading && <LoadingSpiner />}
<ListJsonDebugger enableDebug={state.enableDebug} jsonObj={state.listing} />
</React.Fragment>
);
Expand Down
26 changes: 22 additions & 4 deletions src/main/webui/src/app/utils/RestClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ const genPageParam = (index, size) => {
return queryParam;
};

const genPageStringParam = page => {
let queryParam = "";
if(page !== undefined && page.length > 0) {
queryParam = `page=${page}`;
}
return queryParam;
};

const handleResponse = async response => {
if (response.ok){
let result = {};
Expand Down Expand Up @@ -123,14 +131,24 @@ const IndyRest = {
const response = await http.delete(storeAPIEndpoint(pkgType, type, name));
return handleResponse(response);
},
getStores: async (pkgType, type) => {
const response = await jsonRest.get(`${BASE_STORE_API_PATH}/${pkgType}/${type}`);
getStores: async (pkgType, type, page) => {
const queryParam = genPageStringParam(page);
let apiPath = `${BASE_STORE_API_PATH}/${pkgType}/${type}`;
if(queryParam.length > 0){
apiPath += `?${queryParam}`;
}
const response = await jsonRest.get(apiPath);
return handleResponse(response);
}
},
storeQueryRes: {
getEndpoints: async pkgType => {
const response = await jsonRest.get(`${BASE_STORE_API_PATH}/query/endpoints/${pkgType}`);
getEndpoints: async (pkgType, page) => {
const queryParam = genPageStringParam(page);
let apiPath = `${BASE_STORE_API_PATH}/query/endpoints/${pkgType}`;
if(queryParam.length > 0){
apiPath += `?${queryParam}`;
}
const response = await jsonRest.get(apiPath);
return handleResponse(response);
},
getStoreKeys: async pkgType => {
Expand Down
9 changes: 7 additions & 2 deletions src/main/webui/src/server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,19 @@ const decideMockListFile = (packgeType, type) => {
// For store listing
app.get(`${STORE_API_BASE}/:packageType/:type`, async (req, res) => {
await sleep(2000);
const [pkgType, type] = [req.params.packageType, req.params.type];
const [pkgType, type, page] = [req.params.packageType, req.params.type, req.query.page];
if(pkgType==="_all"){
// TODO: do all packageType for type handling here
}
const mockFile = decideMockListFile(pkgType, type);
if(existsSync(mockFile)){
const list = require(mockFile);
res.status(200).json(list);
if (page === undefined) {
res.status(200).json(list[0]);
} else {
const result = list.find(item=>item.current_page===page);
res.status(200).json(result);
}
}else{
res.status(404).json({error: "No such stores!"});
}
Expand Down
Loading
Loading