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:
parent
a664e556a2
commit
5f23b0d501
File diff suppressed because one or more lines are too long
60
css/main.css
60
css/main.css
@ -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
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -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;
|
||||
|
||||
333
index.html
333
index.html
@ -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');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user