changes to admin task UI

-- task description is now collapsed by default
-- task related options are moved out from context menu to task bottom bar
This commit is contained in:
sairaj mote 2023-02-03 01:51:39 +05:30
parent a664e556a2
commit 5f23b0d501
5 changed files with 227 additions and 255 deletions

File diff suppressed because one or more lines are too long

View File

@ -1076,9 +1076,6 @@ ul {
.task h4 {
margin-top: 0.4rem;
}
.task .assigned-interns .assigned-intern {
padding: 0.4rem;
}
.admin-reply__description {
max-width: 100%;
@ -1099,6 +1096,12 @@ ul {
padding: 1rem;
}
#task_editing_popup [contenteditable] {
padding: 0.8rem;
background-color: rgba(var(--text-color), 0.06);
border-radius: 0.5rem;
}
#dashboard_page {
padding-bottom: 5rem;
grid-template-columns: minmax(0, 1fr);
@ -1318,11 +1321,9 @@ ul {
display: flex;
gap: 1rem;
justify-content: space-evenly;
flex-wrap: wrap;
margin: 1.5rem 0;
}
#stats_wrapper > * {
flex: 1;
}
.stat {
display: flex;
@ -1330,6 +1331,7 @@ ul {
align-items: center;
text-align: center;
gap: 0.5rem;
flex: 1;
}
.stat__display {
display: grid;
@ -1519,6 +1521,11 @@ ul {
padding: 0.2rem 0.4rem;
font-weight: 500;
}
.admin-task .intern-section {
margin: 0 -1rem;
background-color: rgba(var(--text-color), 0.03);
padding: 1rem;
}
.tag {
padding: 0.4rem 0.8rem;
@ -1572,12 +1579,7 @@ ul {
word-wrap: break-word;
}
.assigned-interns {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.assigned-interns .assigned-intern {
.assigned-intern {
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
@ -1590,8 +1592,9 @@ ul {
align-items: center;
white-space: nowrap;
text-transform: capitalize;
height: 100%;
}
.assigned-interns .assigned-intern .unassign-intern-button {
.assigned-intern .unassign-intern-button {
padding: 0.4rem;
margin-right: -0.4rem;
}
@ -1618,34 +1621,6 @@ ul {
padding: 0.6rem 0.8rem;
}
#task_context {
position: absolute;
top: 0;
right: 0;
margin: -1rem 1rem 0 1rem;
list-style: none;
width: -webkit-fit-content;
width: -moz-fit-content;
width: fit-content;
border-radius: 0.5rem;
transition: 0.3s opacity;
background-color: rgba(var(--foreground-color), 1);
box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.16);
transform-origin: top right;
border: solid thin rgba(var(--text-color), 0.16);
}
#task_context li {
display: flex;
align-items: center;
font-size: 0.9rem;
margin: 0.2rem;
padding: 0.6rem 0.8rem;
border-radius: 0.3rem;
}
#task_context li .icon {
margin-right: 0.5rem;
}
#branch_container {
display: flex;
flex-flow: row wrap;
@ -2285,6 +2260,9 @@ input[type=date]:focus {
#post_update_popup {
--width: 28rem;
}
#task_editing_popup {
--width: 42rem;
}
#updates_page {
height: 100%;
gap: 1rem;

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -1047,10 +1047,6 @@ ul {
h4 {
margin-top: 0.4rem;
}
.assigned-interns .assigned-intern {
padding: 0.4rem;
}
}
.admin-reply__description {
max-width: 100%;
@ -1071,6 +1067,14 @@ ul {
padding: 1rem;
}
#task_editing_popup {
[contenteditable] {
padding: 0.8rem;
background-color: rgba(var(--text-color), 0.06);
border-radius: 0.5rem;
}
}
#dashboard_page {
padding-bottom: 5rem;
grid-template-columns: minmax(0, 1fr);
@ -1277,10 +1281,8 @@ ul {
display: flex;
gap: 1rem;
justify-content: space-evenly;
flex-wrap: wrap;
margin: 1.5rem 0;
& > * {
flex: 1;
}
}
.stat {
display: flex;
@ -1288,6 +1290,7 @@ ul {
align-items: center;
text-align: center;
gap: 0.5rem;
flex: 1;
&__display {
display: grid;
justify-items: center;
@ -1466,6 +1469,11 @@ ul {
padding: 0.2rem 0.4rem;
font-weight: 500;
}
.intern-section {
margin: 0 -1rem;
background-color: rgba(var(--text-color), 0.03);
padding: 1rem;
}
}
.tag {
padding: 0.4rem 0.8rem;
@ -1521,26 +1529,21 @@ ul {
overflow-wrap: break-word;
word-wrap: break-word;
}
.assigned-interns {
.assigned-intern {
position: relative;
user-select: none;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
.assigned-intern {
position: relative;
user-select: none;
display: flex;
font-size: 0.9rem;
padding: 0 0.4rem;
border-radius: 0.3rem;
border: 1px solid rgba(var(--text-color), 0.24);
align-items: center;
white-space: nowrap;
text-transform: capitalize;
.unassign-intern-button {
padding: 0.4rem;
margin-right: -0.4rem;
}
font-size: 0.9rem;
padding: 0 0.4rem;
border-radius: 0.3rem;
border: 1px solid rgba(var(--text-color), 0.24);
align-items: center;
white-space: nowrap;
text-transform: capitalize;
height: 100%;
.unassign-intern-button {
padding: 0.4rem;
margin-right: -0.4rem;
}
}
.menu {
@ -1564,33 +1567,6 @@ ul {
}
}
}
#task_context {
position: absolute;
top: 0;
right: 0;
margin: -1rem 1rem 0 1rem;
list-style: none;
width: fit-content;
border-radius: 0.5rem;
transition: 0.3s opacity;
background-color: rgba(var(--foreground-color), 1);
box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.16);
transform-origin: top right;
border: solid thin rgba(var(--text-color), 0.16);
li {
display: flex;
align-items: center;
font-size: 0.9rem;
margin: 0.2rem;
padding: 0.6rem 0.8rem;
border-radius: 0.3rem;
.icon {
margin-right: 0.5rem;
}
}
}
#branch_container {
display: flex;
flex-flow: row wrap;
@ -2232,6 +2208,9 @@ input[type="date"] {
#post_update_popup {
--width: 28rem;
}
#task_editing_popup {
--width: 42rem;
}
#updates_page {
height: 100%;
gap: 1rem;

View File

@ -423,43 +423,6 @@
</svg>
Add task
</button>
<ul id="task_context" class="hidden">
<li tabindex="0" class="interactive" onclick="toggleEditing('title')">
<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="M15.728 9.686l-1.414-1.414L5 17.586V19h1.414l9.314-9.314zm1.414-1.414l1.414-1.414-1.414-1.414-1.414 1.414 1.414 1.414zM7.242 21H3v-4.243L16.435 3.322a1 1 0 0 1 1.414 0l2.829 2.829a1 1 0 0 1 0 1.414L7.243 21z" />
</svg>
Edit title
</li>
<li tabindex="0" class="interactive" onclick="toggleEditing()">
<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="M15.728 9.686l-1.414-1.414L5 17.586V19h1.414l9.314-9.314zm1.414-1.414l1.414-1.414-1.414-1.414-1.414 1.414 1.414 1.414zM7.242 21H3v-4.243L16.435 3.322a1 1 0 0 1 1.414 0l2.829 2.829a1 1 0 0 1 0 1.414L7.243 21z" />
</svg>
Edit description
</li>
<li onclick="showNewBranchPopup()" tabindex="0" class="interactive">
<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="M7.105 15.21A3.001 3.001 0 1 1 5 15.17V8.83a3.001 3.001 0 1 1 2 0V12c.836-.628 1.874-1 3-1h4a3.001 3.001 0 0 0 2.895-2.21 3.001 3.001 0 1 1 2.032.064A5.001 5.001 0 0 1 14 13h-4a3.001 3.001 0 0 0-2.895 2.21zM6 17a1 1 0 1 0 0 2 1 1 0 0 0 0-2zM6 5a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm12 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z" />
</svg>
Create new Branch
</li>
<li onclick="markTaskAsCompleted()" tabindex="0" class="interactive">
<svg class="icon margin-right-0-3" xmlns="http://www.w3.org/2000/svg" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" />
</svg>
Mark as complete
</li>
</ul>
</section>
</section>
<section id="interns_container" class="flex flex-direction-column hidden">
@ -644,6 +607,79 @@
</button>
</sm-form>
</sm-popup>
<sm-popup id="task_editing_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>
<h3>Edit task</h3>
</header>
<sm-form id="task_edit_form">
<div class="grid gap-0-5">
<b>Title</b>
<sm-input id="edit_task_title" required></sm-input>
</div>
<div class="grid gap-0-5">
<b>Description</b>
<p id="edit_task_description" class="task-description ws-pre-line wrap-around" contenteditable="true">
</p>
</div>
<div class="grid gap-0-5 margin-top-1" style="grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));">
<sm-select id="edit_task_category" label="Category: "></sm-select>
<div class="flex flex-1">
<sm-input id="edit_task_duration" class="flex-1" placeholder="Duration" type="number"
style="--border-radius: 0.5rem 0 0 0.5rem; border-right: thin solid rgba(var(--text-color), 0.3);"
animate="" aria-label="Duration" role="textbox">
<svg slot="icon" class="icon" xmlns="http://www.w3.org/2000/svg"
enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
<g>
<rect fill="none" height="24" width="24"></rect>
</g>
<g>
<g>
<g>
<path
d="M15,1H9v2h6V1z M11,14h2V8h-2V14z M19.03,7.39l1.42-1.42c-0.43-0.51-0.9-0.99-1.41-1.41l-1.42,1.42 C16.07,4.74,14.12,4,12,4c-4.97,0-9,4.03-9,9s4.02,9,9,9s9-4.03,9-9C21,10.88,20.26,8.93,19.03,7.39z M12,20c-3.87,0-7-3.13-7-7 s3.13-7,7-7s7,3.13,7,7S15.87,20,12,20z">
</path>
</g>
</g>
</g>
</svg>
</sm-input>
<sm-select id="edit_task_duration_type" class="flex-shrink-0"
style="--select-border-radius: 0 0.5rem 0.5rem 0;" role="listbox" align-select="right">
<sm-option value="days">Days</sm-option>
<sm-option value="months">Months</sm-option>
</sm-select>
</div>
<sm-input id="edit_task_max_slots" placeholder="Max slots available" type="number" animate=""
aria-label="Max slots available" role="textbox"> </sm-input>
<sm-input id="edit_task_reward" type="number" placeholder="Reward" animate="" aria-label="Reward"
role="textbox">
<svg slot="icon" class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24"
height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<g>
<rect fill="none" height="24" width="24"></rect>
</g>
<g>
<g>
<path
d="M13.66,7C13.1,5.82,11.9,5,10.5,5L6,5V3h12v2l-3.26,0c0.48,0.58,0.84,1.26,1.05,2L18,7v2l-2.02,0c-0.25,2.8-2.61,5-5.48,5 H9.77l6.73,7h-2.77L7,14v-2h3.5c1.76,0,3.22-1.3,3.46-3L6,9V7L13.66,7z">
</path>
</g>
</g>
</svg>
</sm-input>
</div>
<button class="button button--primary" onclick="saveTaskChanges()" type="submit">Save</button>
</sm-form>
</sm-popup>
<sm-popup id="create_branch_popup">
<header slot="header" class="popup__header">
<button class="popup__header__close" onclick="closePopup()">
@ -1887,7 +1923,7 @@
</div>
<div class="right">
<h4 class="timeline-task__title">${title}</h4>
${assignedInternsCards.length ? html`<div class="assigned-interns">${assignedInternsCards}</div>` : ''}
${assignedInternsCards.length ? html`<div class="flex align-center gap-0-3 flex-wrap">${assignedInternsCards}</div>` : ''}
<collapsed-text>
${linkifyDescription}
</collapsed-text>
@ -2006,9 +2042,9 @@
</a>
`;
},
assignedInternCard(internFloId, options) {
assignedInternCard(internFloId, taskId) {
let optionsButton
if (options) {
if (taskId && !RIBC.getInternRecord(internFloId).completedTasks.hasOwnProperty(taskId)) {
optionsButton = html` <button class="unassign-intern-button">
<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> `;
@ -2046,7 +2082,7 @@
const div = document.createElement('div')
div.innerHTML = DOMPurify.sanitize(linkify(link || description))
const links = [...div.querySelectorAll('a')].map(link => {
link.textContent = 'See task output'
link.textContent = 'See output'
link.className = 'button button--small button--colored margin-right-auto'
return link
})
@ -2065,7 +2101,7 @@
const assignedInterns = RIBC.getAssignedInterns(appState.params.id, appState.params.branch, task)
const status = RIBC.getTaskStatus(appState.params.id, appState.params.branch, task)
const { title, description, category, maxSlots, duration, durationType, reward } = RIBC.getTaskDetails(appState.params.id, appState.params.branch, task)
let assignedInternsCards = assignedInterns.map(internFloId => render.assignedInternCard(internFloId, status === 'incomplete'))
let assignedInternsCards = assignedInterns.map(internFloId => render.assignedInternCard(internFloId, `${appState.params.id}_${appState.params.branch}_${task}`))
const branches = getAllBranches(appState.params.id)
const branchesButtons = filterMap(branches, (branch) => {
const { branchName, parentBranch, startPoint, endPoint } = branch
@ -2080,65 +2116,67 @@
if (status === 'incomplete') {
const taskTitle = createElement('h4', {
className: 'task-title',
attributes: {
'data-editable': '',
'data-edit-field': 'title',
},
innerHTML: DOMPurify.sanitize(title)
})
const taskDescription = createElement('p', {
className: 'task-description ws-pre-line wrap-around',
attributes: {
'data-editable': '',
'data-edit-field': 'description',
},
innerHTML: DOMPurify.sanitize(description)
})
const categories = objMap(floGlobals.taskCategories, (categoryName, categoryID) => {
return html`<sm-option value=${categoryID} ?selected=${category === categoryID}>${categoryName}</sm-option>`
})
return html`
<li class=${`admin-task ${status}`} .dataset=${{ taskId: task }}>
<div class="flex align-center gap-0-3">
<div class="admin-task__task-number margin-right-auto">ID: ${task}</div>
${taskTitle}
<div class="grid gap-1 intern-section">
<div class="flex align-center gap-0-5">
<button class="button button--small button--colored" onclick="currentTask=this.closest('.admin-task');openPopup('intern_list_popup')">
<svg class="icon margin-right-0-3" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><path d="M20,9V6h-2v3h-3v2h3v3h2v-3h3V9H20z M9,12c2.21,0,4-1.79,4-4c0-2.21-1.79-4-4-4S5,5.79,5,8C5,10.21,6.79,12,9,12z M9,6 c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2S7,9.1,7,8C7,6.9,7.9,6,9,6z M15.39,14.56C13.71,13.7,11.53,13,9,13c-2.53,0-4.71,0.7-6.39,1.56 C1.61,15.07,1,16.1,1,17.22V20h16v-2.78C17,16.1,16.39,15.07,15.39,14.56z M15,18H3v-0.78c0-0.38,0.2-0.72,0.52-0.88 C4.71,15.73,6.63,15,9,15c2.37,0,4.29,0.73,5.48,1.34C14.8,16.5,15,16.84,15,17.22V18z"/></g></svg>
Assign
</button>
<button class="button button--small button--colored" onclick=${initTaskScoring}>
<svg class="icon margin-right-0-3" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"/></svg>
Rate interns
Rate
</button>
<div class="admin-task__task-number">ID: ${task}</div>
</div>
<button class="button--danger icon-only margin-left-auto"onclick="removeThisTask()">
${assignedInternsCards.length ? html`<div class="flex align-center flex-wrap gap-0-3"> ${assignedInternsCards} </div>` : 'No interns assigned. Click on "Assign" to assign interns.'}
</div>
<collapsed-text>
${taskDescription}
${branchesButtons.length ? html`<div class="task__branch_container">${branchesButtons}</div>` : ''}
<div class="display-task__details flex flex-wrap gap-0-3 margin-top-1">
<div class="display-task__detail">
<span class="display-task__detail__title">Category: </span>
<span class="display-task__detail__value">${floGlobals.taskCategories[category]}</span>
</div>
<div class="display-task__detail">
<span class="display-task__detail__title">Duration: </span>
<span class="display-task__detail__value">${duration} ${durationType}</span>
</div>
<div class="display-task__detail">
<span class="display-task__detail__title">Max slots: </span>
<span class="display-task__detail__value">${maxSlots}</span>
</div>
<div class="display-task__detail">
<span class="display-task__detail__title">Reward: </span>
<span class="display-task__detail__value">${reward}</span>
</div>
</div>
</collapsed-text>
${branchesButtons.length ? html`<div class="task__branch_container">${branchesButtons}</div>` : ''}
<div class="flex align-center gap-0-5 flex-wrap margin-top-1">
<button class="button button--small button--colored" onclick=${markTaskAsCompleted}>
<svg class="icon margin-right-0-3" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0z" fill="none" /> <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" /> </svg>
Mark as done
</button>
<button class="button button--small button--colored" onclick=${openNewBranchPopup}>
<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="M7.105 15.21A3.001 3.001 0 1 1 5 15.17V8.83a3.001 3.001 0 1 1 2 0V12c.836-.628 1.874-1 3-1h4a3.001 3.001 0 0 0 2.895-2.21 3.001 3.001 0 1 1 2.032.064A5.001 5.001 0 0 1 14 13h-4a3.001 3.001 0 0 0-2.895 2.21zM6 17a1 1 0 1 0 0 2 1 1 0 0 0 0-2zM6 5a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm12 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2z" /> </svg>
Create Branch
</button>
<button class="button icon-only button--colored margin-left-auto" title="Edit task" onclick=${openTaskEditingPopup}>
<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> <path d="M15.728 9.686l-1.414-1.414L5 17.586V19h1.414l9.314-9.314zm1.414-1.414l1.414-1.414-1.414-1.414-1.414 1.414 1.414 1.414zM7.242 21H3v-4.243L16.435 3.322a1 1 0 0 1 1.414 0l2.829 2.829a1 1 0 0 1 0 1.414L7.243 21z"></path> </svg>
</button>
<button class="button--danger icon-only" title="Delete this task" onclick="removeThisTask()">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z"/></svg>
</button>
<button class="icon-only task-option">
<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 3c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 14c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-7c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" /> </svg>
</button>
</div>
${taskTitle}
<div class="assigned-interns">
<button class="button button--small button--colored" onclick="currentTask=this.closest('.admin-task');openPopup('intern_list_popup')">
<svg class="icon margin-right-0-3" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><path d="M20,9V6h-2v3h-3v2h3v3h2v-3h3V9H20z M9,12c2.21,0,4-1.79,4-4c0-2.21-1.79-4-4-4S5,5.79,5,8C5,10.21,6.79,12,9,12z M9,6 c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2S7,9.1,7,8C7,6.9,7.9,6,9,6z M15.39,14.56C13.71,13.7,11.53,13,9,13c-2.53,0-4.71,0.7-6.39,1.56 C1.61,15.07,1,16.1,1,17.22V20h16v-2.78C17,16.1,16.39,15.07,15.39,14.56z M15,18H3v-0.78c0-0.38,0.2-0.72,0.52-0.88 C4.71,15.73,6.63,15,9,15c2.37,0,4.29,0.73,5.48,1.34C14.8,16.5,15,16.84,15,17.22V18z"/></g></svg>
Assign intern
</button>
${assignedInternsCards}
</div>
${taskDescription}
${branchesButtons.length ? html`<div class="task__branch_container">${branchesButtons}</div>` : ''}
<div class="grid gap-0-5 margin-top-1" style="grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));">
<sm-select data-edit-field="category" label="Category: ">${categories}</sm-select>
<div class="flex flex-1">
<sm-input data-edit-field="duration" value="${duration}" class="flex-1" placeholder="Duration" type="number" style="--border-radius: 0.5rem 0 0 0.5rem; border-right: thin solid rgba(var(--text-color), 0.3);" animate="" aria-label="Duration" role="textbox">
<svg slot="icon" class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <g> <rect fill="none" height="24" width="24"></rect> </g> <g> <g> <g> <path d="M15,1H9v2h6V1z M11,14h2V8h-2V14z M19.03,7.39l1.42-1.42c-0.43-0.51-0.9-0.99-1.41-1.41l-1.42,1.42 C16.07,4.74,14.12,4,12,4c-4.97,0-9,4.03-9,9s4.02,9,9,9s9-4.03,9-9C21,10.88,20.26,8.93,19.03,7.39z M12,20c-3.87,0-7-3.13-7-7 s3.13-7,7-7s7,3.13,7,7S15.87,20,12,20z"></path> </g> </g> </g> </svg>
</sm-input>
<sm-select data-edit-field="durationType" class="flex-shrink-0" style="--select-border-radius: 0 0.5rem 0.5rem 0;" role="listbox" align-select="right" value="days">
<sm-option value="days" ?selected=${durationType === "days"}>Days</sm-option>
<sm-option value="months" ?selected=${durationType === "months"}>Months</sm-option>
</sm-select>
</div>
<sm-input data-edit-field="maxSlots" value=${maxSlots} placeholder="Max slots available" type="number" animate="" aria-label="Max slots available" role="textbox"> </sm-input>
<sm-input data-edit-field="reward" value=${reward} type="number" placeholder="Reward" animate="" aria-label="Reward" role="textbox">
<svg slot="icon" class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <g> <rect fill="none" height="24" width="24"></rect> </g> <g> <g> <path d="M13.66,7C13.1,5.82,11.9,5,10.5,5L6,5V3h12v2l-3.26,0c0.48,0.58,0.84,1.26,1.05,2L18,7v2l-2.02,0c-0.25,2.8-2.61,5-5.48,5 H9.77l6.73,7h-2.77L7,14v-2h3.5c1.76,0,3.22-1.3,3.46-3L6,9V7L13.66,7z"> </path> </g> </g> </svg>
</sm-input>
</div>
</li>
`;
@ -2157,7 +2195,7 @@
<span class="tag">Completed</span>
</div>
<h4 class="task-title">${title}</h4>
<div class="assigned-interns">
<div class="flex align-center gap-0-3 flex-wrap">
${assignedInternsCards}
</div>
<collapsed-text>
@ -2307,6 +2345,10 @@
savedUpdates.set(`${projectCode}_${branch}_${task}`, { link, description })
}
})
const rewardEarned = Object.keys(completedTasks).reduce((acc, task) => {
return acc + RIBC.getAllTasks()[task].reward
}, 0)
console.log('rewardEarned', rewardEarned)
renderElem(getRef('intern_profile'), html`
<div id="intern_profile__left">
<div class="flex flex-direction-column align-items-center gap-1-5">
@ -2363,13 +2405,19 @@
</div>
</div>
<div>
<h4>Completed</h4>
<div class="flex align-center space-between text-align-right">
<h4>Completed</h4>
</div>
<div>
${render.completedInternTasks(internFloId, savedUpdates) || html`<p>No tasks completed yet</p>`}
</div>
</div>
</div>
`)
// <div class="grid">
// <p style="font-size: 0.8rem">Earned</p>
// <b class="stat__count" style="font-size:1rem;">${formatAmount(rewardEarned)}</b>
// </div>
let color = '--green';
if (rating < 50) {
color = '--danger-color'
@ -3004,85 +3052,33 @@
}
})
}
delegate(getRef('task_list'), 'change', 'sm-select', (e) => {
currentTask = e.target.closest('.admin-task');
if (!currentTask) return;
const taskDetails = {
[e.target.dataset.editField]: e.target.value
function saveTaskChanges() {
const changedDetails = {
title: getRef('edit_task_title').value.trim(),
description: DOMPurify.sanitize(getRef('edit_task_description').innerHTML.trim()),
category: getRef('edit_task_category').value,
duration: parseInt(getRef('edit_task_duration').value),
durationType: getRef('edit_task_duration_type').value,
maxSlots: parseInt(getRef('edit_task_max_slots').value),
reward: parseInt(getRef('edit_task_reward').value)
}
RIBC.admin.editTaskDetails(taskDetails, appState.params.id, appState.params.branch, currentTask.dataset.taskId)
notify('Changes saved locally, commit the changes to make them permanent', 'success')
adminDataChanged();
})
getRef('task_list').addEventListener('focusout', (e) => {
currentTask = e.target.closest('.admin-task');
if (!currentTask) return;
const ogTaskDetails = RIBC.getTaskDetails(appState.params.id, appState.params.branch, currentTask.dataset.taskId)
const newTaskDetails = {}
if (e.target.isContentEditable) {
e.target.contentEditable = false
newTaskDetails[e.target.dataset.editField] = DOMPurify.sanitize(e.target.innerHTML.trim())
} else if (e.target.closest('sm-input')) {
newTaskDetails[e.target.dataset.editField] = parseInt(e.target.value)
} else {
return;
}
if (ogTaskDetails[e.target.dataset.editField] !== newTaskDetails[e.target.dataset.editField]) {
RIBC.admin.editTaskDetails(newTaskDetails, appState.params.id, appState.params.branch, currentTask.dataset.taskId)
const changedKeys = Object.keys(changedDetails).filter(key => ogTaskDetails[key] !== changedDetails[key])
if (changedKeys.length) {
RIBC.admin.editTaskDetails(changedDetails, appState.params.id, appState.params.branch, currentTask.dataset.taskId)
renderBranchTasks();
notify('Changes saved locally, commit the changes to make them permanent', 'success')
adminDataChanged();
} else {
notify('No changes detected')
}
})
getRef('task_list').addEventListener('dblclick', (e) => {
if (e.target.closest('[data-editable]') && !e.target.closest('[data-editable]').isContentEditable) {
makeEditable(e.target.closest('[data-editable]'))
}
})
closePopup();
}
getRef('task_list').addEventListener('click', (e) => {
if (e.target.closest('.admin-task')) {
currentTask = e.target.closest('.admin-task');
}
if (e.target.closest('.task-option')) {
const optionButton = e.target.closest('.task-option')
getRef('task_context').setAttribute('style', `top: ${optionButton.offsetTop}px;`)
getRef('task_context').classList.remove('hidden')
getRef('task_context').animate([
{
transform: 'scaleY(0.95) translateY(-0.5rem)',
opacity: '0'
},
{
transform: 'none',
opacity: '1'
},
], {
duration: floGlobals.prefersReducedMotion ? 0 : 200,
easing: 'ease'
})
.onfinish = () => {
getRef('task_context').firstElementChild.focus()
const y = document.addEventListener("click", function (e) {
if (e.target.closest('#context_menu') || e.target.closest('.task-option')) return;
getRef('task_context').animate([
{
transform: 'none',
opacity: '1'
},
{
transform: 'scaleY(0.95) translateY(-0.5rem)',
opacity: '0'
},
], {
duration: floGlobals.prefersReducedMotion ? 0 : 100,
easing: 'ease'
}).onfinish = () => {
getRef('task_context').classList.add('hidden')
document.removeEventListener('click', y);
}
});
}
}
else if (e.target.closest('.unassign-intern-button')) {
if (e.target.closest('.unassign-intern-button')) {
const internCard = e.target.closest('.assigned-intern')
const internId = internCard.dataset.floId
const contentMenu = html.node`
@ -3279,7 +3275,7 @@
renderElem(getRef('all_interns_list'), filterInterns('', { sortByRating: true }))
}
function showNewBranchPopup() {
function openNewBranchPopup() {
openPopup('create_branch_popup')
const startPoint = parseInt(currentTask.dataset.taskId)
getRef('branch_start_point').value = startPoint;
@ -3294,6 +3290,25 @@
closePopup()
adminDataChanged();
}
function openTaskEditingPopup(e) {
const taskNo = e.target.closest('.admin-task').dataset.taskId
const { title, description, category, maxSlots, duration, durationType, reward } = RIBC.getTaskDetails(appState.params.id, appState.params.branch, taskNo)
if (!getRef('edit_task_category').firstElementChild) {
const categories = objMap(floGlobals.taskCategories, (categoryName, categoryID) => {
return html`<sm-option value=${categoryID} ?selected=${category === categoryID}>${categoryName}</sm-option>`
})
renderElem(getRef('edit_task_category'), html`${categories}`)
}
getRef('edit_task_title').value = title
getRef('edit_task_description').innerHTML = DOMPurify.sanitize(description)
getRef('edit_task_category').value = category
getRef('edit_task_duration').value = duration
getRef('edit_task_duration_type').value = durationType
getRef('edit_task_max_slots').value = maxSlots
getRef('edit_task_reward').value = reward
openPopup('task_editing_popup')
getRef('task_edit_form')._checkValidity()
}
function toggleInternNameEditing(e) {
const button = e.target.closest('button');