Skip to content

Commit

Permalink
[FIX]/UI small issues and improvements (#166)
Browse files Browse the repository at this point in the history
* fixed chat scrolling to last message

* fixed modal window removal on chat creation

* changed submind's icons in prompt table

* added participant icon to "selected winner" prompt field

* added participant icon to "selected winner" prompt field

* fixed selected winner box
  • Loading branch information
NeonKirill authored Feb 17, 2025
1 parent 19df5c0 commit 41e8c29
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 46 deletions.
3 changes: 1 addition & 2 deletions chat_client/static/css/chat.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@ body{
-moz-border-radius: 50px;
border-radius: 50px;
width: 100%;
background: #512DA8;
color: #fff;
text-align: center;
line-height: 50px;
user-select: none;
font-size: 14px;
font-size: 13px;
}


Expand Down
80 changes: 59 additions & 21 deletions chat_client/static/js/builder_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,26 @@ async function buildUserMessageHTML(userData, cid, messageID, messageText, timeC
* @return {string} - shortened nickname
*/
const shrinkNickname = (nick) => {
return `${nick[0]}${nick[nick.length - 1]}`;
const index = nick.indexOf('_');
return (index !== -1 && index < 8) ? nick.substring(0, index) : nick.substring(0, 8);
}

/**
* Generates dark color based on username
* @param username
* @returns {string} - generated color in hsl format
*/

function generateDarkColorFromUsername(username) {
if (!username) {
return 'hsl(270, 70%, 30%)';
}
let hash = 0;
for (let i = 0; i < username.length; i++) {
hash = username.charCodeAt(i) + ((hash << 5) - hash);
}
return `hsl(${hash % 360}, 70%, 30%)`;
}

/**
* Builds Prompt Skin HTML for submind responses
Expand All @@ -146,11 +163,8 @@ const shrinkNickname = (nick) => {
* @return {Promise<string|void>} - Submind Data HTML populated with provided data
*/
async function buildSubmindHTML(promptID, submindID, submindUserData, submindResponse, submindOpinion, submindVote) {
const userNickname = shrinkNickname(submindUserData['nickname']);
let tooltip = submindUserData['nickname'];
if (submindUserData['is_bot']){
tooltip = `bot ${tooltip}`;
}
const userNickname = submindUserData['nickname'];
const participantIcon = await buildPromptParticipantIcon(userNickname);
const phaseDataObjectMapping = {
'response': submindResponse,
'opinion': submindOpinion,
Expand All @@ -161,10 +175,9 @@ async function buildSubmindHTML(promptID, submindID, submindUserData, submindRes
'user_id': submindID,
'user_first_name': submindUserData['first_name'],
'user_last_name': submindUserData['last_name'],
'user_nickname': submindUserData['nickname'],
'user_nickname_shrunk': userNickname,
'user_nickname': userNickname,
'participant_icon': participantIcon,
// 'user_avatar': `${configData["CHAT_SERVER_URL_BASE"]}/files/avatar/${submindID}`,
'tooltip': tooltip
}
const submindPromptData = {}
for (const [k,v] of Object.entries(phaseDataObjectMapping)){
Expand All @@ -179,18 +192,37 @@ async function buildSubmindHTML(promptID, submindID, submindUserData, submindRes


/**
* Gets winner text based on the provided winner data
* @param winner: provided winner
* @return {string} generated winner text
* Gets winner field HTML based on provided winner
* @return {string} built winner field HTML
* @param nickname of the winner
*/
const getPromptWinnerText = (winner) => {
let res;
if (winner){
res = `Selected winner "${winner}"`;
}else{
res = 'Consensus not reached';
async function buildPromptWinnerHTML(nickname) {
return `
<div class="d-flex flex-column align-items-center justify-content-center">
<span class="mt-2">Selected winner</span>
${await buildPromptParticipantIcon(nickname)}
</div>
`
}

/**
* Builds prompt participant icon HTML
* @param nickname of the participant
* @returns prompt participant icon HTML
*/
async function buildPromptParticipantIcon(nickname) {
const backgroundColor = generateDarkColorFromUsername(nickname);
const userNicknameShrunk = shrinkNickname(nickname);
let tooltip = nickname;
/* if (submindUserData['is_bot']) assuming only bots participate for now*/ tooltip = `bot ${tooltip}`;
const template_data = {
'user_nickname': nickname,
'user_nickname_shrunk': userNicknameShrunk,
'background_color': backgroundColor,
// 'user_avatar': submindUserData['user_avatar'], not used for now
'tooltip': tooltip
}
return res;
return await buildHTMLFromTemplate("prompt_participant_icon", template_data)
}


Expand All @@ -201,14 +233,13 @@ const getPromptWinnerText = (winner) => {
*/
async function buildPromptHTML(prompt) {
let submindsHTML = "";
let winnerFound = false;
const promptData = prompt['data'];
if (prompt['is_completed'] === '0'){
promptData['winner'] = `Prompt in progress
<div class="spinner-border spinner-border-sm text-dark" role="status">
<span class="sr-only">Loading...</span>
</div>`
}else {
promptData['winner'] = getPromptWinnerText(promptData['winner']);
}
const emptyAnswer = `<h4>-</h4>`;
for (const submindID of Array.from(setDefault(promptData, 'participating_subminds', []))) {
Expand Down Expand Up @@ -245,12 +276,19 @@ async function buildPromptHTML(prompt) {
data[key] = {'message_text': emptyAnswer};
}
});
if (promptData['winner'] === submindUserData['nickname']) {
winnerFound = true;
promptData['winner'] = await buildPromptWinnerHTML(submindUserData['nickname']);
}
submindsHTML += await buildSubmindHTML(prompt['_id'], submindID, submindUserData,
data.proposed_responses, data.submind_opinions, data.votes);
}catch (e) {
console.log(`Malformed data for ${submindID} (prompt_id=${prompt['_id']}) ex=${e}`);
}
}
if (!winnerFound && prompt['is_completed'] === '1'){
promptData['winner'] = 'Consensus not reached.'
}
return await buildHTMLFromTemplate("prompt_table",
{'prompt_text': promptData['prompt_text'],
'selected_winner': promptData['winner'],
Expand Down
28 changes: 15 additions & 13 deletions chat_client/static/js/chat_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ async function buildConversation(conversationData, skin, remember=true,conversat
chatCloseButton.hidden = true;
}
document.getElementById('klatchatHeader').scrollIntoView(true);
scrollChatToLastMessage(cid);
return cid;
}

Expand Down Expand Up @@ -743,19 +744,20 @@ async function createNewConversation(conversationName, isPrivate=false,boundServ
formData.append('bound_service', boundServiceID?boundServiceID: '');
formData.append('is_live_conversation', createLiveConversation? '1': '0')

await fetchServer(`chat_api/new`, REQUEST_METHODS.POST, formData).then(async response => {
const responseJson = await response.json();
let responseOk = false;
if (response.ok) {
await buildConversation(responseJson, CONVERSATION_SKINS.PROMPTS);
responseOk = true;
} else {
displayAlert('newConversationModalBody',
`${responseJson['msg']}`,
'danger');
}
return responseOk;
});
return await fetchServer(`chat_api/new`, REQUEST_METHODS.POST, formData)
.then(async response => {
const responseJson = await response.json();
let responseOk = false;
if (response.ok) {
await buildConversation(responseJson, CONVERSATION_SKINS.PROMPTS);
responseOk = true;
} else {
displayAlert('newConversationModalBody',
`${responseJson['msg']}`,
'danger');
}
return responseOk;
});
}

document.addEventListener('DOMContentLoaded', (_)=>{
Expand Down
5 changes: 4 additions & 1 deletion chat_client/static/js/file_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ function download(content, filename, contentType='application/octet-stream')
* @param image: target image Node
*/
function handleImgError(image) {
image.parentElement.insertAdjacentHTML('afterbegin',`<p>${image.getAttribute('alt')}</p>`);
const backgroundColor = image.getAttribute("data-bgcolor") || "#512DA8";
image.parentElement.insertAdjacentHTML('afterbegin',
`<p style="background: ${backgroundColor}">${image.getAttribute('alt')}</p>`
);
image.parentElement.removeChild(image);
}
16 changes: 16 additions & 0 deletions chat_client/static/js/message_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ const getMessageListContainer = (cid) => {
}
}


const getChatCardBody = (cid) => {
const cidElem = document.getElementById(cid);
if(cidElem){
return cidElem.getElementsByClassName('card-body')[0];
}
}

const scrollChatToLastMessage = (cid) => {
const chatCardBody = getChatCardBody(cid);
if(chatCardBody){
chatCardBody.scrollTo({ top: chatCardBody.scrollHeight, behavior: "smooth" })
}
}

/**
* Gets message node from the message container
* @param messageContainer: DOM Message Container element to consider
Expand Down Expand Up @@ -65,6 +80,7 @@ async function addNewMessage(cid, userID=null, messageID=null, messageText, time
messageList.removeChild(blankChat[0]);
}
messageList.insertAdjacentHTML('beforeend', messageHTML);
scrollChatToLastMessage(cid);
resolveMessageAttachments(cid, messageID, attachments);
resolveUserReply(messageID, repliedMessageID);
addProfileDisplay(userID, cid, messageID, 'plain');
Expand Down
3 changes: 2 additions & 1 deletion chat_client/static/js/sio.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ function initSIO(){
console.info(`setting prompt_id=${promptID} as completed`);
if (promptElem){
const promptWinner = document.getElementById(`${promptID}_winner`);
promptWinner.innerHTML = getPromptWinnerText(data['winner']);
console.log("data:", data)
promptWinner.innerHTML = await buildPromptWinnerHTML(data['winner']);
}else {
console.warn(`Failed to get HTML element from prompt_id=${promptID}`);
}
Expand Down
8 changes: 1 addition & 7 deletions chat_client/templates/components/prompt_participant.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
<tr id="{prompt_id}_{user_id}_prompt_row" data-submind-id="{user_id}">
<td class="d-flex justify-content-center">
<div class="chat-img" data-toggle="tooltip" title="{tooltip}" data-target="{user_nickname}">
<img alt="{user_nickname_shrunk}" onerror="handleImgError(this);"
src="{user_avatar}"
class="img-thumbnail prompt-submind-img" loading="lazy" style="
max-height: 50px!important;
max-width: 50px!important;">
</div>
{participant_icon}
</td>
<td>
<div style="overflow-y:auto; width:100%; max-height: 150px!important;" id="{prompt_id}_{user_id}_resp"
Expand Down
8 changes: 8 additions & 0 deletions chat_client/templates/components/prompt_participant_icon.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="chat-img" data-toggle="tooltip" title="{tooltip}" data-target="{user_nickname}">
<img alt="{user_nickname_shrunk}" onerror="handleImgError(this);"
src="{user_avatar}"
class="img-thumbnail prompt-submind-img" loading="lazy" style="
max-height: 50px!important;
max-width: 50px!important;"
data-bgcolor="{background_color}">
</div>
2 changes: 1 addition & 1 deletion chat_client/templates/components/prompt_table.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
{prompt_participants_data}
</tbody>
<tr>
<th colspan="4" id="{prompt_id}_winner">{selected_winner}</th>
<th colspan="4" id="{prompt_id}_winner" style="font-weight: normal">{selected_winner}</th>
</tr>
</table>
</li>

0 comments on commit 41e8c29

Please sign in to comment.