Skip to content

Commit 93387c7

Browse files
authored
Merge pull request #298 from opengovern/ui-changes
UI changes
2 parents bd59c00 + 80af46b commit 93387c7

File tree

19 files changed

+1262
-15
lines changed

19 files changed

+1262
-15
lines changed

services/webui/.env

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
NODE_ENV=development
22
REACT_APP_RUNTIME_ENVIRONMENT=production
3-
REACT_APP_BASE_URL=https://open.comply.dev
4-
REACT_APP_AUTH_BASE_URL=https://open.comply.dev
5-
REACT_APP_SHOW_COMPLIANCE=false
3+
REACT_APP_BASE_URL=https://demo.opensecurity.sh
4+
REACT_APP_AUTH_BASE_URL=https://demo.opensecurity.sh
5+
REACT_APP_SHOW_COMPLIANCE=true

services/webui/public/env-config.js

Lines changed: 1 addition & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import axios from 'axios';
2+
import { useEffect, useState } from 'react';
3+
import { Agent } from './types';
4+
import { useNavigate } from 'react-router-dom';
5+
import LoadingDots from '../Loading';
6+
import Tooltip from '../Tooltip';
7+
import { Button, Modal } from '@cloudscape-design/components'
8+
import Cal, { getCalApi } from '@calcom/embed-react'
9+
import { Flex } from '@tremor/react'
10+
function Agents() {
11+
const [open,setOpen] = useState(false)
12+
const [openCal, setOpenCal] = useState(false)
13+
14+
const [agents, setAgents] = useState<Agent[]>([
15+
{
16+
name: 'Identity & Access',
17+
description:
18+
'Delivers information on user identities, access controls, and activity.',
19+
welcome_message:
20+
'Hi there! This is your Identity & Access Agent. I can help you with anything related to identity management and access tools. What can I assist you with today? For example, you can ask me things like:',
21+
sample_questions: [
22+
'Get me the list of users who have access to Azure Subscriptions.',
23+
'Get me all SPNs with expired passwords.',
24+
'Show me the access activity for user John Doe.',
25+
],
26+
id: 'identity_access',
27+
enabled: true,
28+
is_available: true,
29+
},
30+
{
31+
name: 'DevOps',
32+
description:
33+
'Provides data on secure code, deployment, and automation workflows.',
34+
welcome_message:
35+
'Hello! This is your DevOps Agent. I can provide insights into secure code, deployment, and automation workflows. How can I assist you today? For instance, you could ask me:',
36+
sample_questions: [
37+
'What are the latest secure code scan results?',
38+
'Show me the deployment status for the production environment.',
39+
'Provide a report on automated workflow execution times.',
40+
],
41+
id: 'devops',
42+
enabled: true,
43+
is_available: true,
44+
},
45+
{
46+
name: 'Sales',
47+
description:
48+
'Answers questions about sales activities, including: total activities per rep, activity breakdown by type, activity per deal, deal stage progression activity, and time to first activity. Enables analysis of sales rep performance and deal progression.',
49+
welcome_message:
50+
'Hello! This is your Sales Agent. I can answer questions about sales activities, including total activities per rep, activity breakdown by type, activity per deal, deal stage progression activity, and time to first activity. What can I help you with? For example:',
51+
sample_questions: [
52+
'Show me the total activities (calls, emails, meetings) for each sales rep.',
53+
'Which sales reps had the most/least activities?',
54+
'How much activity was logged for each deal we closed?',
55+
],
56+
id: 'sales',
57+
enabled: true,
58+
is_available: true,
59+
},
60+
])
61+
const selected_agent = {
62+
id: 'identity_access',
63+
}
64+
const navigate = useNavigate()
65+
66+
67+
68+
return (
69+
<>
70+
<div className=" bg-slate-200 dark:bg-gray-950 h-full w-full max-w-sm justify-start items-start max-h-[90vh] flex flex-col gap-2 ">
71+
<div
72+
id="k-agent-bar"
73+
className="flex flex-col gap-2 max-h-[90vh] overflow-y-scroll mt-2 "
74+
>
75+
{agents?.map((agent) => {
76+
return (
77+
<div
78+
key={agent.id}
79+
onClick={() => {
80+
setOpen(true)
81+
}}
82+
className={`rounded-sm flex flex-col justify-start items-start gap-2 hover:dark:bg-gray-700 hover:bg-gray-400 cursor-pointer p-2 ${
83+
selected_agent?.id == agent.id &&
84+
' bg-slate-400 dark:bg-slate-800'
85+
}`}
86+
>
87+
<span className="text-base text-slate-950 dark:text-slate-200">
88+
{agent.name}
89+
</span>
90+
<span className="text-sm text-slate-500 dark:text-slate-400">
91+
{agent.description}
92+
</span>
93+
</div>
94+
)
95+
})}
96+
</div>
97+
</div>
98+
<Modal
99+
size="medium"
100+
visible={open}
101+
onDismiss={() => setOpen(false)}
102+
header="Not available"
103+
>
104+
<Flex className="flex-col gap-2">
105+
<span>
106+
{' '}
107+
This feature is only available on commercial version.
108+
</span>
109+
<Button
110+
onClick={() => {
111+
setOpenCal(true)
112+
}}
113+
>
114+
Contact us
115+
</Button>
116+
</Flex>
117+
</Modal>
118+
<Modal
119+
size="large"
120+
visible={openCal}
121+
onDismiss={() => setOpenCal(false)}
122+
header="Not available"
123+
>
124+
<Cal
125+
namespace="try-enterprise"
126+
calLink="team/clearcompass/try-enterprise"
127+
style={{
128+
width: '100%',
129+
height: '100%',
130+
overflow: 'scroll',
131+
}}
132+
config={{ layout: 'month_view' }}
133+
/>
134+
</Modal>
135+
</>
136+
)
137+
}
138+
139+
export default Agents;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface Agent {
2+
id: string
3+
name: string
4+
description: string
5+
is_available: boolean
6+
enabled: boolean
7+
welcome_message: string
8+
sample_questions: string[]
9+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { FunctionComponent } from "react";
2+
3+
interface ChatCardProps {
4+
message: string;
5+
keyNumber: number;
6+
date : string
7+
}
8+
9+
const KChatCard: FunctionComponent<any> = ({
10+
message,
11+
keyNumber,
12+
date
13+
}: ChatCardProps) => {
14+
return (
15+
<div key={keyNumber} className=" w-full flex flex-col justify-start items-start">
16+
<div className="flex flex-row gap-1 justify-start items-center">
17+
<span>You</span>
18+
<span className=" text-sm text-slate-800 dark:text-slate-300">{date}</span>
19+
</div>
20+
<span className=" rounded-3xl text-slate-800 dark:text-slate-200 text-left w-fit">{message}</span>
21+
</div>
22+
);
23+
};
24+
25+
export default KChatCard;
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { PaperAirplaneIcon } from "@heroicons/react/24/outline";
2+
import { ChangeEvent, ChangeEventHandler, FunctionComponent, KeyboardEvent, useContext, useEffect, useRef, useState, } from "react";
3+
4+
interface InputProps {
5+
onChange: ChangeEventHandler;
6+
value: string;
7+
onSend: Function;
8+
disabled: boolean;
9+
chats: any;
10+
}
11+
12+
const KInput: FunctionComponent<any> = ({
13+
onChange,
14+
value,
15+
onSend,
16+
disabled,
17+
chats
18+
}: InputProps) => {
19+
// const { Theme, changeTheme } = useContext(ThemeContext);
20+
const [is_dark, setIsDark] = useState(false);
21+
22+
23+
const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
24+
if (event.key === "Enter" && event.shiftKey) {
25+
// Handle Shift+Enter: Add a new line
26+
event.preventDefault(); // Prevent the default behavior of form submission
27+
const e = {
28+
target: {
29+
value: value + "\n",
30+
},
31+
};
32+
onChange(e as ChangeEvent<HTMLInputElement>); // Update the input value with a new line
33+
} else if (event.key === "Enter") {
34+
// Handle Enter: Send the input
35+
event.preventDefault(); // Prevent default behavior
36+
handleSend();
37+
}
38+
};
39+
40+
const handleSend = () => {
41+
if (value.trim() !== "") {
42+
const trimmedValue = value.trim(); // Remove leading and trailing whitespaces
43+
const e = {
44+
target: {
45+
value: trimmedValue,
46+
},
47+
};
48+
onChange(e as ChangeEvent<HTMLInputElement>); // Update the input value with the trimmed value
49+
onSend(); // Trigger the send callback with the current input value
50+
}
51+
52+
};
53+
const firstRender= useRef(false);
54+
// useEffect(()=>{
55+
// if(!firstRender.current || chats.length==0){
56+
// if (value == '' || value == undefined) {
57+
// // @ts-ignore
58+
// onChange({ target: { value: 'Get List of all identities' } });
59+
// }
60+
// firstRender.current=true;
61+
62+
// }
63+
64+
// },[value])
65+
return (
66+
<>
67+
<div
68+
className={` dark:bg-gray-950 bg-slate-200 w-full px-1 sm:px-0 flex justify-center items-center flex-row max-w-[98%] absolute bottom-2 ${window.innerWidth<640 && 'left-0'} `}
69+
>
70+
<div className=" sm:w-full w-[98%] h-12 flex flex-row sm:justify-start justify-center items-center bg-gray-300 dark:bg-gray-950 rounded-full dark:border-slate-600 border-slate-200 border ">
71+
<input
72+
value={value}
73+
onKeyDown={(e) => {
74+
if (!disabled) {
75+
handleKeyDown(e);
76+
}
77+
}}
78+
onChange={onChange}
79+
placeholder="Ask from AI"
80+
className="w-full max-w-[94%] k-input bg-gray-300 dark:bg-gray-950 border-none h-10 rounded-full text-slate-900 dark:text-slate-300 shadow-none placeholder:text-slate-600 dark:placeholder:text-slate-500 focus:shadow-none focus:outline-0 focus:ring-0 resize-none overflow-y-auto text-base p-2 px-4 "
81+
></input>
82+
<button
83+
onClick={() => {
84+
onSend();
85+
}}
86+
disabled={disabled}
87+
className={` absolute right-3 ${is_dark ? 'text-white' : 'text-black'} rounded-full p-2 disabled:text-gray-500 `}
88+
>
89+
<PaperAirplaneIcon color="black" className="w-5" />
90+
</button>
91+
</div>
92+
</div>
93+
</>
94+
);
95+
};
96+
97+
export default KInput;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
/* Individual dot style */
3+
.dot {
4+
width: 7px;
5+
height: 7px;
6+
border-radius: 50%;
7+
animation: blink 1s infinite;
8+
}
9+
10+
/* Delay the blinking for each dot */
11+
.dot:nth-child(2) {
12+
animation-delay: 0.2s;
13+
}
14+
15+
.dot:nth-child(3) {
16+
animation-delay: 0.4s;
17+
}
18+
19+
/* Blinking animation */
20+
@keyframes blink {
21+
0%, 80%, 100% {
22+
opacity: 0;
23+
}
24+
40% {
25+
opacity: 1;
26+
}
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import React from "react";
2+
import "./index.css"; // Add the CSS from above here
3+
4+
const LoadingDots = () => {
5+
return <span className="dot bg-gray-950 dark:bg-slate-100 mt-1"></span>;
6+
};
7+
8+
export default LoadingDots;

0 commit comments

Comments
 (0)