Feature updates

-- added option to save an update from intern
-- added UI to see assigned tasks in intern profile
This commit is contained in:
sairaj mote 2022-11-25 01:07:40 +05:30
parent 4ddeb8ce73
commit c196d31d1b
11 changed files with 871 additions and 821 deletions

View File

@ -1152,6 +1152,7 @@ ul {
user-select: none; user-select: none;
padding: 0.8rem 1rem; padding: 0.8rem 1rem;
gap: 0.8rem; gap: 0.8rem;
color: inherit;
} }
.intern-card input { .intern-card input {
height: 1.3em; height: 1.3em;
@ -1284,7 +1285,7 @@ ul {
flex: 1; flex: 1;
} }
#intern_info__initials { #intern_profile__initials {
position: relative; position: relative;
height: 4rem; height: 4rem;
width: 4rem; width: 4rem;
@ -1292,12 +1293,12 @@ ul {
color: var(--color); color: var(--color);
} }
#intern_info__name { #intern_profile__name {
font-size: 1.5rem; font-size: 1.5rem;
padding: 0.4rem 0.5rem; padding: 0.4rem 0.5rem;
border-radius: 0.5rem; border-radius: 0.5rem;
} }
#intern_info__name[contenteditable=true] { #intern_profile__name[contenteditable=true] {
background-color: rgba(var(--text-color), 0.1); background-color: rgba(var(--text-color), 0.1);
} }
@ -1379,33 +1380,39 @@ ul {
color: var(--nice-blue); color: var(--nice-blue);
} }
#intern_info__wrapper { #intern_profile {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 1rem; gap: 1.5rem;
} }
#intern_info__wrapper > * { #intern_profile__left {
width: min(26rem, 100%);
border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1);
padding: 1rem;
}
#intern_profile__right {
flex: 1; flex: 1;
} }
.intern_info__task { .intern_profile__task {
display: grid; display: grid;
align-items: center; align-items: center;
width: 100%; width: 100%;
gap: 0.3rem; gap: 0.3rem;
margin-top: 1rem; margin-top: 1rem;
padding: 0.5rem; padding: 1rem;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: rgba(var(--text-color), 0.06); background-color: rgba(var(--foreground-color), 1);
grid-template-columns: minmax(0, 1fr) auto; grid-template-columns: minmax(0, 1fr) auto;
} }
.intern_info__task h4 { .intern_profile__task h4 {
grid-column: 1/-1; grid-column: 1/-1;
} }
.intern_info__task p { .intern_profile__task p {
font-weight: 500; font-weight: 500;
} }
.intern_info__task time { .intern_profile__task time {
font-size: 0.9rem; font-size: 0.9rem;
color: rgba(var(--text-color), 0.8); color: rgba(var(--text-color), 0.8);
} }
@ -1853,16 +1860,6 @@ ul {
margin-top: 0.2rem; margin-top: 0.2rem;
} }
.send-update-button,
.init-update-replay {
color: var(--accent-color);
background-color: rgba(var(--text-color), 0.04);
}
.send-update-button .icon,
.init-update-replay .icon {
fill: var(--accent-color);
}
.temp-task { .temp-task {
padding: 1rem; padding: 1rem;
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--foreground-color), 1);
@ -2223,6 +2220,13 @@ input[type=date]:focus {
width: min(48rem, 100%); width: min(48rem, 100%);
margin: 0 auto; margin: 0 auto;
} }
#intern_profile__left {
position: -webkit-sticky;
position: sticky;
top: 1rem;
align-self: flex-start;
padding: 1.5rem;
}
} }
@media only screen and (min-width: 1280px) { @media only screen and (min-width: 1280px) {
#main_page { #main_page {

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -1129,6 +1129,7 @@ ul {
user-select: none; user-select: none;
padding: 0.8rem 1rem; padding: 0.8rem 1rem;
gap: 0.8rem; gap: 0.8rem;
color: inherit;
input { input {
height: 1.3em; height: 1.3em;
width: 1.3em; width: 1.3em;
@ -1256,14 +1257,14 @@ ul {
.container-header h4 { .container-header h4 {
flex: 1; flex: 1;
} }
#intern_info__initials { #intern_profile__initials {
position: relative; position: relative;
height: 4rem; height: 4rem;
width: 4rem; width: 4rem;
font-size: 1.3rem; font-size: 1.3rem;
color: var(--color); color: var(--color);
} }
#intern_info__name { #intern_profile__name {
font-size: 1.5rem; font-size: 1.5rem;
padding: 0.4rem 0.5rem; padding: 0.4rem 0.5rem;
border-radius: 0.5rem; border-radius: 0.5rem;
@ -1348,23 +1349,29 @@ ul {
color: var(--nice-blue); color: var(--nice-blue);
} }
} }
#intern_info__wrapper { #intern_profile {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 1rem; gap: 1.5rem;
& > * { &__left {
width: min(26rem, 100%);
border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1);
padding: 1rem;
}
&__right {
flex: 1; flex: 1;
} }
} }
.intern_info__task { .intern_profile__task {
display: grid; display: grid;
align-items: center; align-items: center;
width: 100%; width: 100%;
gap: 0.3rem; gap: 0.3rem;
margin-top: 1rem; margin-top: 1rem;
padding: 0.5rem; padding: 1rem;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: rgba(var(--text-color), 0.06); background-color: rgba(var(--foreground-color), 1);
grid-template-columns: minmax(0, 1fr) auto; grid-template-columns: minmax(0, 1fr) auto;
h4 { h4 {
grid-column: 1/-1; grid-column: 1/-1;
@ -1794,15 +1801,6 @@ ul {
} }
} }
.send-update-button,
.init-update-replay {
color: var(--accent-color);
background-color: rgba(var(--text-color), 0.04);
.icon {
fill: var(--accent-color);
}
}
.temp-task { .temp-task {
padding: 1rem; padding: 1rem;
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--foreground-color), 1);
@ -2174,6 +2172,14 @@ input[type="date"] {
margin: 0 auto; margin: 0 auto;
} }
} }
#intern_profile {
&__left {
position: sticky;
top: 1rem;
align-self: flex-start;
padding: 1.5rem;
}
}
} }
@media only screen and (min-width: 1280px) { @media only screen and (min-width: 1280px) {

View File

@ -517,6 +517,7 @@
<ul id="task_requests_list" class="grid gap-0-5 observe-empty-state margin-top-1"></ul> <ul id="task_requests_list" class="grid gap-0-5 observe-empty-state margin-top-1"></ul>
<h4 class="empty-state">No task requests</h4> <h4 class="empty-state">No task requests</h4>
</section> </section>
<section id="intern_profile" class="inner-page hidden flex align-start"></section>
<section id="all_interns_page" class="inner-page hidden flex flex-direction-column align-start"> <section id="all_interns_page" class="inner-page hidden flex flex-direction-column align-start">
<div id="all_interns_page__header" class="grid gap-0-5"> <div id="all_interns_page__header" class="grid gap-0-5">
<h2>Interns</h2> <h2>Interns</h2>
@ -563,19 +564,6 @@
</main> </main>
</main> </main>
<sm-popup id="intern_info_popup">
<header slot="header" class="popup__header">
<button class="popup__header__close" onclick="closePopup()">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z" />
</svg>
</button>
</header>
<section id="intern_info__wrapper" class="grid gap-1"></section>
</sm-popup>
<sm-popup id="intern_list_popup"> <sm-popup id="intern_list_popup">
<header slot="header" class="popup__header"> <header slot="header" class="popup__header">
<button class="popup__header__close" onclick="closePopup()"> <button class="popup__header__close" onclick="closePopup()">
@ -1224,6 +1212,9 @@
case 'all_interns_page': case 'all_interns_page':
renderAllInterns() renderAllInterns()
break; break;
case 'intern_profile':
render.internProfile(params?.id)
break;
case 'project_explorer': case 'project_explorer':
let breadcrumbs = [] let breadcrumbs = []
if (subPageId1) { if (subPageId1) {
@ -1917,7 +1908,8 @@
</div> </div>
`; `;
}, },
internCard(internFloId, { selectable = false } = {}) { internCard(internFloId, options = {}) {
const { selectable } = options
const internName = RIBC.getInternList()[internFloId] const internName = RIBC.getInternList()[internFloId]
const internPoints = RIBC.getInternRating(internFloId) const internPoints = RIBC.getInternRating(internFloId)
const splitName = internName.split(' ') const splitName = internName.split(' ')
@ -1925,9 +1917,10 @@
if (splitName.length > 1) { if (splitName.length > 1) {
initials += splitName[splitName.length - 1][0] initials += splitName[splitName.length - 1][0]
} }
if (selectable) {
return html` return html`
<label class="intern-card align-center interact" .dataset=${{ internFloId }} onclick=${selectable ? false : showInternInfo} title="Intern Information"> <label class="intern-card align-center interact" .dataset=${{ internFloId }} title="Intern Information">
${selectable ? html`<input type="checkbox" class="intern-card__checkbox" value=${internFloId}>` : ''} <input type="checkbox" class="intern-card__checkbox" value=${internFloId}>
<div class="intern-card__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div> <div class="intern-card__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div>
<div class="intern-card__name">${internName}</div> <div class="intern-card__name">${internName}</div>
<div class="intern-card__score-wrapper flex align-center"> <div class="intern-card__score-wrapper flex align-center">
@ -1935,6 +1928,17 @@
<svg class="icon icon--star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z" /> <path d="M12 18.26l-7.053 3.948 1.575-7.928L.587 8.792l8.027-.952L12 .5l3.386 7.34 8.027.952-5.935 5.488 1.575 7.928z" /> </svg> <svg class="icon icon--star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z" /> <path d="M12 18.26l-7.053 3.948 1.575-7.928L.587 8.792l8.027-.952L12 .5l3.386 7.34 8.027.952-5.935 5.488 1.575 7.928z" /> </svg>
</div> </div>
</label>`; </label>`;
} else {
return html`
<a class="intern-card align-center interact" href=${`#/intern_profile?id=${internFloId}`} title="Intern Information">
<div class="intern-card__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div>
<div class="intern-card__name">${internName}</div>
<div class="intern-card__score-wrapper flex align-center">
<b class="intern-card__score">${internPoints}</b>
<svg class="icon icon--star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z" /> <path d="M12 18.26l-7.053 3.948 1.575-7.928L.587 8.792l8.027-.952L12 .5l3.386 7.34 8.027.952-5.935 5.488 1.575 7.928z" /> </svg>
</div>
</a>`;
}
}, },
adminInterns() { adminInterns() {
const addInternButton = html`<button class="button button--colored" onclick="openPopup('add_intern_popup')"> const addInternButton = html`<button class="button button--colored" onclick="openPopup('add_intern_popup')">
@ -1944,12 +1948,16 @@
renderElem(getRef('admin_page__intern_list'), html`${[addInternButton, filterInterns('')]}`) renderElem(getRef('admin_page__intern_list'), html`${[addInternButton, filterInterns('')]}`)
}, },
internUpdateCard(update) { internUpdateCard(update) {
const { floID, time, note, update: { projectCode, branch, task, description, link } } = update const { floID, time, note, update: { projectCode, branch, task, description, link }, tag } = update
let topic = `${RIBC.getProjectDetails(projectCode).projectName} / ${RIBC.getTaskDetails(projectCode, branch, task).title}` let topic = `${RIBC.getProjectDetails(projectCode).projectName} / ${RIBC.getTaskDetails(projectCode, branch, task).title}`
const internName = RIBC.getInternList()[floID] const internName = RIBC.getInternList()[floID]
let replyButton let replyButton
if (userType === "admin" && !note) { let saveButton
replyButton = html`<button class="button button--small init-update-replay margin-left-auto">Reply</button>` if (userType === "admin") {
if (!note)
replyButton = html`<button class="button button--small button--colored init-update-replay">Reply</button>`
if (!tag)
saveButton = html`<button class="button button--small button--colored save-update margin-left-auto">Save</button>`
} }
let providedLink let providedLink
if (link) { if (link) {
@ -1971,8 +1979,8 @@
<h4 class="update__topic">${topic}</h4> <h4 class="update__topic">${topic}</h4>
<p class="update__message ws-pre-line wrap-around">${description}</p> <p class="update__message ws-pre-line wrap-around">${description}</p>
${providedLink} ${providedLink}
${replyButton}
${adminReply} ${adminReply}
${saveButton || replyButton ? html`<div class="flex align-center gap-0-3">${saveButton}${replyButton}</div>` : ''}
</li>`; </li>`;
}, },
branchButton(obj = {}) { branchButton(obj = {}) {
@ -1997,14 +2005,33 @@
</span> </span>
` `
}, },
internSpecificTasks(internId) { assignedInternTasks(internId) {
const { assignedTasks, completedTasks } = RIBC.getInternRecord(internId)
if (getObjLength(assignedTasks) === 0) return false
const assignedTasksList = [];
for (const task in assignedTasks) {
if (completedTasks[task]) continue;
const { points, assignedOn } = assignedTasks[task];
const { title } = RIBC.getAllTasks()[task];
assignedTasksList.push(html`
<div class="intern_profile__task">
<h4>${title}</h4>
<time>${getFormattedTime(assignedOn, 'date-only')}</time>
<p class="flex align-center gap-0-3">
${points}
<svg class="icon icon--star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z"></path> <path d="M12 18.26l-7.053 3.948 1.575-7.928L.587 8.792l8.027-.952L12 .5l3.386 7.34 8.027.952-5.935 5.488 1.575 7.928z"></path> </svg>
</p>
</div>`)
}
},
completedInternTasks(internId) {
const { completedTasks } = RIBC.getInternRecord(internId) const { completedTasks } = RIBC.getInternRecord(internId)
if (getObjLength(completedTasks) === 0) return false if (getObjLength(completedTasks) === 0) return false
return Object.keys(completedTasks).map(task => { return Object.keys(completedTasks).map(task => {
const { points, completionDate } = completedTasks[task]; const { points, completionDate } = completedTasks[task];
const { title } = RIBC.getAllTasks()[task]; const { title } = RIBC.getAllTasks()[task];
return html` return html`
<div class="intern_info__task"> <div class="intern_profile__task">
<h4>${title}</h4> <h4>${title}</h4>
<time>${getFormattedTime(completionDate, 'date-only')}</time> <time>${getFormattedTime(completionDate, 'date-only')}</time>
<p class="flex align-center gap-0-3"> <p class="flex align-center gap-0-3">
@ -2197,13 +2224,94 @@
<h4 class="task__title">${title}</h4> <h4 class="task__title">${title}</h4>
${linkifyDescription} ${linkifyDescription}
</div> </div>
<button class="send-update-button button--small margin-left-auto" onclick=${initTaskUpdate}> <button class="send-update-button button--small button--colored margin-left-auto" onclick=${initTaskUpdate}>
<svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M1.946 9.315c-.522-.174-.527-.455.01-.634l19.087-6.362c.529-.176.832.12.684.638l-5.454 19.086c-.15.529-.455.547-.679.045L12 14l6-8-8 6-8.054-2.685z"/></svg> <svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M1.946 9.315c-.522-.174-.527-.455.01-.634l19.087-6.362c.529-.176.832.12.684.638l-5.454 19.086c-.15.529-.455.547-.679.045L12 14l6-8-8 6-8.054-2.685z"/></svg>
Post an update Post an update
</button> </button>
</li> </li>
`; `;
}, },
internProfile(internFloId) {
const { joined, completedTasks = {}, active = true } = RIBC.getInternRecord(internFloId) || {}
const internName = RIBC.getInternList()[internFloId]
const rating = RIBC.getInternRating(internFloId)
let completedTasksCount = 0;
let totalPoints = 0
for (const task in completedTasks) {
completedTasksCount++
totalPoints += completedTasks[task].points
}
const splitName = internName.split(' ')
let initials = splitName[0][0]
if (splitName.length > 1) {
initials += splitName[splitName.length - 1][0]
}
renderElem(getRef('intern_profile'), html`
<div id="intern_profile__left">
<div class="flex flex-direction-column align-items-center gap-1-5">
<div id="intern_profile__initials" class="intern-card__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div>
<div class="flex flex-direction-column align-items-center gap-0-5">
<div class="flex align-center gap-0-5">
<h3 id="intern_profile__name" class="text-center">${internName}</h3>
${userType === "admin" ? html`<button id="edit_intern_name" class="button button--small button--colored" onclick=${toggleInternNameEditing}>Edit</button> ` : ''}
</div>
<sm-copy id="intern_profile__flo_id" value=${internFloId}></sm-copy>
</div>
${joined ? html`<p>Joined on ${getFormattedTime(joined, 'date-only')}</p>` : ''}
</div>
<div id="stats_wrapper">
<div id="intern_rating" class="stat">
<div class="stat__display">
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
<span class="stat__count">${rating}%</h4>
</div>
<p>Rating</p>
</div>
<div id="intern_complete_tasks" class="stat">
<div class="stat__display">
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
<span class="stat__count">${completedTasksCount}</h4>
</div>
<p>Task completed</p>
</div>
<div id="intern_points" class="stat">
<div class="stat__display">
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
<span class="stat__count">${totalPoints}</h4>
</div>
<p>Points earned</p>
</div>
</div>
</div>
<div id="intern_profile__right" class="flex flex-direction-column gap-1-5">
<div class="flex align-center space-between gap-1">
<h3>Tasks</h3>
<a href=${`#/updates_page?projectCode=all&internId=${internFloId}`} class="button button--small button--colored">See updates</a>
</div>
<div>
<h4>Assigned</h4>
<div>
${render.assignedInternTasks(internFloId) || html`<p>No currently assigned tasks</p>`}
</div>
</div>
<div>
<h4>Completed</h4>
<div>
${render.completedInternTasks(internFloId) || html`<p>No tasks completed yet</p>`}
</div>
</div>
</div>
`)
let color = '--green';
if (rating < 50) {
color = '--danger-color'
} else if (rating < 80) {
color = '--orange'
}
setTimeout(() => {
getRef('intern_rating').style = `--progress: ${400 - (rating * 4)}; --rating-color:var(${color})`;
}, 100);
},
dashProject(projectCode) { dashProject(projectCode) {
const { projectName } = RIBC.getProjectDetails(projectCode) const { projectName } = RIBC.getProjectDetails(projectCode)
const projectMap = RIBC.getProjectMap(projectCode) const projectMap = RIBC.getProjectMap(projectCode)
@ -2620,85 +2728,6 @@
return days; return days;
} }
// opens a popup containing various intern information
function showInternInfo(e) {
const internFloId = e.target.closest('.intern-card').dataset.internFloId;
const { joined, completedTasks = {}, active = true } = RIBC.getInternRecord(internFloId) || {}
const internName = RIBC.getInternList()[internFloId]
const rating = RIBC.getInternRating(internFloId)
let completedTasksCount = 0;
let totalPoints = 0
for (const task in completedTasks) {
completedTasksCount++
totalPoints += completedTasks[task].points
}
const splitName = internName.split(' ')
let initials = splitName[0][0]
if (splitName.length > 1) {
initials += splitName[splitName.length - 1][0]
}
renderElem(getRef('intern_info__wrapper'), html`
<div id="intern_info__left">
<div class="flex flex-direction-column align-items-center gap-1-5">
<div id="intern_info__initials" class="intern-card__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div>
<div class="flex flex-direction-column align-items-center gap-0-5">
<div class="flex align-center gap-0-5">
<h3 id="intern_info__name" class="text-center">${internName}</h3>
${userType === "admin" ? html`<button id="edit_intern_name" class="button button--small button--colored" onclick=${toggleInternNameEditing}>Edit</button> ` : ''}
</div>
<sm-copy id="intern_info__flo_id" value=${internFloId}></sm-copy>
</div>
${joined ? html`<p>Joined on ${getFormattedTime(joined, 'date-only')}</p>` : ''}
</div>
<div id="stats_wrapper">
<div id="intern_rating" class="stat">
<div class="stat__display">
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
<span class="stat__count">${rating}%</h4>
</div>
<p>Rating</p>
</div>
<div id="intern_complete_tasks" class="stat">
<div class="stat__display">
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
<span class="stat__count">${completedTasksCount}</h4>
</div>
<p>Task completed</p>
</div>
<div id="intern_points" class="stat">
<div class="stat__display">
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
<span class="stat__count">${totalPoints}</h4>
</div>
<p>Points earned</p>
</div>
</div>
</div>
<div id="intern_info__right">
<div id="intern_info__tasks">
<div class="flex align-center space-between gap-1">
<h3>Tasks completed</h3>
<a href=${`#/updates_page?projectCode=all&internId=${internFloId}`} class="button button--small button--colored">See updates</a>
</div>
<div id="intern_info__tasks_list">
${render.internSpecificTasks(internFloId) || html`<p>No tasks completed yet</p>`}
</div>
</div>
</div>
`)
openPopup('intern_info_popup');
let color = '--green';
if (rating < 50) {
color = '--danger-color'
} else if (rating < 80) {
color = '--orange'
}
setTimeout(() => {
getRef('intern_rating').style = `--progress: ${400 - (rating * 4)}; --rating-color:var(${color})`;
}, 100);
}
// opens a popup containing various project information // opens a popup containing various project information
function showProjectInfo(projectCode) { function showProjectInfo(projectCode) {
const { projectName, projectDescription } = RIBC.getProjectDetails(projectCode); const { projectName, projectDescription } = RIBC.getProjectDetails(projectCode);
@ -3156,22 +3185,22 @@
function toggleInternNameEditing(e) { function toggleInternNameEditing(e) {
const button = e.target.closest('button'); const button = e.target.closest('button');
if (getRef('intern_info__name').isContentEditable) { if (getRef('intern_profile__name').isContentEditable) {
const floId = getRef('intern_info__flo_id').value; const floId = getRef('intern_profile__flo_id').value;
const newName = getRef('intern_info__name').textContent.trim(); const newName = getRef('intern_profile__name').textContent.trim();
if (newName !== '' && floGlobals.tempEditableContent !== newName) { if (newName !== '' && floGlobals.tempEditableContent !== newName) {
RIBC.admin.renameIntern(floId, newName) RIBC.admin.renameIntern(floId, newName)
const highPerformingInterns = Object.keys(RIBC.getInternList()).sort((a, b) => RIBC.getInternRating(b) - RIBC.getInternRating(a)); const highPerformingInterns = Object.keys(RIBC.getInternList()).sort((a, b) => RIBC.getInternRating(b) - RIBC.getInternRating(a));
renderElem(getRef('top_interns'), html`${highPerformingInterns.slice(0, 8).map(floId => render.internCard(floId))}`) renderElem(getRef('top_interns'), html`${highPerformingInterns.slice(0, 8).map(floId => render.internCard(floId))}`)
notify('Intern name updated locally, please commit changes to make them permanent.', 'success') notify('Intern name updated locally, please commit changes to make them permanent.', 'success')
} }
getRef('intern_info__name').contentEditable = false; getRef('intern_profile__name').contentEditable = false;
button.textContent = 'Edit'; button.textContent = 'Edit';
document.getSelection().collapseToEnd() document.getSelection().collapseToEnd()
floGlobals.tempEditableContent = ''; floGlobals.tempEditableContent = '';
adminDataChanged(); adminDataChanged();
} else { } else {
makeEditable(getRef('intern_info__name')) makeEditable(getRef('intern_profile__name'))
button.textContent = 'Done' button.textContent = 'Done'
} }
} }
@ -3233,7 +3262,7 @@
} }
delegate(getRef('all_updates_list'), 'click', '.init-update-replay', (e) => { delegate(getRef('all_updates_list'), 'click', '.init-update-replay', (e) => {
const vectorClock = e.delegateTarget.closest('.intern-update').dataset.vectorClock; const vectorClock = e.delegateTarget.closest('.intern-update').dataset.vectorClock;
e.delegateTarget.after(html.node` e.delegateTarget.parentNode.after(html.node`
<sm-form class="update-replay grid gap-0-5"> <sm-form class="update-replay grid gap-0-5">
<sm-textarea placeholder="Enter your reply here" class="update-reply-textarea" rows="4" required></sm-textarea> <sm-textarea placeholder="Enter your reply here" class="update-reply-textarea" rows="4" required></sm-textarea>
<div class="flex align-center gap-0-3 margin-left-auto"> <div class="flex align-center gap-0-3 margin-left-auto">
@ -3244,9 +3273,22 @@
</div> </div>
</sm-form> </sm-form>
`) `)
e.delegateTarget.classList.add('hidden') e.delegateTarget.parentNode.classList.add('hidden')
e.target.closest('.intern-update').querySelector('.update-reply-textarea').focusIn() e.target.closest('.intern-update').querySelector('.update-reply-textarea').focusIn()
}) })
delegate(getRef('all_updates_list'), 'click', '.save-update', (e) => {
const vectorClock = e.delegateTarget.closest('.intern-update').dataset.vectorClock;
getConfirmation('Are you sure you want to save this update?', { confirmText: 'Save' }).then((res) => {
if (res) {
floCloudAPI.tagApplicationData(vectorClock, 'saved').then(() => {
notify('Update saved', 'success')
e.delegateTarget.remove()
}).catch(() => {
notify('Failed to save update', 'error')
})
}
})
})
function cancelUpdateReply(replayBox) { function cancelUpdateReply(replayBox) {
replayBox.previousElementSibling.classList.remove('hidden') replayBox.previousElementSibling.classList.remove('hidden')
@ -3385,9 +3427,6 @@
case 'rate_participants_popup': case 'rate_participants_popup':
renderElem(getRef('rating_wrapper'), html``) renderElem(getRef('rating_wrapper'), html``)
break; break;
case 'intern_info_popup':
renderElem(getRef('intern_info__wrapper'), html``)
break;
} }
if (popupStack.items.length === 0) { if (popupStack.items.length === 0) {
getRef('main_page').removeAttribute('inert') getRef('main_page').removeAttribute('inert')

View File

@ -71,7 +71,8 @@
floID: data.senderID, floID: data.senderID,
update: data.message, update: data.message,
time: data.vectorClock.split('_')[0], time: data.vectorClock.split('_')[0],
note: data.note note: data.note,
tag: data.tag
} }
}) })
internUpdates = internUpdates.filter(data => data.floID in _.internList) internUpdates = internUpdates.filter(data => data.floID in _.internList)

2
scripts/ribc.min.js vendored

File diff suppressed because one or more lines are too long