Skip to content

Commit

Permalink
Implement NFC page
Browse files Browse the repository at this point in the history
  • Loading branch information
ligangty committed Feb 4, 2024
1 parent e93b0b2 commit 8755350
Show file tree
Hide file tree
Showing 15 changed files with 2,529 additions and 25 deletions.
1 change: 1 addition & 0 deletions src/main/webui/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
**/*.css
**/*.json
**/*.ico
**/*.bak
**/index.html
**/README.md
2 changes: 1 addition & 1 deletion src/main/webui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"dev": "webpack-dev-server --open --hot",
"lint": "eslint './src/**'",
"lint-fix": "eslint './src/**' --fix",
"server": "npm run build-dev && nodemon src/server/app.js --exec babel-node --presets @babel/preset-env",
"server": "nodemon src/server/app.js --exec babel-node --presets @babel/preset-env",
"test": "NODE_ENV=test jest"
}
}
2 changes: 0 additions & 2 deletions src/main/webui/src/app/components/content/Main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ export const Main = () => <Container fluid>
<Route path="/cache/delete" element={<Cache />} />
{
// <Route exact path={["/nfc/view/:packageType/:type/:name"]} element={} />
//
// <Route exact path={"/logout"} element={} />
}
</Routes>
</Container>;
2 changes: 1 addition & 1 deletion src/main/webui/src/app/components/content/addons/Cache.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default function Cache() {
<label htmlFor="conent-path">Input the the metadata url:</label>
(Can be a full or a relative url like &quot;/api/content/maven/group/central/org/foo/bar/maven-metadata.xml. Be noticed that this will trigger the deletions of the target path from all <b>affected groups</b>.&quot;)
<input id="conent-path" style={{width: "100%"}} {...register("path", {required: true})}/>
{errors.path?.type === "required" && <span className="alert">Metadata url is required</span>}
{errors.path?.type === "required" && <span className="indy-alert">Metadata url is required</span>}
</div>
<div className="cp-row">
<button onClick={showConfirmLog}>Delete</button>
Expand Down
322 changes: 320 additions & 2 deletions src/main/webui/src/app/components/content/addons/NFC.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,326 @@
* limitations under the License.
*/

import React from 'react';
import React, {useState, useEffect, useRef, Fragment} from 'react';
import {LoadingSpiner} from '../common/LoadingSpiner.jsx';
import {IndyRest} from '#utils/RestClient.js';
import {Utils} from '#utils/AppUtils.js';

const {storeQueryRes, nfcRes} = IndyRest;

export default function NFC() {
return <div>This is not implemented yet!</div>;
const [nfcStoreKeys, setNfcStoreKeys] = useState([]);
const [message, setMessage] = useState('');
const [error, setError] = useState('');
const [currentKey, setCurrentKey] = useState("");
const [sections, setSections] = useState([]);
const pageSizes = [10, 50, 100];
const page = useRef({
index: 0,
size: pageSizes[0]
});
const [prevDisabled, setPrevDisabled] = useState(true);
const [paginationHidden, setPagginationHidden] = useState(true);
const [isShowAll, setShowAll] = useState(true);
const [loading, setLoading] = useState(false);
const [loadingSection, setLoadingSection] = useState(false);

const updatePage = partialPage => {
const newPage = Utils.cloneObj(page.current);
for (let key in partialPage) {
if (Object.hasOwn(partialPage, key)){
newPage[key] = partialPage[key];
}
}
page.current = newPage;
};
useEffect(()=>{
setLoadingSection(true);
(async () =>{
const res = await storeQueryRes.getEndpoints("all");
if (res.success){
const raw = await res.result;
const allKeys = raw.items.filter(item=>item.type!=="group").map(item=>item.key);
setNfcStoreKeys(allKeys);
setLoadingSection(false);
}else{
setError(res.error.message);
}
})();
}, []);

const clearMessage = () => {
setMessage('');
setError('');
};

const labelSections = secs => {
secs.forEach(s => {
s.label = Utils.keyLabel(s.key);
s.paths.sort();
});
};

const showSection = e => {
const selectKey = e.target.value;
if (!selectKey){
return;
}
clearMessage();
setCurrentKey(selectKey);
setPagginationHidden(true);
setLoading(true);
const [packageType, type, name] = selectKey.split(':');
setSections([]);
(async ()=> {
const resp = await nfcRes.get(packageType, type, name, "");
if(resp.success){
if(resp.result && resp.result.sections !== undefined){
labelSections(resp.result.sections);
setSections(Utils.sortByEmbeddedKey(resp.result.sections));
setShowAll(false);
}
}
setLoading(false);
})();
};

const showAll = e => {
e.preventDefault();
clearMessage();
const [index, size] = [page.current.index, page.current.size];
setPagginationHidden(false);
setLoading(true);
setSections([]);
(async ()=> {
const resp = await nfcRes.query(index, size);
if(resp.success){
if(resp.result && resp.result.sections !== undefined){
labelSections(resp.result.sections);
setSections(Utils.sortByEmbeddedKey(resp.result.sections));
setShowAll(true);
setCurrentKey("");
}
}
setLoading(false);
})();
};

const clearAllNFC = e => {
e.preventDefault();
(async () => {
const result = await nfcRes.deleteAll();
if(result.success){
setSections([]);
setPagginationHidden(true);
setMessage("All NFC entries cleared successfully.");
}else{
Utils.logMessage(`Failed to clear all NFC! Error reason: ${result.error.message}`);
}
})();
};

const clearSection = (section, secs) => {
setMessage("");
let key = section.key;
// alert( "Clear all NFC entries for: " + key );

let name = Utils.nameFromKey(key);
let packageType = Utils.packageTypeFromKey(key);
let type = Utils.typeFromKey(key);
(async () => {
const result = await nfcRes.delete(packageType, type, name, "");
if(result.success){
setMessage(`Cleared NFC for ${key}`);
section.paths = [];
const index = secs.indexOf(section);
secs.splice(index, 1);
}else{
setMessage(`Failed to clear NFC for ${key}`);
setError(result.error);
}
})();
};

const clearSectionPath = (section, path) => {
const subPath = path.substring(1);
let key = section.key;

// alert( "Clear all NFC entries for: " + key + ", path: " + path );

let name = Utils.nameFromKey(key);
let packageType = Utils.packageTypeFromKey(key);
let type = Utils.typeFromKey(key);

(async () => {
const result = await nfcRes.delete(packageType, type, name, subPath);
if(result.success){
setMessage(`Cleared NFC for ${key}, path: ${subPath}`);
let idx = section.paths.indexOf(subPath);
section.paths.splice(idx,1);
}else{
setError(result.error);
}
})();
};

const queryByPageIndexAndSize = (index, size) =>{
setMessage("");
setPagginationHidden(true);
setLoading(true);
setSections([]);
if (isShowAll){
// alert( "showing all NFC entries");
// delete $scope.currentKey;
(async () => {
const resp = await nfcRes.query(index, size);
if(resp.success){
if (resp.result && resp.result.sections !== undefined){
labelSections(resp.result.sections);
setSections(Utils.sortByEmbeddedKey(resp.result.sections));
setPagginationHidden(false);
setPrevDisabled(index <= 0);
}
}
setLoading(false);
})();
}else{
const packageType = Utils.packageTypeFromKey(currentKey);
const type = Utils.typeFromKey(currentKey);
const name = Utils.nameFromKey(currentKey);
if (type !== undefined && name !== undefined){
(async () => {
const resp = await nfcRes.get(packageType, type, name, "", index, size);
if(resp.success){
if(resp.result && resp.result.sections !== undefined){
labelSections(resp.result.sections);
setSections(Utils.sortByEmbeddedKey(resp.result.sections));
setPagginationHidden(false);
// TODO: check if need to setCurrentKey here
setCurrentKey(Utils.formatKey(packageType, type, name));
setPrevDisabled(index <= 0);
}
}
setLoading(false);
})();
// alert( "showing NFC entries for: " + $scope.currentKey);
}
}
};
const changePageSize = currentSize => {
updatePage({"size": currentSize, "index": 0});
queryByPageIndexAndSize(page.current.index, page.current.size);
};
const changePageNumber = e => {
if(e.keyCode === 13) {
const pageIndex = parseInt(e.target.value, 10);
updatePage({"index": pageIndex});
queryByPageIndexAndSize(page.current.index, page.current.size);
}
};
const prevPage = () => {
const [curIndex, curSize] = [page.current.index-1, page.current.size];
queryByPageIndexAndSize(curIndex, curSize);
updatePage({"index": curIndex, "size": curSize});
};
const nextPage = () => {
const curIndex = page.current.index + 1;
queryByPageIndexAndSize(curIndex, page.current.size);
updatePage({"index": curIndex});
};

const handleSearch = e => {
e.preventDefault();
// TODO: not implemented yet!
};

return <Fragment>
<div className="control-panel">
{
loadingSection && <LoadingSpiner />
}
<div className="cp-row">
Not-Found Cache Entries for:
</div>
<div className="cp-row">
<select role="nfcSel" value={currentKey}
onChange={showSection}>
<option value=""></option>
{
nfcStoreKeys.map(key => <option key={`storeKey:${key}`} label={Utils.keyLabel(key)} value={`${key}`}>{Utils.keyLabel(key)}</option>)
}
</select>{' '}
</div>
<div className="cp-row">
<button onClick={showAll}>Show All</button>
<button onClick={clearAllNFC}>Clear All</button>
</div>
<hr/>
<div className="cp-row">
Search: <input type="text" name="query" onChange={handleSearch}/>
</div>
<hr/>
<div className="cp-row cp-debug">
<input type="checkbox"/> Debug Data
</div>
</div>
<div className="content-panel">
{loading && <LoadingSpiner />}
{message && message.trim() !== "" && <div className="alert alert-success" role="alert">{message}</div>}
{error && error.trim() !== "" && <div className="alert alert-danger" role="alert">{error}</div>}
{(message && message.trim() !== "" || error && error.trim() !== "") && <hr />}
{
sections && sections.length > 0 &&
<ul>
{
sections.map(section => <li key={section.key} role={`section-${section.key}`} className="section">
<div className="with-inline-cp">
<div className="inline key">{section.label}</div>
<div className="inline inline-cp">
<a href="" onClick={e =>{
e.preventDefault();
clearSection(section, sections);
}} className="inline-cp-action">&#x2718;</a>
</div>
</div>
{
section.paths && section.paths.length > 0 && <ul>
{
section.paths.map(path =><li key={path}>
<div className="with-inline-cp">
<div className="inline label">{path}</div>
<div className="inline inline-cp">
<a href="" onClick={e=>{
e.preventDefault();
clearSectionPath(section, path);
}} className="inline-cp-action">&#x2718;</a>
</div>
</div>
</li>)
}
</ul>
}
</li>)
}
</ul>
}
{
!paginationHidden && <div className="pagination">
<label>Page Size:</label>&nbsp;
<select value={page.current.size} onChange={e => {
changePageSize(e.target.value);
}}>
{
pageSizes.map(pageSize => <option key={pageSize} value={pageSize}>{pageSize}</option>)
}
</select>&nbsp;&nbsp;&nbsp;
{
!prevDisabled && <Fragment><input type="button" value="Prev" onClick={prevPage} />&nbsp;</Fragment>
}
<input type="number" style={{width: "50px"}} defaultValue={page.current.index} onKeyDown={changePageNumber}/>&nbsp;
<input type="button" value="Next" onClick={nextPage} />
</div>
}
</div>
</Fragment>;
}
Loading

0 comments on commit 8755350

Please sign in to comment.