Skip to content

Commit

Permalink
iniital set up for project specific chat ui for MICA
Browse files Browse the repository at this point in the history
  • Loading branch information
irvins committed Jun 14, 2024
1 parent f3b6cb1 commit 399766c
Show file tree
Hide file tree
Showing 28 changed files with 163 additions and 204 deletions.
46 changes: 9 additions & 37 deletions MICA.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@ class MICA extends \ExternalModules\AbstractExternalModule {

const SecureChatInstanceModuleName = 'SecureChatAI';

private $system_context;
private $system_context_persona;
private $system_context_steps;

private $system_context_rules;

private $entityFactory;

public function __construct() {
parent::__construct();
$this->system_context = $this->getSystemSetting('chatbot_system_context');
$this->system_context_persona = $this->getSystemSetting('chatbot_system_context_persona');
$this->system_context_steps = $this->getSystemSetting('chatbot_system_context_steps');
$this->system_context_rules = $this->getSystemSetting('chatbot_system_context_rules');

$this->entityFactory = new \REDCapEntity\EntityFactory();
}

Expand Down Expand Up @@ -62,42 +69,7 @@ public function redcap_module_system_enable($version) {
}

public function redcap_every_page_top($project_id) {
try {
preg_match('/redcap_v[\d\.].*\/index\.php/m', $_SERVER['SCRIPT_NAME'], $matches, PREG_OFFSET_CAPTURE);
if (strpos($_SERVER['SCRIPT_NAME'], 'ProjectSetup') !== false || !empty($matches)) {
$this->injectIntegrationUI();
}
} catch (\Exception $e) {
\REDCap::logEvent('Exception initiating REDCap Chatbot.', $e->getMessage());
}
}

public function injectJSMO($data = null, $init_method = null): void {
echo $this->initializeJavascriptModuleObject();
$cmds = [
"window.chatbot_jsmo_module = " . $this->getJavascriptModuleObjectName()
];

$initial_system_context = $this->appendSystemContext(array(), $this->system_context);
$data = !empty($initial_system_context) ? $initial_system_context : null;
if (!empty($data)) $cmds[] = "window.chatbot_jsmo_module.data = " . json_encode($data);
if (!empty($init_method)) $cmds[] = "window.chatbot_jsmo_module.afterRender(chatbot_jsmo_module." . $init_method . ")";
?>
<script src="<?= $this->getUrl("assets/jsmo.js", true) ?>"></script>
<script>
$(function () { <?php echo implode(";\n", $cmds) ?> })
</script>
<?php
}

public function injectIntegrationUI() {
$this->injectJSMO(null);
$build_files = $this->generateAssetFiles();
foreach ($build_files as $file) {
echo $file;
}
echo '<div id="chatbot_ui_container"></div>';
$this->emdebug("injectIntegrationUI() End");
}

public function generateAssetFiles(): array {
Expand Down
4 changes: 2 additions & 2 deletions assets/jsmo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

Object.assign(module, {
InitFunction: function () {
console.log("Calling this InitFunction() after load...", window.chatbot_jsmo_module.data);
console.log("Calling this InitFunction() after load...", window.mica_jsmo_module.data);
},

getInitialSystemContext: function() {
return window.chatbot_jsmo_module.data;
return window.mica_jsmo_module.data;
},

callAI: async (payload, callback, errorCallback) => {
Expand Down
12 changes: 6 additions & 6 deletions chatbot_ui/build/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"files": {
"main.css": "/static/css/main.afb79ba4.css",
"main.js": "/static/js/main.9208706f.js",
"main.css": "/static/css/main.da89d019.css",
"main.js": "/static/js/main.05320a56.js",
"static/js/488.5c64e536.chunk.js": "/static/js/488.5c64e536.chunk.js",
"service-worker.js": "/service-worker.js",
"index.html": "/index.html",
"main.afb79ba4.css.map": "/static/css/main.afb79ba4.css.map",
"main.9208706f.js.map": "/static/js/main.9208706f.js.map",
"main.da89d019.css.map": "/static/css/main.da89d019.css.map",
"main.05320a56.js.map": "/static/js/main.05320a56.js.map",
"488.5c64e536.chunk.js.map": "/static/js/488.5c64e536.chunk.js.map"
},
"entrypoints": [
"static/css/main.afb79ba4.css",
"static/js/main.9208706f.js"
"static/css/main.da89d019.css",
"static/js/main.05320a56.js"
]
}
2 changes: 1 addition & 1 deletion chatbot_ui/build/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><script src="https://cdn.jsdelivr.net/npm/react-bootstrap@next/dist/react-bootstrap.min.js" crossorigin></script><title>REDCap Chat GPT Powered Support Chatbot</title><script defer="defer" src="/static/js/main.9208706f.js"></script><link href="/static/css/main.afb79ba4.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><script src="https://cdn.jsdelivr.net/npm/react-bootstrap@next/dist/react-bootstrap.min.js" crossorigin></script><title>REDCap Chat GPT Powered Support Chatbot</title><script defer="defer" src="/static/js/main.05320a56.js"></script><link href="/static/css/main.da89d019.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"></body></html>
2 changes: 1 addition & 1 deletion chatbot_ui/build/service-worker.js

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions chatbot_ui/build/static/css/main.afb79ba4.css

This file was deleted.

1 change: 0 additions & 1 deletion chatbot_ui/build/static/css/main.afb79ba4.css.map

This file was deleted.

2 changes: 2 additions & 0 deletions chatbot_ui/build/static/css/main.da89d019.css

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions chatbot_ui/build/static/css/main.da89d019.css.map

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions chatbot_ui/build/static/js/main.05320a56.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions chatbot_ui/build/static/js/main.05320a56.js.map

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions chatbot_ui/build/static/js/main.9208706f.js

This file was deleted.

1 change: 0 additions & 1 deletion chatbot_ui/build/static/js/main.9208706f.js.map

This file was deleted.

13 changes: 13 additions & 0 deletions chatbot_ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions chatbot_ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"react-dom": "^18.3.1",
"react-draggable": "^4.4.6",
"react-markdown": "^9.0.1",
"react-resizable": "^3.0.5",
"react-router-dom": "^6.23.1",
"react-scripts": "^5.0.1",
"uuidv4": "^6.2.13",
Expand Down
102 changes: 19 additions & 83 deletions chatbot_ui/src/App.css
Original file line number Diff line number Diff line change
@@ -1,113 +1,49 @@
.container {
max-width:initial;
}

#chatbot_ui_container {
position: fixed; /* Cover the entire viewport */
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 9999;
pointer-events: none; /* Allow clicks to pass through */
}

.draggable-container {
position: absolute;
bottom: 30px; /* Initial position */
right: 30px; /* Initial position */
pointer-events: auto; /* Make this element interactive */
transition: box-shadow 0.2s ease-in-out; /* Smooth transition for shadow */
pointer-events: auto; /* Make the entire container interactive */
display: flex;
flex-direction: column;
background-color:#E6E7ED;
}

.draggable-container.splash {
width: 100px; /* Size of the splash icon */
height: 100px;
background: none;
border: none;
}

.draggable-container.home,
.draggable-container.history {
background: #2C2C2C; /* Assuming you want the same background */
border-radius: 10px;
border: 1px solid #999;
max-height: 80vh; /* Adjust this as necessary */
.full-screen-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* Adding shadow for depth */
}

.handle {
cursor: move; /* Indicate draggable area */
background: #2C2C2C; /* Assuming you want the same background */
}

.App {
width: auto; /* Make .App fill the container */
height: auto; /* Adjust height as necessary, or make it auto based on content */
.full-screen-container.splash {
background: none;
display: flex;
justify-content: center;
align-items: center;
}

.content {
flex: 1;
overflow: hidden; /* Prevent overflow from the content */
overflow: hidden;
display: flex;
flex-direction: column;
height: calc(98% - 60px); /* Account for the footer height */
}

.body {
flex: 1;
overflow-y: auto; /* Allow vertical scrolling */
overflow-y: auto;
}

.messages {
height: 100%; /* Full height for messages */
height: 100%;
overflow-y: scroll;
padding-bottom: 50px;
}

.react-resizable {
transition: width 0.3s ease, height 0.3s ease; /* Adjust the duration and easing as needed */
}

.react-resizable-box {
position: relative;
}

.react-resizable-handle {
width: 20px;
height: 20px;
position: absolute;
bottom: 0;
right: 0;
cursor: nwse-resize;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
background: rgba(200, 200, 200, 0.5); /* Lighter, more subtle gray */
border-radius: 10px 0 10px 0; /* Match the rounded corner */
}

.react-resizable-handle::before {
content: "\f0c9"; /* Font Awesome icon for 'bars' */
font-family: "Font Awesome 5 Free";
font-weight: 900;
font-size: 12px;
color: #777;
transform: translate(2px, 2px); /* Adjust position */
}


@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
47 changes: 11 additions & 36 deletions chatbot_ui/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,16 @@ import Footer from './components/footer/footer';
import Splash from './views/Splash';
import Home from './views/Home';
import History from './views/History';
import Draggable from 'react-draggable';
import ResizableContainer from './components/ResizableContainer';
import './App.css';
import './assets/styles/global.css';

function App() {
const [currentView, setCurrentView] = useState('splash');
const [defaultPosition, setDefaultPosition] = useState({ x: 0, y: 0 });
const [size, setSize] = useState({ width: 390, height: 300 }); // Default size for the UI

const changeView = (viewName) => {
if (viewName === 'splash') {
setDefaultPosition({ x: 0, y: 0 });
}
setCurrentView(viewName);
};

useEffect(() => {
if (currentView === 'splash') {
setDefaultPosition({ x: 0, y: 0 });
}
}, [currentView]);

let ViewComponent;
switch (currentView) {
case 'home':
Expand All @@ -42,29 +29,17 @@ function App() {
}

return (
<div id="chatbot_ui_container">
<Draggable handle=".handle" position={defaultPosition} onStop={(e, data) => setDefaultPosition({ x: data.x, y: data.y })}>
<div className={`draggable-container ${currentView}`}>
<ResizableContainer
width={size.width}
height={size.height}
minConstraints={[320, 480]}
maxConstraints={[600, 800]}
onResizeStop={(e, data) => setSize({ width: data.size.width, height: data.size.height })}
>
{currentView !== 'splash' && (
<>
<Header changeView={changeView} />
<div className="content">
{ViewComponent}
</div>
<Footer changeView={changeView} />
</>
)}
{currentView === 'splash' && ViewComponent}
</ResizableContainer>
</div>
</Draggable>
<div className={`full-screen-container ${currentView}`}>
{currentView !== 'splash' && (
<>
<Header changeView={changeView} />
<div className="content">
{ViewComponent}
</div>
<Footer changeView={changeView} />
</>
)}
{currentView === 'splash' && ViewComponent}
</div>
);
}
Expand Down
Binary file added chatbot_ui/src/assets/images/mica_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 11 additions & 4 deletions chatbot_ui/src/components/footer/footer.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
.footer {
background: #fff;
border-radius: 0 0 10px 10px;
border-radius: 0;
position: absolute;
bottom: 0;
width: 100%;
width: 100vw; /* Ensure it covers the entire viewport width */
display: flex;
align-items: center;
justify-content: space-between;
justify-content: space-between; /* Distribute space between input and buttons */
padding: 10px;
box-sizing: border-box; /* Include padding and border in the element's total width and height */
}

.footer button {
Expand All @@ -17,14 +18,20 @@

.footer .user_input {
border: none;
width: 82%;
flex: 1; /* Take up remaining space */
padding: 10px 0;
text-align: left; /* Ensure text is left-aligned */
}

.footer .user_input:focus {
outline: none;
}

.footer .send-container {
display: flex;
align-items: center;
}

.footer button .sendfill.rotate {
display: initial;
animation: rotate 2s linear infinite;
Expand Down
4 changes: 3 additions & 1 deletion chatbot_ui/src/components/footer/footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ function Footer({ changeView }) {
<Container className={`container footer`}>
<button onClick={chat_context.clearMessages} className={`clear_chat`}><EraserFill color="#ccc" size={20} /></button>
<input className={`user_input`} placeholder={inputPH} value={input} onChange={(e) => setInput(e.target.value)} onKeyDown={handleKeyDown} />
<button onClick={handleSubmit}><Send color="#ccc" size={20} className={`send ${loading ? "off" : ""}`} /><ArrowClockwise color="#ccc" size={20} className={`sendfill ${loading ? "rotate" : ""}`} /></button>
<div className="send-container">
<button onClick={handleSubmit}><Send color="#ccc" size={20} className={`send ${loading ? "off" : ""}`} /><ArrowClockwise color="#ccc" size={20} className={`sendfill ${loading ? "rotate" : ""}`} /></button>
</div>
</Container>
);
}
Expand Down
Loading

0 comments on commit 399766c

Please sign in to comment.