Skip to content

Commit

Permalink
Merge pull request #112 from tarilabs/tarilabs-20240826-sync
Browse files Browse the repository at this point in the history
periodic sync upstream KF to midstream ODH
  • Loading branch information
openshift-merge-bot[bot] committed Aug 26, 2024
2 parents 6ebe77f + b399b43 commit 024fb6d
Show file tree
Hide file tree
Showing 20 changed files with 927 additions and 701 deletions.
279 changes: 147 additions & 132 deletions clients/python/poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion clients/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ coverage = { extras = ["toml"], version = "^7.3.2" }
pytest-cov = ">=4.1,<6.0"
ruff = ">=0.5.2,<0.7.0"
mypy = "^1.7.0"
pytest-asyncio = "^0.23.7"
pytest-asyncio = ">=0.23.7,<0.25.0"
requests = "^2.32.2"
black = "^24.4.2"

Expand Down
828 changes: 313 additions & 515 deletions clients/ui/frontend/package-lock.json

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions clients/ui/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"scripts": {
"build": "run-s build:prod",
"build:analyze": "run-s build build:bundle-profile build:bundle-analyze",
"build:bundle-profile": "_ODH_OUTPUT_ONLY=true webpack --config ./config/webpack.prod.js --profile --json > ./bundle.stats.json",
"build:bundle-profile": "webpack --config ./config/webpack.prod.js --profile --json > ./bundle.stats.json",
"build:bundle-analyze": "webpack-bundle-analyzer ./bundle.stats.json",
"build:clean": "rimraf ./public",
"build:prod": "webpack --config ./config/webpack.prod.js",
Expand All @@ -32,7 +32,7 @@
"@cypress/code-coverage": "^3.12.45",
"@testing-library/cypress": "^10.0.1",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^14.0.0",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "14.4.3",
"@types/jest": "^29.5.12",
"@types/react-router-dom": "^5.3.3",
Expand All @@ -42,7 +42,7 @@
"chai-subset": "^1.6.0",
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^6.11.0",
"css-minimizer-webpack-plugin": "^5.0.1",
"css-minimizer-webpack-plugin": "^7.0.0",
"cypress": "^13.10.0",
"cypress-axe": "^1.5.0",
"cypress-high-resolution": "^1.0.0",
Expand All @@ -63,17 +63,17 @@
"prettier": "^3.3.3",
"prop-types": "^15.8.1",
"raw-loader": "^4.0.2",
"react-router-dom": "^6.4.1",
"react-router-dom": "^6.26.1",
"regenerator-runtime": "^0.14.1",
"rimraf": "^6.0.1",
"serve": "^14.2.1",
"style-loader": "^4.0.0",
"svg-url-loader": "^8.0.0",
"terser-webpack-plugin": "^5.3.10",
"ts-jest": "^29.2.4",
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.1",
"tsconfig-paths-webpack-plugin": "^4.1.0",
"tslib": "^2.6.3",
"tslib": "^2.7.0",
"typescript": "^5.5.4",
"url-loader": "^4.1.1",
"webpack": "^5.91.0",
Expand All @@ -86,6 +86,7 @@
"@patternfly/react-core": "6.0.0-alpha.102",
"@patternfly/react-icons": "6.0.0-alpha.35",
"@patternfly/react-styles": "6.0.0-alpha.35",
"lodash-es": "^4.17.21",
"npm-run-all": "^4.1.5",
"react": "^18",
"react-dom": "^18"
Expand Down
100 changes: 86 additions & 14 deletions clients/ui/frontend/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,88 @@ import '@patternfly/react-core/dist/styles/base.css';
import AppRoutes from './AppRoutes';
import './app.css';
import {
Alert,
Bullseye,
Button,
Flex,
Masthead,
MastheadContent,
MastheadToggle,
Page,
PageSection,
PageToggleButton,
Title
} from '@patternfly/react-core';
import NavSidebar from './NavSidebar';
import { BarsIcon } from '@patternfly/react-icons';
Spinner,
Stack,
StackItem,
Title,
} from "@patternfly/react-core";
import NavSidebar from "./NavSidebar";
import { BarsIcon } from "@patternfly/react-icons";
import { AppContext } from "./AppContext";
import { useSettings } from "./useSettings";

const App: React.FC = () => {
const {
configSettings,
userSettings,
loaded: configLoaded,
loadError: configError,
} = useSettings();

const contextValue = React.useMemo(
() =>
configSettings && userSettings
? {
config: configSettings!,
user: userSettings!,
}
: null,
[configSettings, userSettings]
);

// We lack the critical data to startup the app
if (configError) {
// There was an error fetching critical data
return (
<Page>
<PageSection>
<Stack hasGutter>
<StackItem>
<Alert variant="danger" isInline title="General loading error">
<p>
{configError.message ||
"Unknown error occurred during startup."}
</p>
<p>Logging out and logging back in may solve the issue.</p>
</Alert>
</StackItem>
<StackItem>
<Button
variant="secondary"
onClick={() => {
// TODO: logout
}}
>
Logout
</Button>
</StackItem>
</Stack>
</PageSection>
</Page>
);
}

// Waiting on the API to finish
const loading = !configLoaded || !userSettings || !configSettings || !contextValue;

const masthead = (
<Masthead>
<MastheadToggle>
<PageToggleButton id="page-nav-toggle" variant="plain" aria-label="Dashboard navigation">
<PageToggleButton
id="page-nav-toggle"
variant="plain"
aria-label="Dashboard navigation"
>
<BarsIcon />
</PageToggleButton>
</MastheadToggle>
Expand All @@ -33,15 +99,21 @@ const App: React.FC = () => {
</Masthead>
);

return (
<Page
mainContainerId='primary-app-container'
masthead={masthead}
isManagedSidebar
sidebar={<NavSidebar />}
>
<AppRoutes />
</Page>
return loading ? (
<Bullseye>
<Spinner />
</Bullseye>
) : (
<AppContext.Provider value={contextValue}>
<Page
mainContainerId="primary-app-container"
masthead={masthead}
isManagedSidebar
sidebar={<NavSidebar />}
>
<AppRoutes />
</Page>
</AppContext.Provider>
);
};

Expand Down
13 changes: 13 additions & 0 deletions clients/ui/frontend/src/app/AppContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as React from 'react';
import { UserSettings, ConfigSettings } from '~/types';


type AppContextProps = {
config: ConfigSettings;
user: UserSettings;
};

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
export const AppContext = React.createContext({} as AppContextProps);

export const useAppContext = (): AppContextProps => React.useContext(AppContext);
84 changes: 84 additions & 0 deletions clients/ui/frontend/src/app/useSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import * as React from "react";
import useTimeBasedRefresh from "./useTimeBasedRefresh";
import { ConfigSettings, UserSettings } from "../types";
import { POLL_INTERVAL } from "~/utilities/const";
import { useDeepCompareMemoize } from "../utilities/useDeepCompareMemoize";

export const useSettings = (): {
configSettings: ConfigSettings | null;
userSettings: UserSettings | null;
loaded: boolean;
loadError: Error | undefined;
} => {
const [loaded, setLoaded] = React.useState(false);
const [loadError, setLoadError] = React.useState<Error>();
const [config, setConfig] = React.useState<ConfigSettings | null>(null);
const [user, setUser] = React.useState<UserSettings | null>(null);
const setRefreshMarker = useTimeBasedRefresh();

React.useEffect(() => {
let watchHandle: ReturnType<typeof setTimeout>;
let cancelled = false;
const watchConfig = () => {
Promise.all([fetchConfig(), fetchUser()])
.then(([config, user]) => {
if (cancelled) {
return;
}
setConfig(config);
setUser(user);
setLoaded(true);
setLoadError(undefined);
})
.catch((e) => {
if (e?.message?.includes("Error getting Oauth Info for user")) {
// NOTE: this endpoint only requests oauth because of the security layer, this is not an ironclad use-case
// Something went wrong on the server with the Oauth, let us just log them out and refresh for them
/* eslint-disable-next-line no-console */
console.error(
"Something went wrong with the oauth token, please log out...",
e.message,
e
);
setRefreshMarker(new Date());
return;
}
setLoadError(e);
});
watchHandle = setTimeout(watchConfig, POLL_INTERVAL);
};
watchConfig();

return () => {
cancelled = true;
clearTimeout(watchHandle);
};
}, [setRefreshMarker]);

const retConfig = useDeepCompareMemoize<ConfigSettings | null>(config);
const retUser = useDeepCompareMemoize<UserSettings | null>(user);

return { configSettings: retConfig, userSettings: retUser, loaded, loadError };
};

// Mock a settings config call
// TODO: replace with thea actual call once we have the endpoint
export const fetchConfig = async (): Promise<ConfigSettings> => {
return {
common: {
featureFlags: {
modelRegistry: true,
},
},
};
};

// Mock a settings user call
// TODO: replace with thea actual call once we have the endpoint
export const fetchUser = async (): Promise<UserSettings> => {
return {
username: "admin",
isAdmin: true,
isAllowed: true,
};
};
48 changes: 48 additions & 0 deletions clients/ui/frontend/src/app/useTimeBasedRefresh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as React from 'react';
import { useBrowserStorage } from '~/components/browserStorage';


export type SetTime = (refreshDateMarker: Date) => void;

const useTimeBasedRefresh = (): SetTime => {
const KEY_NAME = 'kf.dashboard.last.auto.refresh';
const [lastRefreshTimestamp, setLastRefreshTimestamp] = useBrowserStorage(
KEY_NAME,
'0',
false,
true,
);
const ref = React.useRef<{
lastRefreshTimestamp: string;
setLastRefreshTimestamp: (newValue: string) => void;
}>({ lastRefreshTimestamp, setLastRefreshTimestamp });
ref.current = { lastRefreshTimestamp, setLastRefreshTimestamp };

return React.useCallback<SetTime>((refreshDateMarker) => {
// Intentionally avoid referential changes. We want the value at call time.
// Recomputing the ref is not needed and will impact usage in hooks if it does.
const lastDate = new Date(ref.current.lastRefreshTimestamp);
const setNewDateString = ref.current.setLastRefreshTimestamp;

/* eslint-disable no-console */
// Print into the console in case we are not refreshing or the browser has preserve log enabled
console.warn('Attempting to re-trigger an auto refresh');
console.log('Last refresh was on:', lastDate);
console.log('Refreshing requested after:', refreshDateMarker);

lastDate.setHours(lastDate.getHours() + 1);
if (lastDate < refreshDateMarker) {
setNewDateString(refreshDateMarker.toString());
console.log('Logging out and refreshing');
// TODO: Replace with actual logout function
//logout().then(() => window.location.reload());
} else {
console.error(
`We should have refreshed but it appears the last time we auto-refreshed was less than an hour ago. '${KEY_NAME}' session storage setting can be cleared for this to refresh again within the hour from the last refresh.`,
);
}
/* eslint-enable no-console */
}, []);
};

export default useTimeBasedRefresh;
Empty file.
Loading

0 comments on commit 024fb6d

Please sign in to comment.