Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[pull] master from postgres-ai:master #146

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

Merged
pull merged 2 commits into nagyist:master from postgres-ai:master
Mar 17, 2025
Merged
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
7 changes: 6 additions & 1 deletion ui/packages/platform/src/pages/Bot/ChatsList/ChatsList.tsx
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const useStyles = makeStyles<Theme, ChatsListProps>((theme) => ({
[theme.breakpoints.down('sm')]: {
height: '100vh!important',
marginTop: '0!important',
width: 320,
width: 'min(100%, 360px)',
zIndex: 9999
},
'& > ul': {
Expand All @@ -57,6 +57,11 @@ const useStyles = makeStyles<Theme, ChatsListProps>((theme) => ({
background: 'white',
[theme.breakpoints.down('sm')]: {
padding: 0
},
"@media (max-width: 960px)": {
"& .MuiFormControl-root": {
display: "none" // Hide model selector in chats list
}
}
},
listItemLink: {
Expand Down
81 changes: 81 additions & 0 deletions ui/packages/platform/src/pages/Bot/ModelSelector/ModelSelector.tsx
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React from 'react';
import { FormControl, Select, MenuItem, Typography, InputLabel, useMediaQuery } from "@mui/material";
import { SelectChangeEvent } from "@mui/material/Select";

import { useAiBot } from "../hooks";

export const ModelSelector = () => {
const { aiModel, aiModels, setAiModel } = useAiBot();
const isSmallScreen = useMediaQuery("(max-width: 960px)");

const handleChange = (event: SelectChangeEvent<string | null>) => {
const [vendor, name] = (event.target.value as string).split("/");
const model = aiModels?.find(
(model) => model.vendor === vendor && model.name === name
);
if (model) setAiModel(model);
};

const truncateText = (text: string, maxLength: number) => {
return text.length > maxLength ? text.substring(0, maxLength) + "..." : text;
};

return (
<FormControl
variant="outlined"
size="small"
sx={{ minWidth: isSmallScreen ? 120 : 200 }}
>
<Select
labelId="model-select-label"
id="model-select"
value={aiModel ? `${aiModel.vendor}/${aiModel.name}` : ""}
onChange={handleChange}
displayEmpty
inputProps={{
"aria-describedby": "Select the AI model to be used for generating responses. Different models may vary in performance. Choose the one that best suits your needs.",
sx: {
height: "32px",
fontSize: "0.875rem",
padding: isSmallScreen ? "8px 24px 8px 8px!important" : "8px 14px",
},
}}
sx={{ height: "32px" }}
renderValue={(selected) => {
if (!selected) return "Select Model";
const [vendor, name] = selected.split("/");
return truncateText(`${vendor}/${name}`, isSmallScreen ? 20 : 30);
}}
>
{aiModels &&
aiModels.map((model) => (
<MenuItem
key={`${model.vendor}/${model.name}`}
value={`${model.vendor}/${model.name}`}
title={`${model.vendor}/${model.name}`}
sx={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start"
}}
>
<span>{truncateText(`${model.vendor}/${model.name}`, isSmallScreen ? 33 : 40)}</span>
{model.comment && (
<Typography
variant="body2"
color="textSecondary"
sx={{
fontSize: "0.7rem",
color: "rgba(0, 0, 0, 0.6)",
}}
aria-hidden="true"
>
{model.comment}
</Typography>
)}
</MenuItem>
))}
</Select>
</FormControl>
);
};
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
makeStyles,
Radio,
RadioGroup,
TextField,
TextField, Theme,
Typography,
} from '@material-ui/core'
import MuiDialogTitle from '@material-ui/core/DialogTitle'
Expand All @@ -30,6 +30,8 @@ import { AiModel } from "../../../types/api/entities/bot";
import settings from "../../../utils/settings";
import { Link } from "@postgres.ai/shared/components/Link2";
import { ExternalIcon } from "@postgres.ai/shared/icons/External";
import Divider from "@material-ui/core/Divider";
import cn from "classnames";

type DialogTitleProps = {
id: string
Expand Down Expand Up @@ -123,35 +125,30 @@ const DialogActions = (props: { children: React.ReactNode }) => {
)
}

const useDialogStyles = makeStyles(
() => ({
const useDialogStyles = makeStyles<Theme>(
(theme) => ({
textField: {
...styles.inputField,
marginTop: '0px',
width: 480,
[theme.breakpoints.down('sm')]: {

}
},
copyButton: {
marginTop: '-3px',
fontSize: '20px',
},
dialog: {},
remark: {
fontSize: 12,
lineHeight: '12px',

paddingLeft: 20,
paddingBottom: 5,
},
remarkIcon: {
display: 'block',
height: '20px',
width: '22px',
float: 'left',
paddingTop: '5px',
},
urlContainer: {
marginTop: 10,
paddingLeft: 22,
marginTop: 8,
paddingLeft: 20,
[theme.breakpoints.down('sm')]: {
padding: 0,
width: '100%',
'& .MuiTextField-root': {
maxWidth: 'calc(100% - 36px)'
}
},
},
radioGroup: {
fontSize: 12,
Expand All @@ -170,16 +167,34 @@ const useDialogStyles = makeStyles(
marginBottom: 0
}
},
unlockNoteDemo: {
paddingLeft: 20
},
formControlLabel: {
'& .Mui-disabled > *, & .Mui-disabled': {
color: 'rgba(0, 0, 0, 0.6)'
},
[theme.breakpoints.down('sm')]: {
marginRight: 0,
alignItems: 'flex-start',
'&:first-child': {
marginTop: 6
}
},
},
formControlLabelRadio: {
[theme.breakpoints.down('sm')]: {
padding: '4px 9px'
}
},
externalIcon: {
width: 14,
height: 14,
marginLeft: 4,
transform: 'translateY(2px)',
},
divider: {
margin: '12px 0'
}
}),
{ index: 1 },
Expand Down Expand Up @@ -295,8 +310,8 @@ export const SettingsDialog = (props: PublicChatDialogProps) => {
<>
<FormLabel component="legend">Visibility</FormLabel>
<RadioGroup
aria-label="shareUrl"
name="shareUrl"
aria-label="Thread visibility"
name="threadVisibility"
value={visibility}
onChange={(event) => {
setVisibility(event.target.value as Visibility)
Expand All @@ -306,20 +321,22 @@ export const SettingsDialog = (props: PublicChatDialogProps) => {
<FormControlLabel
value={Visibility.PUBLIC}
className={classes.formControlLabel}
control={<Radio />}
control={<Radio className={classes.formControlLabelRadio} />}
label={<><b>Public:</b> anyone can view chats, but only team members can respond</>}
aria-label="Public: anyone can view chats, but only team members can respond"
/>
{visibility === Visibility.PUBLIC && threadId && (
<div className={classes.urlContainer}>{urlField}</div>
)}
<FormControlLabel
value={Visibility.PRIVATE}
className={classes.formControlLabel}
control={<Radio />}
control={<Radio className={classes.formControlLabelRadio} />}
label={<><b>Private:</b> chats are visible only to members of your organization</>}
aria-label="Private: chats are visible only to members of your organization"
disabled={Boolean(isDemoOrg) || !isSubscriber}
/>
{Boolean(isDemoOrg) && <Typography className={classes.remark}>Private chats are not allowed in "Demo"</Typography>}
{Boolean(isDemoOrg) && <Typography className={cn(classes.unlockNote, classes.unlockNoteDemo)}>Private chats are not allowed in "Demo"</Typography>}
{!Boolean(isDemoOrg) && !isSubscriber && <Typography variant="body2" className={classes.unlockNote}>
Unlock private conversations by either:
<ol>
Expand All @@ -339,29 +356,6 @@ export const SettingsDialog = (props: PublicChatDialogProps) => {
</Typography>}
</RadioGroup>
</>
{aiModels && <>
<FormLabel component="legend">Model</FormLabel>
<RadioGroup
aria-label="model"
name="model"
value={`${model?.vendor}/${model?.name}`}
onChange={(event) => {
const selectedModel = aiModels?.find((model) => `${model.vendor}/${model.name}` === event.target.value)
setModel(selectedModel!)
}}
className={classes.radioGroup}
>
{aiModels.map((model) =>
<FormControlLabel
key={`${model.vendor}/${model.name}`}
value={`${model.vendor}/${model.name}`}
control={<Radio />}
label={`${model.name} ${model.comment ? model.comment : ''}`}
/>
)
}
</RadioGroup>
</>}
</DialogContent>

<DialogActions>
Expand Down
74 changes: 25 additions & 49 deletions ui/packages/platform/src/pages/Bot/SettingsPanel/SettingsPanel.tsx
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { theme } from "@postgres.ai/shared/styles/theme";
import { permalinkLinkBuilder } from "../utils";
import { useAiBot } from "../hooks";
import DeveloperModeIcon from "@material-ui/icons/DeveloperMode";
import { ModelSelector } from "../ModelSelector/ModelSelector";
import { Skeleton } from "@mui/material";

export type SettingsPanelProps = {
onSettingsClick: () => void;
Expand All @@ -31,25 +33,14 @@ const useStyles = makeStyles((theme) => ({
}
},
labelVisibility: {
marginLeft: '0.5rem',
marginRight: '0.5rem',
[theme.breakpoints.down('sm')]: {
marginLeft: '0.25rem'
marginRight: '0.25rem'
},
'&:hover': {
backgroundColor: colors.secondary1.main
}
},
labelModel: {
background: colors.secondary1.main,
},
labelModelInvalid: {
background: colors.state.error,
border: "none",
cursor: 'pointer',
'&:hover': {
backgroundColor: colors.primary.dark
}
},
labelPrivate: {
backgroundColor: colors.pgaiDarkGray,
},
Expand All @@ -74,48 +65,33 @@ const useStyles = makeStyles((theme) => ({

export const SettingsPanel = (props: SettingsPanelProps) => {
const { onSettingsClick, onConsoleClick } = props;
const { loading } = useAiBot()
const classes = useStyles();
const matches = useMediaQuery(theme.breakpoints.down('sm'));
const { messages, chatVisibility, aiModel, aiModelsLoading } = useAiBot();
const { messages, chatVisibility, aiModelsLoading } = useAiBot();
const permalinkId = useMemo(() => messages?.[0]?.id, [messages]);

let modelLabel;

if (aiModel) {
modelLabel = (
<span
className={cn(classes.label, classes.labelModel)}
>
{aiModel.name}
</span>
)
} else {
modelLabel = (
<button
className={cn(classes.label, classes.labelModelInvalid)}
onClick={onSettingsClick}
>
Model not set
</button>
)
}

return (
<>
{!aiModelsLoading && modelLabel}
{permalinkId && <a
href={permalinkId && chatVisibility === 'public' ? permalinkLinkBuilder(permalinkId) : ''}
className={cn(classes.label, classes.labelVisibility,
{
[classes.labelPrivate]: chatVisibility === 'private',
[classes.disabled]: chatVisibility === 'private' || !permalinkId
}
)}
target="_blank"
aria-disabled={chatVisibility === 'private' || !permalinkId}
>
<span>{chatVisibility}</span> thread
</a>}
{permalinkId && <>
{loading
? <Skeleton variant="rectangular" className={cn(classes.label, classes.labelVisibility)} width={64} height={16} />
: <a
href={permalinkId && chatVisibility === 'public' ? permalinkLinkBuilder(permalinkId) : ''}
className={cn(classes.label, classes.labelVisibility,
{
[classes.labelPrivate]: chatVisibility === 'private',
[classes.disabled]: chatVisibility === 'private' || !permalinkId
}
)}
target="_blank"
aria-disabled={chatVisibility === 'private' || !permalinkId}
>
<span>{chatVisibility}</span> thread
</a>
}
</>}
{!aiModelsLoading && <ModelSelector />}
<Button
variant="outlined"
onClick={onSettingsClick}
Expand Down
Loading

AltStyle によって変換されたページ (->オリジナル) /