diff --git a/src/main/webui/.eslintrc.json b/src/main/webui/.eslintrc.json
index b432c40..f91204b 100644
--- a/src/main/webui/.eslintrc.json
+++ b/src/main/webui/.eslintrc.json
@@ -17,7 +17,8 @@
},
"plugins": [
"react",
- "jest"
+ "jest",
+ "react-hooks"
],
"settings": {
"react": {
@@ -295,6 +296,8 @@
"yoda": [
2,
"never"
- ]
+ ],
+ "react-hooks/rules-of-hooks": 1,
+ "react-hooks/exhaustive-deps": 1
}
}
diff --git a/src/main/webui/package-lock.json b/src/main/webui/package-lock.json
index 78cec39..fc56cff 100644
--- a/src/main/webui/package-lock.json
+++ b/src/main/webui/package-lock.json
@@ -36,6 +36,7 @@
"eslint": "^8.51.0",
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.6.0",
"eslint-webpack-plugin": "^4.0.1",
"express": "^4.18.2",
"fetch-mock": "^9.11.0",
@@ -6331,6 +6332,18 @@
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
}
},
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+ "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
"node_modules/eslint-plugin-react/node_modules/doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
diff --git a/src/main/webui/package.json b/src/main/webui/package.json
index 1f6f2ef..13abc23 100644
--- a/src/main/webui/package.json
+++ b/src/main/webui/package.json
@@ -45,6 +45,7 @@
"eslint": "^8.51.0",
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.6.0",
"eslint-webpack-plugin": "^4.0.1",
"express": "^4.18.2",
"fetch-mock": "^9.11.0",
diff --git a/src/main/webui/src/app/components/content/common/PackageTypeSelect.jsx b/src/main/webui/src/app/components/content/common/PackageTypeSelect.jsx
index 17a8cfd..90661b6 100644
--- a/src/main/webui/src/app/components/content/common/PackageTypeSelect.jsx
+++ b/src/main/webui/src/app/components/content/common/PackageTypeSelect.jsx
@@ -24,21 +24,18 @@ export const PackageTypeSelect = ({packageType,vauleChangeHandler}) =>{
pkgTypes: []
});
- (function() {
- const typeUrl = '/api/stats/package-type/keys';
- useEffect(()=>{
- const fetchPkgTypes = async () =>{
- const response = await jsonRest.get(typeUrl);
- if (response.ok){
- const pkgTypes = await response.json();
- setState({pkgTypes});
- }else{
- Utils.logMessage(response);
- }
- };
- fetchPkgTypes();
- }, []);
- }());
+ useEffect(()=>{
+ const fetchPkgTypes = async () =>{
+ const response = await jsonRest.get('/api/stats/package-type/keys');
+ if (response.ok){
+ const pkgTypes = await response.json();
+ setState({pkgTypes});
+ }else{
+ Utils.logMessage(response);
+ }
+ };
+ fetchPkgTypes();
+ }, []);
const selectedValue = packageType || "maven";
const onChangeHandler = vauleChangeHandler || (()=>{});
diff --git a/src/main/webui/src/app/components/content/remote/RemoteEdit.jsx b/src/main/webui/src/app/components/content/remote/RemoteEdit.jsx
index 7a10c4d..46da52d 100644
--- a/src/main/webui/src/app/components/content/remote/RemoteEdit.jsx
+++ b/src/main/webui/src/app/components/content/remote/RemoteEdit.jsx
@@ -26,49 +26,6 @@ import {TimeUtils} from '#utils/TimeUtils.js';
import {jsonRest} from '#utils/RestClient.js';
import {STORE_API_BASE_URL} from "../../ComponentConstants.js";
-const init = (pkgType, storeName, setState) => {
- const getUrl = `${STORE_API_BASE_URL}/${pkgType}/remote/${storeName}`;
- useEffect(()=>{
- const fetchStore = async () =>{
- // get Store data
- const response = await jsonRest.get(getUrl);
- if (response.ok){
- const raw = await response.json();
- const storeView = Utils.cloneObj(raw);
- storeView.disabled = raw.disabled === undefined ? false : raw.disabled;
- storeView.useX509 = raw.server_certificate_pem || raw.key_certificate_pem;
- storeView.useProxy = raw.proxy_host && true;
- // eslint-disable-next-line no-extra-parens
- storeView.useAuth = (storeView.useProxy && storeView.proxy_user) || storeView.user;
-
- // get Store disablement data
- const timeoutUrl = `/api/admin/schedule/store/${storeView.packageType}/${storeView.type}/${storeView.name}/disable-timeout`;
- const timeoutResponse = await jsonRest.get(timeoutUrl);
- const cloned = Utils.cloneObj(storeView);
- if (timeoutResponse.ok){
- const timeout = await timeoutResponse.json();
- cloned.disableExpiration = timeout.expiration;
- }else{
- response.text().then(error=>Utils.logMessage(`disable timeout getting failed! Error reason: ${error}`));
- }
-
- // Change state and re-rendering
- setState({
- storeView: cloned,
- store: raw
- });
- }else{
- // TODO: find another way to do error handling
- response.text().then(error=>setState({
- message: error
- }));
- }
- };
-
- fetchStore();
- }, []);
-};
-
const CertificateSection = ({store, handleValueChange}) =>
{
store.useAuth &&
@@ -113,17 +70,54 @@ export default function RemoteEdit() {
storeView: {}
});
const location = useLocation();
+ const {packageType, name} = useParams();
const path = location.pathname;
const mode = path.match(/.*\/new$/u)? 'new':'edit';
let [pkgType, storeName] = ["",""];
// Give a default packageType
let store = {"packageType": "maven", "type": "remote"};
- if(mode === 'edit'){
- const {packageType, name} = useParams();
- [pkgType, storeName] = [packageType, name];
- init(pkgType, storeName, setState);
- store = state.store;
- }
+ [pkgType, storeName] = [packageType, name];
+ useEffect(()=>{
+ if(mode === 'edit'){
+ const fetchStore = async () =>{
+ // get Store data
+ const response = await jsonRest.get(`${STORE_API_BASE_URL}/${pkgType}/remote/${storeName}`);
+ if (response.ok){
+ const raw = await response.json();
+ const storeView = Utils.cloneObj(raw);
+ storeView.disabled = raw.disabled === undefined ? false : raw.disabled;
+ storeView.useX509 = raw.server_certificate_pem || raw.key_certificate_pem;
+ storeView.useProxy = raw.proxy_host && true;
+ // eslint-disable-next-line no-extra-parens
+ storeView.useAuth = (storeView.useProxy && storeView.proxy_user) || storeView.user;
+ // get Store disablement data
+ const timeoutUrl = `/api/admin/schedule/store/${storeView.packageType}/${storeView.type}/${storeView.name}/disable-timeout`;
+ const timeoutResponse = await jsonRest.get(timeoutUrl);
+ const cloned = Utils.cloneObj(storeView);
+ if (timeoutResponse.ok){
+ const timeout = await timeoutResponse.json();
+ cloned.disableExpiration = timeout.expiration;
+ }else{
+ response.text().then(error=>Utils.logMessage(`disable timeout getting failed! Error reason: ${error}`));
+ }
+ // Change state and re-rendering
+ setState({
+ storeView: cloned,
+ store: raw
+ });
+ }else{
+ // TODO: find another way to do error handling
+ response.text().then(error=>setState({
+ message: error
+ }));
+ }
+ };
+
+ fetchStore();
+ }
+ }, [pkgType, storeName, mode]);
+
+ store = state.store;
const handleCheckChange = (event, field) => {
if (event.target.checked) {
diff --git a/src/main/webui/src/app/components/content/remote/RemoteList.jsx b/src/main/webui/src/app/components/content/remote/RemoteList.jsx
index ff3dc86..2c57ddc 100644
--- a/src/main/webui/src/app/components/content/remote/RemoteList.jsx
+++ b/src/main/webui/src/app/components/content/remote/RemoteList.jsx
@@ -23,8 +23,30 @@ import {StoreListingWidget} from '../common/StoreListingWidget.jsx';
import {Utils} from '#utils/AppUtils.js';
import {jsonRest} from '#utils/RestClient.js';
+const handlers = {
+ handleDebug: (event, setState) => {
+ setState({
+ enableDebug: event.target.checked
+ });
+ },
+ handleSearch: (event, rawList, setState) => {
+ setState({
+ rawList,
+ listing: Utils.searchByKeyForNewStores(event.target.value, rawList)
+ });
+ }
+};
+
+export default function RemoteList() {
+ const {packageType} = useParams();
+ const [state, setState] = useState({
+ rawList: [],
+ listing: [],
+ disabledMap: {},
+ enableDebug: false,
+ message: ''
+ });
-const init = (packageType, setState) => {
useEffect(()=>{
const fetchdData = async ()=>{
const response = await jsonRest.get(`${STORE_API_BASE_URL}/${packageType}/remote`);
@@ -42,6 +64,7 @@ const init = (packageType, setState) => {
data = JSON.parse(data);
}
setState({
+ rawList: data.items,
listing: data.items,
disabledMap
});
@@ -55,44 +78,18 @@ const init = (packageType, setState) => {
};
fetchdData();
}, [packageType]);
-};
-
-const handlers = {
- handleDebug: (event, setState) => {
- setState({
- enableDebug: event.target.checked
- });
- },
- handleSearch: (event, rawList, setState) => {
- setState({
- listing: Utils.searchByKeyForNewStores(event.target.value, rawList)
- });
- }
-};
-
-export default function RemoteList() {
- const {packageType} = useParams();
- const [state, setState] = useState({
- listing: [],
- disabledMap: {},
- enableDebug: false,
- message: ''
- });
- init(packageType,setState);
- const listing = state.listing;
- const disMap = state.disabledMap;
return (
handlers.handleSearch(event, state.listing, setState)}
+ handleSearch={event => handlers.handleSearch(event, state.rawList, setState)}
handleDebug={event => handlers.handleDebug(event, setState)}
/>
{
- listing?
- :
+ state.listing?
+ :
No content fetched!
diff --git a/src/main/webui/src/app/components/content/remote/RemoteView.jsx b/src/main/webui/src/app/components/content/remote/RemoteView.jsx
index e49a389..3f50d18 100644
--- a/src/main/webui/src/app/components/content/remote/RemoteView.jsx
+++ b/src/main/webui/src/app/components/content/remote/RemoteView.jsx
@@ -28,43 +28,6 @@ import {TimeUtils} from '#utils/TimeUtils.js';
import {jsonRest} from '#utils/RestClient.js';
import {STORE_API_BASE_URL} from '../../ComponentConstants.js';
-const init = (pkgType, storeName, setState) => {
- const storeUrl = `${STORE_API_BASE_URL}/${pkgType}/remote/${storeName}`;
- useEffect(()=>{
- const fetchStore = async () => {
- const response = await jsonRest.get(storeUrl);
- if (response.ok){
- const raw = await response.json();
- const store = Utils.cloneObj(raw);
- store.disabled = raw.disabled === undefined ? false : raw.disabled;
- store.useX509 = raw.server_certificate_pem || raw.key_certificate_pem;
- store.useProxy = raw.proxy_host && true;
- store.useAuth = store.useProxy && store.proxy_user;
- store.useAuth = store.useAuth || store.user;
-
- // get Store disablement data
- const timeoutUrl = `/api/admin/schedule/store/${store.packageType}/${store.type}/${store.name}/disable-timeout`;
- const timeoutResponse = await jsonRest.get(timeoutUrl);
- const newStore = Utils.cloneObj(store);
- if(timeoutResponse.ok){
- const timeoutData = await timeoutResponse.json();
- newStore.disableExpiration = timeoutData.expiration;
- }
- // Change state and re-rendering
- setState({
- store: newStore
- });
- }else{
- response.text().then(data => {
- Utils.logMessage(`Failed to get store data. Error reason: ${response.status}->${data}`);
- });
- }
- };
-
- fetchStore();
- }, []);
-};
-
const RemoteAccessSection = ({store})=>
@@ -193,7 +156,41 @@ export default function RemoteView() {
message: ''
});
const {packageType, name} = useParams();
- init(packageType, name, setState);
+
+ useEffect(()=>{
+ const fetchStore = async () => {
+ const response = await jsonRest.get(`${STORE_API_BASE_URL}/${packageType}/remote/${name}`);
+ if (response.ok){
+ const raw = await response.json();
+ const store = Utils.cloneObj(raw);
+ store.disabled = raw.disabled === undefined ? false : raw.disabled;
+ store.useX509 = raw.server_certificate_pem || raw.key_certificate_pem;
+ store.useProxy = raw.proxy_host && true;
+ store.useAuth = store.useProxy && store.proxy_user;
+ store.useAuth = store.useAuth || store.user;
+
+ // get Store disablement data
+ const timeoutUrl = `/api/admin/schedule/store/${store.packageType}/${store.type}/${store.name}/disable-timeout`;
+ const timeoutResponse = await jsonRest.get(timeoutUrl);
+ const newStore = Utils.cloneObj(store);
+ if(timeoutResponse.ok){
+ const timeoutData = await timeoutResponse.json();
+ newStore.disableExpiration = timeoutData.expiration;
+ }
+ // Change state and re-rendering
+ setState({
+ store: newStore
+ });
+ }else{
+ response.text().then(data => {
+ Utils.logMessage(`Failed to get store data. Error reason: ${response.status}->${data}`);
+ });
+ }
+ };
+
+ fetchStore();
+ }, [packageType, name]);
+
const store = state.store;
if(!Utils.isEmptyObj(store)) {
return (
diff --git a/src/main/webui/src/app/components/nav/NavFooter.jsx b/src/main/webui/src/app/components/nav/NavFooter.jsx
index 114f98a..77b0010 100644
--- a/src/main/webui/src/app/components/nav/NavFooter.jsx
+++ b/src/main/webui/src/app/components/nav/NavFooter.jsx
@@ -24,26 +24,23 @@ import {Col, Row} from 'react-bootstrap';
export default function NavFooter() {
const [state, setState] = useState({stats: {}});
- (function(){
- const versionUrl = `/api/stats/version-info`;
- useEffect(()=>{
- const fetchVersion = async () => {
- const response = await jsonRest.get(versionUrl);
- if (response.ok){
- const raw = await response.json();
- setState({
- stats: raw
- });
- }else{
- response.text().then(data => {
- Utils.logMessage(`Failed to version info. Error reason: ${response.status}->${data}`);
- });
- }
- };
+ useEffect(()=>{
+ const fetchVersion = async () => {
+ const response = await jsonRest.get(`/api/stats/version-info`);
+ if (response.ok){
+ const raw = await response.json();
+ setState({
+ stats: raw
+ });
+ }else{
+ response.text().then(data => {
+ Utils.logMessage(`Failed to version info. Error reason: ${response.status}->${data}`);
+ });
+ }
+ };
- fetchVersion();
- }, []);
- }());
+ fetchVersion();
+ }, []);
const stats = state.stats;
const gridClass = "col-md-auto border-right border-secondary";
diff --git a/src/main/webui/src/content-browse/DirectoryListing.jsx b/src/main/webui/src/content-browse/DirectoryListing.jsx
index 0c99de4..87e5ac3 100644
--- a/src/main/webui/src/content-browse/DirectoryListing.jsx
+++ b/src/main/webui/src/content-browse/DirectoryListing.jsx
@@ -102,11 +102,16 @@ URLPage.propTypes = {
listingData: PropTypes.object.isRequired
};
-const init = setState => {
- const url =`/api${document.location.pathname}`;
+export default function DirectoryListing () {
+ const [state, setState] = useState({
+ error: null,
+ isLoaded: false,
+ data: {}
+ });
+
useEffect(()=>{
const fetchData = async () => {
- const response = await jsonRest.get(url);
+ const response = await jsonRest.get(`/api${document.location.pathname}`);
if(response.ok){
const data = await response.json();
setState({
@@ -122,16 +127,6 @@ const init = setState => {
};
fetchData();
}, []);
-};
-
-export default function DirectoryListing () {
- const [state, setState] = useState({
- error: null,
- isLoaded: false,
- data: {}
- });
-
- init(setState);
const {error, isLoaded, data} = state;
if (error) {