Skip to content

Commit

Permalink
Center messages, header, add icons config, round text input
Browse files Browse the repository at this point in the history
  • Loading branch information
Wutras committed Oct 10, 2023
1 parent 19c303e commit 5ad5c03
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 50 deletions.
83 changes: 53 additions & 30 deletions src/components/App/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,59 @@ class App extends Component {
constructor(props) {
super(props);

this.state = {
messages: [],
components:
this.texts = textsHelper.getTexts();
const iconUrl = localStorage.getItem("iconUrl") ?? "";
const backendType =
defaultBackendType in supportedServiceNames
? defaultBackendType
: supportedServiceNames[0];
const now = new Date(Date.now());
const backendUrl = localStorage.getItem("backendUrl") ?? "";
const components =
JSON.parse(localStorage.getItem("components")) ??
defaultChatbotComponents,
defaultChatbotComponents;
const isConfigured =
backendType === "rasa"
? !!backendUrl
: !!backendUrl && !!components?.length > 0;
const initialMessage = isConfigured
? this.texts["default-responses"]["initial-message"][
"is-configured"
].replace("{{url}}", backendUrl)
: this.texts["default-responses"]["initial-message"]["is-not-configured"];

this.state = {
messages: [
{
text: initialMessage,
followUpNeeded: false,
loadedSuccessfully: false, // This is to prevent the source of data bit from showing up
visualization: {},
time: now.getHours() + ":" + ("0" + now.getMinutes()).slice(-2),
isReply: true,
icon: iconUrl || robot_icon,
},
],
components,
/* // TODO: Add back in once we move on from the MVP
.map((componentName) => ({
name: componentName,
activated: false,
}))*/
backendUrl: localStorage.getItem("backendUrl") ?? "",
backendUrl,
isSending: false,
backendType:
defaultBackendType in supportedServiceNames
? defaultBackendType
: supportedServiceNames[0],
backendType,
currentTheme: "default",
iconUrl,
};

this.texts = textsHelper.getTexts();

this.sendMessage = this.sendMessage.bind(this);
this.setBackendUrl = this.setBackendUrl.bind(this);
this.setComponents = this.setComponents.bind(this);
this.setBackendType = this.setBackendType.bind(this);
this.setTheme = this.setTheme.bind(this);
this.setIconUrl = this.setIconUrl.bind(this);
// TODO: Add back in once we move on from the MVP
// this.toggleComponent = this.toggleComponent.bind(this);
}
Expand Down Expand Up @@ -120,7 +147,7 @@ class App extends Component {
visualization: reply.visualization,
time: now.getHours() + ":" + ("0" + now.getMinutes()).slice(-2),
isReply: true,
icon: robot_icon,
icon: this.state.iconUrl || robot_icon,
};

if (typeof reply.answer === "object") {
Expand Down Expand Up @@ -164,6 +191,19 @@ class App extends Component {
});
}

setIconUrl(iconUrl) {
const messagesCopy = this.state.messages.map((message) => {
if (message.isReply) message.icon = iconUrl || robot_icon;
return message;
});

localStorage.setItem("iconUrl", iconUrl);
this.setState({
iconUrl,
messages: messagesCopy,
});
}

setComponents(components) {
// is array and only contains strings, if it has elements
// TODO: Edit string check back once we move on from the MVP
Expand Down Expand Up @@ -237,16 +277,6 @@ class App extends Component {
}

render() {
const now = new Date(Date.now());
const isConfigured =
this.state.backendType === "rasa"
? !!this.state.backendUrl
: !!this.state.backendUrl && !!this.state.components?.length > 0;
const initialMessage = isConfigured
? this.texts["default-responses"]["initial-message"][
"is-configured"
].replace("{{url}}", this.state.backendUrl)
: this.texts["default-responses"]["initial-message"]["is-not-configured"];
return (
<div className={`theme ${this.state.currentTheme}`}>
<PageHeader
Expand All @@ -256,22 +286,15 @@ class App extends Component {
setComponents={this.setComponents}
setBackendType={this.setBackendType}
setTheme={this.setTheme}
setIconUrl={this.setIconUrl}
components={this.state.components}
backendUrl={this.state.backendUrl}
backendType={this.state.backendType}
currentTheme={this.state.currentTheme}
iconUrl={this.state.iconUrl}
/>
<MessagePanel
messages={[
{
text: initialMessage,
followUpNeeded: false,
loadedSuccessfully: false, // This is to prevent the source of data bit from showing up
visualization: {},
time: now.getHours() + ":" + ("0" + now.getMinutes()).slice(-2),
isReply: true,
icon: robot_icon,
},
...this.state.messages,
]}
/>
Expand Down
1 change: 1 addition & 0 deletions src/components/MessageInput/MessageInput.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
width: 33%;
font-size: 1em;
height: 25%;
border-radius: 2px;
}

#inputTextBox::placeholder {
Expand Down
5 changes: 5 additions & 0 deletions src/components/MessagePanel/MessagePanel.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
margin-top: 2vh;
}

.itzbund.theme #messagePanel {
max-width: 50%;
margin: 0 auto;
}

/*
#messagePanel::before {
content: 'Covid-19 Chatbot';
Expand Down
8 changes: 6 additions & 2 deletions src/components/PageHeader/PageHeader.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@
display: flex;
flex-wrap: nowrap;
height: 75px;
width: 100%;
z-index: 1;
}

.itzbund.theme #header {
margin: 0 auto;
max-width: 60%;
}

.default.theme #header {
background-color: var(--dark-teal);
}

.itzbund.theme #header {
.itzbund.theme #headerContainer {
background-color: var(--white);
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
box-shadow: 0px 10px 17px 0px rgba(0, 0, 0, 0.1);
Expand Down
4 changes: 4 additions & 0 deletions src/components/PageHeader/PageHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default class PageHeader extends Component {
render() {
return (
<>
<div id="headerContainer">
<div tabIndex="-1" id="header">
<ClickableIcon
onClick={() => toggleContainer("imprint")}
Expand Down Expand Up @@ -137,12 +138,15 @@ export default class PageHeader extends Component {
backendUrl={this.props.backendUrl}
backendType={this.props.backendType}
currentTheme={this.props.currentTheme}
iconUrl={this.props.iconUrl}
setComponents={this.props.setComponents}
setBackendUrl={this.props.setBackendUrl}
setBackendType={this.props.setBackendType}
setTheme={this.props.setTheme}
setIconUrl={this.props.setIconUrl}
// toggleComponent={this.props.toggleComponent} // TODO: Add back in once we move on from the MVP
/>
</div>
</>
);
}
Expand Down
13 changes: 10 additions & 3 deletions src/components/SettingsContainer/SettingsContainer.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@
width: 100%;
}

#backendUrlInput {
#chatbotSettings > * {
margin-top: 1rem;
}

input[type="text"] {
min-width: 20rem;
max-width: 100%;
margin-right: 1rem;
}

input[type="text"] ~ button, input[type="text"] ~ input[type="button"] {
margin-left: 1rem;
}

#componentInput {
Expand All @@ -30,4 +37,4 @@

.errorMessage.hidden {
display: none !important;
}
}
55 changes: 42 additions & 13 deletions src/components/SettingsContainer/SettingsContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Component } from "react";
import "./SettingsContainer.css";
import { ContentContainer } from "..";
import { textsHelper } from "../../helpers";
import { defaultChatbotBackendUrl } from "../../helpers/constants";
import { defaultChatbotBackendUrl, defaultChatbotIconUrl } from "../../helpers/constants";
import { supportedServiceNames, supportedThemes } from "../../services";
import { SpringBootHealthCheck } from "@qanary/spring-boot-health-check";

Expand Down Expand Up @@ -54,33 +54,61 @@ export default class SettingsContainer extends Component {
render() {
return (
<ContentContainer id="chatbotSettings">
<h2>{this.texts.settings.ui.headline}</h2>
<div>
{this.texts.settings.explanation}
{this.texts.settings["select-service-type"]}
</div>
<div>
Select backend type:{" "}
Select design theme:{" "}
<select
onChange={(changeEvent) => {
this.props.setBackendType(changeEvent.target.value);
this.props.setTheme(changeEvent.target.value);
}}
>
{supportedServiceNames.map((name) => (
<option key={name} selected={name === this.props.backendType}>
{supportedThemes.map((name) => (
<option key={name} selected={name === this.props.currentTheme}>
{name}
</option>
))}
</select>
</div>
<div id="iconUrlSettingsContainer">
<span>{this.texts.settings.ui.iconUrlLabel}</span>
<input
type="text"
id="iconUrlInput"
defaultValue={this.props.iconUrl || defaultChatbotIconUrl}
/>
<input
type="button"
value={this.texts.settings["confirm-url"]}
onClick={() => {
const urlInput = document.getElementById("iconUrlInput");
const errElement = document.querySelector(
"#iconUrlSettingsContainer > .errorMessage"
);
this.props.setIconUrl(urlInput.value).catch((errorMessage) => {
console.error(errorMessage);
errElement.classList.remove("hidden");
});
errElement.classList.add("hidden");
}}
/>
<div className="errorMessage hidden">
{this.texts.settings["url-malformed"]}
</div>
</div>
<h2>{this.texts.settings.functional.headline}</h2>
<div>
Select design theme:{" "}
{this.texts.settings.explanation}
{this.texts.settings["select-service-type"]}
</div>
<div>
Select backend type:{" "}
<select
onChange={(changeEvent) => {
this.props.setTheme(changeEvent.target.value);
this.props.setBackendType(changeEvent.target.value);
}}
>
{supportedThemes.map((name) => (
<option key={name} selected={name === this.props.currentTheme}>
{supportedServiceNames.map((name) => (
<option key={name} selected={name === this.props.backendType}>
{name}
</option>
))}
Expand All @@ -91,6 +119,7 @@ export default class SettingsContainer extends Component {
type={this.props.backendType === "rasa" ? "basic" : "actuator"}
/>
<div id="urlSettingsContainer">
<span>{this.texts.settings.functional.backendUrlLabel}</span>
<input
type="text"
id="backendUrlInput"
Expand Down
3 changes: 3 additions & 0 deletions src/helpers/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export const chatbotFrontendUrl =
export const defaultChatbotBackendUrl =
window._env_?.DEFAULT_CHATBOT_BACKEND_URL ?? "http://localhost:8000";

export const defaultChatbotIconUrl =
window._env_?.DEFAULT_CHATBOT_ICON_URL ?? "";

export const defaultLanguage = window._env_?.DEFAULT_LANGUAGE ?? "de";

export const defaultRasaBackendUrl =
Expand Down
10 changes: 9 additions & 1 deletion src/texts/de/texts.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,15 @@
"no-components": "Es konnten keine Komponenten gefunden werden. Es muss ein valides Backend angegeben und CORS entsprechend konfiguriert werden.",
"components-explanation": "Geben Sie hier die Komponenten in der richtigen Reihenfolge an. Trennen Sie die Komponenten durch Kommata.",
"admin-panel-url": "Liste der Komponenten",
"select-service-type": "Wählen Sie die Art des Services aus, den Sie nutzen möchten: "
"select-service-type": "Wählen Sie die Art des Services aus, den Sie nutzen möchten: ",
"ui": {
"headline": "Kosmetische Einstellungen",
"iconUrlLabel": "URL zum Chatbot-Icon (Leer lassen für Standard): "
},
"functional": {
"headline": "Technische Einstellungen",
"backendUrlLabel": "Backend-URL: "
}
},
"credits": "Diese Anwendung wurde am <a href=\"https://www.hs-anhalt.de/hochschule-anhalt/fachbereich-5/ueberblick.html\" target=\"_blank\" rel=\"noreferrer\">Fachbereich Informatik und Sprachen</a> der <a href=\"https://hs-anhalt.de/\" target=\"_blank\" rel=\"noreferrer\">Hochschule Anhalt</a> unter der Leitung von <a href=\"https://fim.htwk-leipzig.de/fakultaet/personen/professorinnen-und-professoren/andreas-both/\" target=\"_blank\" rel=\"noreferrer\">Prof. Dr. Andreas Both</a> und mit der Unterstützung von Paul Heinze durch Jonas Wunsch entwickelt. Für diese Anwendung gilt die Apache 2.0 Lizenz."
}
10 changes: 9 additions & 1 deletion src/texts/en/texts.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,15 @@
"no-components": "No components were found. A valid backend has to be provided and CORS has to be configured accordingly.",
"components-explanation": "Set the components in the right order here. Separate them using commas.",
"admin-panel-url": "List of components",
"select-service-type": "Select the type of service you want to use: "
"select-service-type": "Select the type of service you want to use: ",
"ui": {
"headline": "Cosmetic Settings",
"iconUrlLabel": "Chatbot icon URL (empty for default): "
},
"functional": {
"headline": "Functional Settings",
"backendUrlLabel": "Backend URL: "
}
},
"credits": "This application has been developed by Jonas Wunsch at the <a href=\"https://www.hs-anhalt.de/hochschule-anhalt/fachbereich-5/ueberblick.html\" target=\"_blank\" rel=\"noreferrer\">Department of Computer Science and Languages</a> of the <a href=\"https://hs-anhalt.de/\" target=\"_blank\" rel=\"noreferrer\">Anhalt University of Applied Sciences</a> under the direction of <a href=\"https://fim.htwk-leipzig.de/fakultaet/personen/professorinnen-und-professoren/andreas-both/\" target=\"_blank\" rel=\"noreferrer\">Prof. Dr. Andreas Both</a> and with help from Paul Heinze. The Apache 2.0 license applies to this project."
}

0 comments on commit 5ad5c03

Please sign in to comment.