mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Release Notes
Release notes
This commit is contained in:
+40
-23
@@ -1,7 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import NextImage from 'next/image';
|
||||
import TimeAgo from 'react-timeago';
|
||||
|
||||
import { AspectRatio, Box, Button, Card, CardContent, CardOverflow, Container, Grid, Sheet, Typography } from '@mui/joy';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import LaunchIcon from '@mui/icons-material/Launch';
|
||||
@@ -57,13 +56,47 @@ export const newsRoadmapCallout =
|
||||
</CardContent>
|
||||
</Card>;
|
||||
|
||||
export function BuildInfoCard(props: { noMargin?: boolean }) {
|
||||
return (
|
||||
<Card variant='solid' color='neutral' invertedColors sx={props.noMargin ? undefined : { mb: 3 }}>
|
||||
<Typography level='title-md' sx={{ my: -1 }}>
|
||||
Development Build Information
|
||||
</Typography>
|
||||
<BuildInfoSheet />
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function BuildInfoSheet() {
|
||||
const backendBuild = React.useMemo(() => getBackendCapabilities().build, []);
|
||||
const frontendBuild = React.useMemo(() => Release.buildInfo('frontend'), []);
|
||||
return (
|
||||
<Sheet variant='soft' invertedColors sx={{
|
||||
fontSize: 'xs',
|
||||
// fontFamily: 'code',
|
||||
color: 'text.secondary',
|
||||
backgroundColor: 'background.popup',
|
||||
// border: '1px solid',
|
||||
// borderColor: 'divider',
|
||||
borderRadius: 'sm',
|
||||
// boxShadow: 'inset 1px 1px 4px -2px rgba(0,0,0,0.1)',
|
||||
p: 1,
|
||||
mb: -1,
|
||||
mx: -1,
|
||||
}}>
|
||||
PL: <strong>{Release.TenantSlug}</strong> · package {backendBuild?.pkgVersion} ({Release.Monotonics.NewsVersion}).<br />
|
||||
Frontend: {frontendBuild.gitSha} - deployed {frontendBuild.timestamp ? <strong><TimeAgo date={frontendBuild.timestamp} /></strong> : 'unknown'}, and
|
||||
backend {backendBuild?.gitSha}{backendBuild?.timestamp === frontendBuild.timestamp ? '.' : backendBuild?.timestamp ? <TimeAgo date={backendBuild?.timestamp!} /> : 'unknown.'}<br />
|
||||
Ships with -modal/-model: {Object.entries(Release.TechLevels).map(([name, version], idx, arr) => <><strong>{name}</strong> v{version}{idx < arr.length - 1 ? ', ' : ''}</>)}.<br />
|
||||
Ships with intelligent functions: {Release.AiFunctions.map((name, idx, arr) => <><i>{name}</i>{idx < arr.length - 1 ? ', ' : ''}</>)}.
|
||||
</Sheet>
|
||||
);
|
||||
}
|
||||
|
||||
export function AppNews() {
|
||||
// state
|
||||
const [lastNewsIdx, setLastNewsIdx] = React.useState<number>(NEWS_INITIAL_COUNT - 1);
|
||||
|
||||
const backendBuild = getBackendCapabilities().build;
|
||||
|
||||
// news selection
|
||||
const news = NewsItems.filter((_, idx) => idx <= lastNewsIdx);
|
||||
const firstNews = news[0] ?? null;
|
||||
@@ -117,6 +150,9 @@ export function AppNews() {
|
||||
const addPadding = false; //!firstCard; // || showExpander;
|
||||
return <React.Fragment key={idx}>
|
||||
|
||||
{/* Inject the Build Info Sheet */}
|
||||
{idx === 0 && <BuildInfoCard />}
|
||||
|
||||
{/* Inject the Big-AGI 2.0 item here*/}
|
||||
{/*{idx === 1 && (*/}
|
||||
{/* <Box sx={{ mb: 3 }}>*/}
|
||||
@@ -168,26 +204,7 @@ export function AppNews() {
|
||||
</ul>
|
||||
)}
|
||||
|
||||
{idx === 0 && (
|
||||
<Sheet variant='soft' invertedColors sx={{
|
||||
fontSize: 'xs',
|
||||
// fontFamily: 'code',
|
||||
color: 'text.secondary',
|
||||
// border: '1px solid',
|
||||
// borderColor: 'divider',
|
||||
borderRadius: 'sm',
|
||||
boxShadow: 'inset 1px 1px 4px -2px rgba(0,0,0,0.1)',
|
||||
p: 2,
|
||||
mb: -1,
|
||||
mx: -1,
|
||||
}}>
|
||||
PL: <strong>{Release.App.pl}</strong> · package {backendBuild?.pkgVersion} ({Release.Monotonics.NewsVersion}).<br />
|
||||
Frontend: {_frontendBuild.gitSha} - deployed {_frontendBuild.timestamp ? <strong><TimeAgo date={_frontendBuild.timestamp} /></strong> : 'unknown'}, and
|
||||
backend {backendBuild?.gitSha}{backendBuild?.timestamp === _frontendBuild.timestamp ? '.' : backendBuild?.timestamp ? <TimeAgo date={backendBuild?.timestamp!} /> : 'unknown.'}<br />
|
||||
Ships with -modal/-model: {Object.entries(Release.TechLevels).map(([name, version], idx, arr) => <><strong>{name}</strong> v{version}{idx < arr.length - 1 ? ', ' : ''}</>)}.<br />
|
||||
Ships with intelligent functions: {Release.AiFunctions.map((name, idx, arr) => <><i>{name}</i>{idx < arr.length - 1 ? ', ' : ''}</>)}.
|
||||
</Sheet>
|
||||
)}
|
||||
{/*{idx === 0 && <BuildInfoSheet />}*/}
|
||||
|
||||
</CardContent>
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ export const Release = {
|
||||
App: {
|
||||
versionCode: '2.0.0-open-rc2', // 1.92.0 sequentially...
|
||||
versionName: 'Big-AGI 2',
|
||||
releaseNotes: '',
|
||||
},
|
||||
|
||||
// Future compatibility
|
||||
|
||||
@@ -1,18 +1,30 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import type { SxProps } from '@mui/joy/styles/types';
|
||||
import { Box, IconButton, Typography } from '@mui/joy';
|
||||
import { Box, Dropdown, IconButton, ListDivider, ListItem, ListItemDecorator, Menu, MenuButton, MenuItem, Typography } from '@mui/joy';
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||
import EngineeringIcon from '@mui/icons-material/Engineering';
|
||||
import FeedbackIcon from '@mui/icons-material/Feedback';
|
||||
import LightbulbOutlinedIcon from '@mui/icons-material/LightbulbOutlined';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||
import NavigateNextIcon from '@mui/icons-material/NavigateNext';
|
||||
import NewReleasesIcon from '@mui/icons-material/NewReleases';
|
||||
|
||||
import { BuildInfoCard } from '../../../../apps/news/AppNews';
|
||||
import { blocksRenderHTMLIFrameCss } from '~/modules/blocks/code/code-renderers/RenderCodeHtmlIFrame';
|
||||
|
||||
import { BigAgiSquircleIcon } from '~/common/components/icons/big-agi/BigAgiSquircleIcon';
|
||||
import { Brand } from '~/common/app.config';
|
||||
import { GoodModal } from '~/common/components/modals/GoodModal';
|
||||
import { LayoutSidebarRight } from '~/common/components/icons/LayoutSidebarRight';
|
||||
import { Link } from '~/common/components/Link';
|
||||
import { Release } from '~/common/app.release';
|
||||
import { TooltipOutlined } from '~/common/components/TooltipOutlined';
|
||||
import { checkVisibleNav, NavItemApp } from '~/common/app.nav';
|
||||
import { navigateToIndex, ROUTE_INDEX } from '~/common/app.routes';
|
||||
// import { useDynamicUsersnap } from '~/common/components/3rdparty/Usersnap';
|
||||
import { useOverlayComponents } from '~/common/layout/overlays/useOverlayComponents';
|
||||
|
||||
import { InvertedBar, InvertedBarCornerItem } from '../InvertedBar';
|
||||
import { PopupPanel } from '../panel/PopupPanel';
|
||||
@@ -80,12 +92,51 @@ export function OptimaBar(props: { component: React.ElementType, currentApp?: Na
|
||||
const appMenuAnchor = React.useRef<HTMLButtonElement>(null);
|
||||
|
||||
// external state
|
||||
/**
|
||||
* NOTE: shall we fall back to the 'standard' release notes when not available on the tenant?
|
||||
* - prob not because this could be a per-company deployment, and we don't know the tenant's release notes
|
||||
*/
|
||||
const releaseNotesUrl = Release.App.releaseNotes;
|
||||
// const { openUsersnap, loadingError: usersnapLoadingError } = useDynamicUsersnap();
|
||||
const { showPromisedOverlay } = useOverlayComponents();
|
||||
const hasDrawerContent = useOptimaPortalHasInputs('optima-portal-drawer');
|
||||
const { panelAsPopup, panelHasContent, panelShownAsPanel, panelShownAsPopup } = useOptimaPanelOpen(props.isMobile, props.currentApp);
|
||||
|
||||
// derived state
|
||||
const navIsShown = checkVisibleNav(props.currentApp);
|
||||
|
||||
|
||||
// Handlers
|
||||
|
||||
const handleShowReleaseNotes = React.useCallback(async () => {
|
||||
if (!releaseNotesUrl) return;
|
||||
return await showPromisedOverlay('app-recent-changes', { rejectWithValue: false }, ({ onResolve, onUserReject }) =>
|
||||
<GoodModal
|
||||
open
|
||||
onClose={onUserReject}
|
||||
noTitleBar
|
||||
themedColor='neutral'
|
||||
unfilterBackdrop
|
||||
sx={{ minWidth: { xs: 400, sm: 580, md: 780, lg: 890 } }}
|
||||
>
|
||||
<iframe
|
||||
src={releaseNotesUrl}
|
||||
style={{ ...blocksRenderHTMLIFrameCss, height: '70svh' }}
|
||||
title='Release Notes Embed'
|
||||
loading='lazy' // do not load until visible in the viewport
|
||||
/>
|
||||
</GoodModal>,
|
||||
);
|
||||
}, [releaseNotesUrl, showPromisedOverlay]);
|
||||
|
||||
const handleShowTechnologies = React.useCallback(async () => {
|
||||
return await showPromisedOverlay<void>('app-recent-changes', {}, ({ onResolve }) =>
|
||||
<GoodModal open onClose={onResolve} noTitleBar unfilterBackdrop>
|
||||
<BuildInfoCard noMargin />
|
||||
</GoodModal>,
|
||||
);
|
||||
}, [showPromisedOverlay]);
|
||||
|
||||
// [Desktop] optionally hide the Bar if the current app asks for it
|
||||
if (props.currentApp?.hideBar && !props.isMobile && !panelHasContent)
|
||||
return null;
|
||||
@@ -115,7 +166,53 @@ export function OptimaBar(props: { component: React.ElementType, currentApp?: Na
|
||||
{/* Pluggable Toolbar Items */}
|
||||
<CenterItemsPortal currentApp={props.currentApp} />
|
||||
|
||||
{/* Panel/Menu button */}
|
||||
{/* (PREVIEW) Preview Menu */}
|
||||
{!props.isMobile && (
|
||||
<Dropdown>
|
||||
<MenuButton
|
||||
aria-label='Notifications Menu'
|
||||
slots={{ root: IconButton }}
|
||||
slotProps={{ root: { size: 'md' } }}
|
||||
>
|
||||
{/*<NotificationsNoneOutlinedIcon />*/}
|
||||
<LightbulbOutlinedIcon />
|
||||
{/*<FeedbackOutlinedIcon />*/}
|
||||
</MenuButton>
|
||||
|
||||
<Menu placement='bottom-end' sx={{ minWidth: 220 }}>
|
||||
<ListItem>
|
||||
<Typography level='body-xs' sx={{ textTransform: 'uppercase' }}>
|
||||
{Release.App.versionName}
|
||||
</Typography>
|
||||
</ListItem>
|
||||
|
||||
{!!releaseNotesUrl && (
|
||||
<MenuItem onClick={handleShowReleaseNotes}>
|
||||
<ListItemDecorator><NewReleasesIcon /></ListItemDecorator>
|
||||
Release Notes
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={handleShowTechnologies}>
|
||||
{/*<ListItemDecorator><EventNoteOutlinedIcon /></ListItemDecorator>*/}
|
||||
<ListItemDecorator><EngineeringIcon /></ListItemDecorator>
|
||||
Build Info
|
||||
</MenuItem>
|
||||
|
||||
|
||||
|
||||
{/*<ListDivider />*/}
|
||||
|
||||
{/*<TooltipOutlined title={usersnapLoadingError}>*/}
|
||||
{/* <MenuItem onClick={openUsersnap}>*/}
|
||||
{/* <ListItemDecorator><FeedbackIcon /></ListItemDecorator>*/}
|
||||
{/* Feedback -> Enrico*/}
|
||||
{/* </MenuItem>*/}
|
||||
{/*</TooltipOutlined>*/}
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
)}
|
||||
|
||||
{/* Panel Open: has content always on Mobile (the app menu) */}
|
||||
{panelHasContent && (
|
||||
<InvertedBarCornerItem>
|
||||
{/*<Tooltip disableInteractive title={contentToPopup ? (panelIsOpen ? 'Close' : 'Open') + ' Menu' : (panelIsOpen ? 'Close' : 'Open')}>*/}
|
||||
|
||||
@@ -17,6 +17,7 @@ interface OverlayItem {
|
||||
}
|
||||
|
||||
export type GlobalOverlayId = // string - disabled so we keep an orderliness
|
||||
| 'app-recent-changes' // Recent changes in the app, only private branch
|
||||
| 'chat-attachments-clear'
|
||||
| 'chat-delete-confirmation'
|
||||
| 'chat-reset-confirmation'
|
||||
|
||||
@@ -8,7 +8,7 @@ body { min-height: 100vh; line-height: 1.5; -webkit-font-smoothing: antialiased;
|
||||
img, picture, svg, video { display: block;max-width: 100%; }
|
||||
`;
|
||||
|
||||
const customIFrameCss: React.CSSProperties = {
|
||||
export const blocksRenderHTMLIFrameCss: React.CSSProperties = {
|
||||
flexGrow: 1,
|
||||
width: '100%',
|
||||
height: '54svh',
|
||||
@@ -18,8 +18,8 @@ const customIFrameCss: React.CSSProperties = {
|
||||
maxHeight: '100%',
|
||||
} as const;
|
||||
|
||||
const customIFrameFullscreenCss: React.CSSProperties = {
|
||||
...customIFrameCss,
|
||||
const blocksRenderHTMLIFrameFullScreenCss: React.CSSProperties = {
|
||||
...blocksRenderHTMLIFrameCss,
|
||||
height: undefined,
|
||||
flex: 1,
|
||||
} as const;
|
||||
@@ -86,7 +86,7 @@ export function RenderCodeHtmlIFrame(props: { htmlCode: string, isFullscreen?: b
|
||||
return (
|
||||
<iframe
|
||||
ref={iframeRef}
|
||||
style={props.isFullscreen ? customIFrameFullscreenCss : customIFrameCss}
|
||||
style={props.isFullscreen ? blocksRenderHTMLIFrameFullScreenCss : blocksRenderHTMLIFrameCss}
|
||||
title='Sandboxed Web Content'
|
||||
aria-label='Interactive content frame'
|
||||
sandbox='allow-scripts allow-same-origin allow-forms' // restrict to only these
|
||||
|
||||
Reference in New Issue
Block a user