UI improvements
This commit is contained in:
parent
7fcdf46618
commit
0ecde83eb1
File diff suppressed because one or more lines are too long
26
css/main.css
26
css/main.css
@ -190,7 +190,9 @@ button:not(:disabled),
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
filter: saturate(0);
|
||||
}
|
||||
|
||||
.cta {
|
||||
@ -1345,7 +1347,7 @@ ul {
|
||||
padding: 1rem 0 1.5rem 0;
|
||||
}
|
||||
|
||||
.task-list-item {
|
||||
.admin-task {
|
||||
display: grid;
|
||||
align-content: flex-start;
|
||||
padding: 1rem;
|
||||
@ -1353,13 +1355,13 @@ ul {
|
||||
border-radius: 0.5rem;
|
||||
background: rgba(var(--foreground-color), 1);
|
||||
}
|
||||
.task-list-item h4 {
|
||||
.admin-task h4 {
|
||||
margin: 0;
|
||||
}
|
||||
.task-list-item .task-title {
|
||||
.admin-task .task-title {
|
||||
line-height: 1.6;
|
||||
}
|
||||
.task-list-item__task-number {
|
||||
.admin-task__task-number {
|
||||
font-size: 0.8rem;
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
border: solid 0.1em var(--accent-color);
|
||||
@ -1368,6 +1370,15 @@ ul {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tag {
|
||||
padding: 0.4rem 0.8rem;
|
||||
border-radius: 3rem;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
color: var(--green);
|
||||
background-color: rgba(var(--text-color), 0.06);
|
||||
}
|
||||
|
||||
.task__branch_container:not(:empty) {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
@ -1422,8 +1433,8 @@ ul {
|
||||
user-select: none;
|
||||
display: flex;
|
||||
font-size: 0.8rem;
|
||||
padding: 0.2rem 0 0.2rem 0.4rem;
|
||||
border-radius: 0.2rem;
|
||||
padding: 0.4rem;
|
||||
border-radius: 0.3rem;
|
||||
border: 1px solid rgba(var(--text-color), 0.24);
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
@ -1431,6 +1442,7 @@ ul {
|
||||
}
|
||||
.assigned-interns .assigned-intern button {
|
||||
padding: 0.2rem;
|
||||
margin-right: -0.2rem;
|
||||
}
|
||||
.assigned-interns .assigned-intern button .icon {
|
||||
height: 1rem;
|
||||
|
||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -181,7 +181,9 @@ button,
|
||||
}
|
||||
}
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
filter: saturate(0);
|
||||
}
|
||||
|
||||
.cta {
|
||||
@ -1333,13 +1335,15 @@ ul {
|
||||
gap: 0.5rem;
|
||||
padding: 1rem 0 1.5rem 0;
|
||||
}
|
||||
.task-list-item {
|
||||
.admin-task {
|
||||
display: grid;
|
||||
align-content: flex-start;
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
background: rgba(var(--foreground-color), 1);
|
||||
&.completed {
|
||||
}
|
||||
h4 {
|
||||
margin: 0;
|
||||
}
|
||||
@ -1355,6 +1359,14 @@ ul {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.tag {
|
||||
padding: 0.4rem 0.8rem;
|
||||
border-radius: 3rem;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
color: var(--green);
|
||||
background-color: rgba(var(--text-color), 0.06);
|
||||
}
|
||||
.task__branch_container {
|
||||
&:not(:empty) {
|
||||
display: grid;
|
||||
@ -1410,14 +1422,15 @@ ul {
|
||||
user-select: none;
|
||||
display: flex;
|
||||
font-size: 0.8rem;
|
||||
padding: 0.2rem 0 0.2rem 0.4rem;
|
||||
border-radius: 0.2rem;
|
||||
padding: 0.4rem;
|
||||
border-radius: 0.3rem;
|
||||
border: 1px solid rgba(var(--text-color), 0.24);
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
text-transform: capitalize;
|
||||
button {
|
||||
padding: 0.2rem;
|
||||
margin-right: -0.2rem;
|
||||
.icon {
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
|
||||
135
index.html
135
index.html
@ -1857,7 +1857,7 @@
|
||||
const internPoints = RIBC.getInternRating(internFloId)
|
||||
const initials = internName.split(' ').map(v => v.charAt(0)).join('');
|
||||
return html`
|
||||
<label class="intern-card align-center interact" .dataset=${{ internFloId }} onclick=${showInternInfo} title="Intern Information">
|
||||
<label class="intern-card align-center interact" .dataset=${{ internFloId }} onclick=${selectable ? false : showInternInfo} title="Intern Information">
|
||||
${selectable ? html`<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__name capitalize">${internName}</div>
|
||||
@ -1921,13 +1921,13 @@
|
||||
</span>
|
||||
`
|
||||
},
|
||||
taskListItem(task, ref) {
|
||||
adminTask(task) {
|
||||
const assignedInterns = RIBC.getAssignedInterns(appState.params.id, appState.params.branch, task)
|
||||
const taskDetails = { title, description, category, maxSlots, duration, durationType, reward } = RIBC.getTaskDetails(appState.params.id, appState.params.branch, task)
|
||||
const status = RIBC.getTaskStatus(appState.params.id, appState.params.branch, task)
|
||||
const taskDetails = { title, description, category, maxSlots, duration, durationType, reward } = RIBC.getTaskDetails(appState.params.id, appState.params.branch, task)
|
||||
let assignedInternsCards
|
||||
if (assignedInterns) {
|
||||
assignedInternsCards = filterMap(assignedInterns, (internFloId) => render.assignedInternCard(internFloId, true))
|
||||
assignedInternsCards = filterMap(assignedInterns, (internFloId) => render.assignedInternCard(internFloId, status === 'incomplete'))
|
||||
}
|
||||
const branches = getAllBranches(appState.params.id)
|
||||
const branchesButtons = filterMap(branches, (branch) => {
|
||||
@ -1940,26 +1940,31 @@
|
||||
})
|
||||
}
|
||||
})
|
||||
const categories = [];
|
||||
for (const categoryID in floGlobals.taskCategories) {
|
||||
categories.push(html`<sm-option value=${categoryID} ?selected=${categoryID === category}>${floGlobals.taskCategories[categoryID]}</sm-option>`)
|
||||
}
|
||||
const taskDescription = createElement('p', {
|
||||
const descriptionOptions = {
|
||||
className: 'task-description ws-pre-line wrap-around',
|
||||
attributes: {
|
||||
innerHTML: DOMPurify.sanitize(description)
|
||||
}
|
||||
if (status === 'incomplete') {
|
||||
descriptionOptions.attributes = {
|
||||
'data-editable': '',
|
||||
'data-edit-field': 'description',
|
||||
},
|
||||
innerHTML: DOMPurify.sanitize(description)
|
||||
})
|
||||
return html.for(ref, `${appState.params.id}_${appState.params.branch}_${task}`)`
|
||||
<li class="task-list-item" .dataset=${{ taskId: task }}>
|
||||
}
|
||||
}
|
||||
const taskDescription = createElement('p', descriptionOptions)
|
||||
if (status === 'incomplete') {
|
||||
const categories = [];
|
||||
for (const categoryID in floGlobals.taskCategories) {
|
||||
categories.push(html`<sm-option value=${categoryID} ?selected=${categoryID === category}>${floGlobals.taskCategories[categoryID]}</sm-option>`)
|
||||
}
|
||||
return html`
|
||||
<li class=${`admin-task ${status}`} .dataset=${{ taskId: task }}>
|
||||
<div class="flex align-center gap-0-3">
|
||||
<div class="flex align-center gap-0-5">
|
||||
<sm-checkbox ?checked=${status === 'completed'}>
|
||||
<p class="margin-left-0-5">Mark as complete</p>
|
||||
</sm-checkbox>
|
||||
<div class="task-list-item__task-number">ID: ${task}</div>
|
||||
<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="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>
|
||||
Mark as complete
|
||||
</button>
|
||||
<div class="admin-task__task-number">ID: ${task}</div>
|
||||
</div>
|
||||
<button class="button--danger icon-only margin-left-auto"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>
|
||||
@ -1970,13 +1975,14 @@
|
||||
</div>
|
||||
<h4 class="task-title capitalize" data-editable data-edit-field="title">${title}</h4>
|
||||
<div class="assigned-interns">
|
||||
<button class="button--outlined button--small button--colored" onclick="currentTask=this.closest('.task-list-item');openPopup('intern_list_popup')">
|
||||
<button class="button--outlined 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" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0-6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zM5 18c.2-.63 2.57-1.68 4.96-1.94l2.04-2c-.39-.04-.68-.06-1-.06-2.67 0-8 1.34-8 4v2h9l-2-2H5zm15.6-5.5l-5.13 5.17-2.07-2.08L12 17l3.47 3.5L22 13.91z"/></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">
|
||||
@ -1993,9 +1999,48 @@
|
||||
<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>
|
||||
${branchesButtons.length ? html`<div class="task__branch_container">${branchesButtons}</div>` : ''}
|
||||
</li>
|
||||
`;
|
||||
} else {
|
||||
return html`
|
||||
<li class=${`admin-task ${status}`} .dataset=${{ taskId: task }}>
|
||||
<div class="flex align-center gap-0-3 space-between">
|
||||
<button class="button button--small button--danger" onclick=${markTaskAsIncomplete}>
|
||||
<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"/><path d="M17,12c-2.76,0-5,2.24-5,5s2.24,5,5,5c2.76,0,5-2.24,5-5S19.76,12,17,12z M18.65,19.35l-2.15-2.15V14h1v2.79l1.85,1.85 L18.65,19.35z M18,3h-3.18C14.4,1.84,13.3,1,12,1S9.6,1.84,9.18,3H6C4.9,3,4,3.9,4,5v15c0,1.1,0.9,2,2,2h6.11 c-0.59-0.57-1.07-1.25-1.42-2H6V5h2v3h8V5h2v5.08c0.71,0.1,1.38,0.31,2,0.6V5C20,3.9,19.1,3,18,3z M12,5c-0.55,0-1-0.45-1-1 c0-0.55,0.45-1,1-1c0.55,0,1,0.45,1,1C13,4.55,12.55,5,12,5z"/></g></svg>
|
||||
Mark as incomplete
|
||||
</button>
|
||||
<span class="tag">Completed</span>
|
||||
</div>
|
||||
<h4 class="task-title capitalize">${title}</h4>
|
||||
<div class="assigned-interns">
|
||||
${assignedInternsCards}
|
||||
</div>
|
||||
<details>
|
||||
<summary>View details</summary>
|
||||
${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>
|
||||
</details>
|
||||
</li>
|
||||
`;
|
||||
}
|
||||
},
|
||||
taskRequestCard(request) {
|
||||
const { details: { taskId, name, brief, contact, portfolioLink }, floID, vectorClock } = request
|
||||
@ -2540,7 +2585,7 @@
|
||||
</p>`)
|
||||
}
|
||||
if (taskListContainer === 'task_list') {
|
||||
branchTasks.slice(4).forEach((task) => tasks.push(render.taskListItem(task, getRef(taskListContainer))))
|
||||
branchTasks.slice(4).forEach((task) => tasks.push(render.adminTask(task)))
|
||||
} else {
|
||||
branchTasks.slice(4).forEach((task) => tasks.push(render.taskCard(task)))
|
||||
}
|
||||
@ -2579,27 +2624,17 @@
|
||||
return '₹0';
|
||||
return amount.toLocaleString(currency === 'inr' ? `en-IN` : 'en-US', { style: 'currency', currency, maximumFractionDigits: 0 })
|
||||
}
|
||||
delegate(getRef('task_list'), 'mousedown', 'sm-checkbox', (e) => {
|
||||
e.preventDefault();
|
||||
currentTask = e.target.closest('.task-list-item');
|
||||
if (e.delegateTarget.checked) {
|
||||
getConfirmation('Mark this task as incomplete?', { confirmText: 'Mark as incomplete' }).then(res => {
|
||||
if (res) {
|
||||
RIBC.admin.putTaskStatus('incomplete', appState.params.id, appState.params.branch, currentTask.dataset.taskId)
|
||||
currentTask.querySelector('sm-checkbox').checked = false;
|
||||
// TODO: remove task scores from intern rating
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const assignedInterns = RIBC.getAssignedInterns(appState.params.id, appState.params.branch, currentTask.dataset.taskId);
|
||||
renderElem(getRef('rating_wrapper'), html`
|
||||
function initTaskScoring(e) {
|
||||
currentTask = e.target.closest('.admin-task');
|
||||
const assignedInterns = RIBC.getAssignedInterns(appState.params.id, appState.params.branch, currentTask.dataset.taskId);
|
||||
renderElem(getRef('rating_wrapper'), html`
|
||||
<h4>${currentTask.querySelector('.task-title').textContent}</h4>
|
||||
<sm-form>
|
||||
${assignedInterns.map((intern, index) => html`
|
||||
<div class="flex flex-direction-column gap-0-5 rating-part" data-intern-id=${intern}>
|
||||
<h4>${RIBC.getInternList()[intern]}</h4>
|
||||
<div class="flex gap-0-5">
|
||||
<sm-input type="number" min="0" max="50" class="flex-1" placeholder="Rate out of 50" error-text="Points must be between 0-50" required></sm-input>
|
||||
<sm-input type="number" min="0" max="50" class="flex-1" placeholder="Rate out of 50" error-text="Points must be between 0-50" autofocus required></sm-input>
|
||||
<input class="flex-1" type="date" value=${formatDate(new Date())} placeholder="Completion date" aria-label="Set date of completion" required>
|
||||
</div>
|
||||
</div>
|
||||
@ -2607,9 +2642,19 @@
|
||||
<button id="rate_participants_btn" class="button button--primary" type="submit" disabled onclick="rateParticipants()"> Rate </button>
|
||||
</sm-form>
|
||||
`)
|
||||
openPopup('rate_participants_popup')
|
||||
}
|
||||
})
|
||||
openPopup('rate_participants_popup')
|
||||
}
|
||||
function markTaskAsIncomplete(e) {
|
||||
currentTask = e.target.closest('.admin-task');
|
||||
getConfirmation('Mark this task as incomplete?', { message: 'Score given to participants regarding this task will also be removed', confirmText: 'Mark as incomplete' }).then(res => {
|
||||
if (res) {
|
||||
RIBC.admin.putTaskStatus('incomplete', appState.params.id, appState.params.branch, currentTask.dataset.taskId)
|
||||
// TODO: remove task scores from intern rating
|
||||
renderBranchTasks()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// format unix timestamp to yyyy-mm-dd
|
||||
function formatDate(unixTimestamp) {
|
||||
const date = new Date(unixTimestamp);
|
||||
@ -2623,6 +2668,7 @@
|
||||
// remove task from displayed list
|
||||
const taskId = `${appState.params.id}_${appState.params.branch}_${currentTask.dataset.taskId}`;
|
||||
const filteredTasks = RIBC.getDisplayedTasks().filter(task => task !== taskId)
|
||||
renderBranchTasks()
|
||||
}
|
||||
function rateParticipants() {
|
||||
document.querySelectorAll('.rating-part').forEach((ratingPart) => {
|
||||
@ -2634,10 +2680,9 @@
|
||||
})
|
||||
markTaskAsCompleted()
|
||||
closePopup()
|
||||
currentTask.querySelector('sm-checkbox').checked = true;
|
||||
}
|
||||
delegate(getRef('task_list'), 'change', 'sm-select', (e) => {
|
||||
currentTask = e.target.closest('.task-list-item');
|
||||
currentTask = e.target.closest('.admin-task');
|
||||
if (!currentTask) return;
|
||||
const taskDetails = {
|
||||
[e.target.dataset.editField]: e.target.value
|
||||
@ -2646,7 +2691,7 @@
|
||||
notify('Changes saved locally, commit the changes to make them permanent', 'success')
|
||||
})
|
||||
getRef('task_list').addEventListener('focusout', (e) => {
|
||||
currentTask = e.target.closest('.task-list-item');
|
||||
currentTask = e.target.closest('.admin-task');
|
||||
if (!currentTask) return;
|
||||
const ogTaskDetails = RIBC.getTaskDetails(appState.params.id, appState.params.branch, currentTask.dataset.taskId)
|
||||
const newTaskDetails = {}
|
||||
@ -2669,8 +2714,8 @@
|
||||
}
|
||||
})
|
||||
getRef('task_list').addEventListener('click', (e) => {
|
||||
if (e.target.closest('.task-list-item')) {
|
||||
currentTask = e.target.closest('.task-list-item');
|
||||
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')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user