Bug fixes
This commit is contained in:
parent
8138ddfb79
commit
0c85e55c20
File diff suppressed because one or more lines are too long
28
css/main.css
28
css/main.css
@ -178,6 +178,10 @@ button:not(:disabled),
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.cta {
|
||||
text-transform: uppercase;
|
||||
font-size: 0.8rem;
|
||||
@ -199,10 +203,6 @@ button:not(:disabled),
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
a:-webkit-any-link:focus-visible {
|
||||
outline: rgba(var(--text-color), 1) 0.1rem solid;
|
||||
}
|
||||
@ -707,17 +707,25 @@ ul {
|
||||
}
|
||||
|
||||
.popup__header {
|
||||
position: relative;
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
padding: 0 1.5rem 0 0.5rem;
|
||||
align-items: center;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
grid-template-columns: auto 1fr;
|
||||
}
|
||||
.popup__header > * {
|
||||
grid-row: 1;
|
||||
}
|
||||
.popup__header h3,
|
||||
.popup__header h4 {
|
||||
grid-column: 1/-1;
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.popup__header__close {
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.page {
|
||||
@ -1951,12 +1959,12 @@ input[type=date]:focus {
|
||||
#dashboard_page {
|
||||
grid-template-columns: 1fr 18rem;
|
||||
}
|
||||
#dashboard_page > :not(#best_interns_container, #dashboard_view_selector) {
|
||||
#dashboard_page > :not(#intern_leaderboard_container, #dashboard_view_selector) {
|
||||
grid-column: 1;
|
||||
width: min(48rem, 100%);
|
||||
margin: 0 auto;
|
||||
}
|
||||
#best_interns_container {
|
||||
#intern_leaderboard_container {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -170,6 +170,9 @@ button,
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.cta {
|
||||
text-transform: uppercase;
|
||||
@ -192,10 +195,6 @@ button,
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
a:any-link:focus-visible {
|
||||
outline: rgba(var(--text-color), 1) 0.1rem solid;
|
||||
}
|
||||
@ -698,17 +697,25 @@ ul {
|
||||
}
|
||||
|
||||
.popup__header {
|
||||
position: relative;
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
padding: 0 1.5rem 0 0.5rem;
|
||||
align-items: center;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
|
||||
.popup__header__close {
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
grid-template-columns: auto 1fr;
|
||||
& > * {
|
||||
grid-row: 1;
|
||||
}
|
||||
h3,
|
||||
h4 {
|
||||
grid-column: 1/-1;
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
}
|
||||
&__close {
|
||||
grid-column: 1;
|
||||
}
|
||||
}
|
||||
.page {
|
||||
height: 100%;
|
||||
@ -1942,13 +1949,13 @@ input[type="date"] {
|
||||
|
||||
#dashboard_page {
|
||||
grid-template-columns: 1fr 18rem;
|
||||
& > :not(#best_interns_container, #dashboard_view_selector) {
|
||||
& > :not(#intern_leaderboard_container, #dashboard_view_selector) {
|
||||
grid-column: 1;
|
||||
width: min(48rem, 100%);
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
#best_interns_container {
|
||||
#intern_leaderboard_container {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
grid-column: 2;
|
||||
|
||||
392
index.html
392
index.html
@ -265,8 +265,8 @@
|
||||
Applications
|
||||
</span>
|
||||
</a>
|
||||
<a href="#/admin_page" class="admin-option nav-list__item interact open-first-project"
|
||||
title="open admin panel">
|
||||
<a id="admin_page_nav_button" href="#/admin_page"
|
||||
class="admin-option nav-list__item interact open-first-project" title="open admin panel">
|
||||
<svg class="icon icon--outlined" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24"
|
||||
height="24">
|
||||
<path fill="none" d="M0 0h24v24H0z" />
|
||||
@ -342,8 +342,8 @@
|
||||
<section id="project_editing_panel" class="hidden">
|
||||
<div id="project_details_wrapper"
|
||||
class="flex flex-direction-column gap-1 margin-bottom-2 align-items-start">
|
||||
<a class="flex gap-0-3 align-center button--colored hide-on-desktop" href="#/admin_page"
|
||||
title="Go back">
|
||||
<a class="flex gap-0-3 align-center button--colored hide-on-desktop"
|
||||
href="#/admin_page/projects" title="Go back">
|
||||
<svg class="icon" style="margin-left: -0.3rem;" xmlns="http://www.w3.org/2000/svg"
|
||||
height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
@ -549,36 +549,7 @@
|
||||
<h4 class="empty-state">No tasks are added to this projects</h4>
|
||||
</section>
|
||||
</section>
|
||||
<section id="settings_page" class="inner-page hidden">
|
||||
<section class="grid gap-1 card">
|
||||
<div class="grid">
|
||||
<h4>FLO address</h4>
|
||||
<sm-copy id="user_flo_id"></sm-copy>
|
||||
</div>
|
||||
<button id="logout" class="justify-self-start button button--danger" onclick="signOut()">
|
||||
<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="M4 18h2v2h12V4H6v2H4V3a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-3zm2-7h7v2H6v3l-5-4 5-4v3z" />
|
||||
</svg>
|
||||
Sign out
|
||||
</button>
|
||||
</section>
|
||||
<div class="grid gap-1 card">
|
||||
<div class="grid gap-0-5">
|
||||
<h4>Secure private key</h4>
|
||||
<p>
|
||||
You can set a password to secure your private key and use the password instead of private
|
||||
key.
|
||||
This is applied to this browser only.
|
||||
</p>
|
||||
</div>
|
||||
<button id="secure_pwd_button" class="button button--primary justify-self-start secure-priv-key"
|
||||
onclick="openPopup('secure_pwd_popup')">Set
|
||||
password</button>
|
||||
</div>
|
||||
</section>
|
||||
<section id="settings_page" class="inner-page hidden"></section>
|
||||
</article>
|
||||
</main>
|
||||
</main>
|
||||
@ -1147,8 +1118,8 @@
|
||||
switch (pageId) {
|
||||
case 'landing':
|
||||
renderElem(getRef('landing_tasks_wrapper'), render.displayTasks(params?.category, params?.search))
|
||||
if (subPageId1) {
|
||||
showTaskDetails(params.id)
|
||||
if (params?.taskId) {
|
||||
showTaskDetails(params.taskId)
|
||||
} else {
|
||||
hideTaskDetails()
|
||||
}
|
||||
@ -1168,12 +1139,16 @@
|
||||
renderedAssignedTasks = html`No task assigned yet.`;
|
||||
}
|
||||
}
|
||||
//creates cards for highest performing interns
|
||||
//sort interns earned points
|
||||
const highPerformingInterns = Object.keys(RIBC.getInternList()).sort((a, b) => RIBC.getInternRating(b) - RIBC.getInternRating(a));
|
||||
const routedToAllTasks = (subPageId1 && subPageId1 === 'all_tasks') || (!subPageId1 && typeOfUser !== 'intern');
|
||||
renderElem(getRef('dashboard_page'), html`
|
||||
<strip-select id="dashboard_view_selector" class="margin-right-auto" onchange=${handleDashboardViewChange}>
|
||||
${typeOfUser === 'intern' ? html`<strip-option value="intern_view" selected>My tasks</strip-option>` : ''}
|
||||
<strip-option value="dashboard_tasks_wrapper" ?selected=${typeOfUser !== 'intern'}>All tasks</strip-option>
|
||||
<strip-option value="projects_wrapper">Projects</strip-option>
|
||||
${floGlobals.isMobileView ? html`<strip-option value="best_interns_container">Leaderboard</strip-option>` : ''}
|
||||
<strip-option value="dashboard_tasks_wrapper" ?selected=${routedToAllTasks}>All tasks</strip-option>
|
||||
<strip-option value="projects_wrapper" ?selected=${subPageId1 === 'projects'}>Projects</strip-option>
|
||||
${floGlobals.isMobileView ? html`<strip-option value="intern_leaderboard_container">Leaderboard</strip-option>` : ''}
|
||||
</strip-select>
|
||||
${typeOfUser === 'intern' ? html`
|
||||
<section id="intern_view" class="intern-option dashboard-view__item">
|
||||
@ -1181,60 +1156,25 @@
|
||||
</section>
|
||||
` : ''}
|
||||
<div id="dashboard_tasks_wrapper" class=${`flex flex-direction-column justify-center dashboard-view__item ${typeOfUser === 'intern' ? 'hidden' : ''}`}>${render.displayTasks(params?.category, params?.search)}</div>
|
||||
<div id="projects_wrapper" class="grid gap-2 align-items-start dashboard-view__item hidden">
|
||||
<section id="pinned_project_section" class="w-100">
|
||||
<h4>Pinned</h4>
|
||||
<div id="pinned_projects" class="observe-empty-state"></div>
|
||||
<div class="empty-state">
|
||||
<h4>There are no pinned projects</h4>
|
||||
<p class="margin-block-0-5">
|
||||
You can pin projects for easier monitoring by clicking on the 'pin' icon on project card.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<div id="project_list_container" class=${`hidden`}>
|
||||
<div class="flex align-center space-between margin-bottom-0-5">
|
||||
<h4>Projects</h4>
|
||||
<a href="#/project_explorer" class="button open-first-project">All</a>
|
||||
</div>
|
||||
<div id="project_list" class="flex flex-direction-column gap-0-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="best_interns_container" class="container-card dashboard-view__item hide-on-mobile">
|
||||
<div id="projects_wrapper" class="grid gap-2 align-items-start dashboard-view__item hidden"></div>
|
||||
<div id="intern_leaderboard_container" class="container-card dashboard-view__item hide-on-mobile">
|
||||
<div class="container-header">
|
||||
<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 7a8 8 0 1 1 0 16 8 8 0 0 1 0-16zm0 3.5l-1.323 2.68-2.957.43 2.14 2.085-.505 2.946L12 17.25l2.645 1.39-.505-2.945 2.14-2.086-2.957-.43L12 10.5zm1-8.501L18 2v3l-1.363 1.138A9.935 9.935 0 0 0 13 5.049L13 2zm-2 0v3.05a9.935 9.935 0 0 0-3.636 1.088L6 5V2l5-.001z" /> </svg>
|
||||
<h4>Leaderboard</h4>
|
||||
<a id="all_interns_btn" href="#/all_interns_page" class="button">All</a>
|
||||
</div>
|
||||
<div id="top_interns" class="observe-empty-state"></div>
|
||||
<div id="top_interns" class="observe-empty-state">${highPerformingInterns.slice(0, 8).map(floId => render.internCard(floId))}</div>
|
||||
<div class="empty-state">
|
||||
<h4>There are no interns</h4>
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
render.dashProjects(getRef('pinned_projects'), pinnedProjects);
|
||||
// displays recent projects
|
||||
const unpinnedProjects = RIBC.getProjectList().filter(project => !pinnedProjects.includes(project)).reverse()
|
||||
if (unpinnedProjects.length > 0) {
|
||||
getRef('project_list_container').classList.remove('hidden')
|
||||
} else {
|
||||
getRef('project_list_container').classList.add('hidden')
|
||||
renderElem(getRef('projects_wrapper'), render.dashProjects())
|
||||
if (params?.taskId) {
|
||||
showTaskDetails(params.taskId)
|
||||
}
|
||||
render.dashProjects(getRef('project_list'), unpinnedProjects)
|
||||
delegate(getRef('top_interns'), 'click', '.intern-card', e => {
|
||||
showInternInfo(e.delegateTarget.dataset.internFloId)
|
||||
})
|
||||
//creates cards for highest performing interns
|
||||
//sort interns earned points
|
||||
const highPerformingInterns = Object.keys(RIBC.getInternList()).sort((a, b) => {
|
||||
return RIBC.getInternRating(b) - RIBC.getInternRating(a)
|
||||
});
|
||||
renderElem(getRef('top_interns'), html`${highPerformingInterns.slice(0, 8).map(floId => render.internCard(floId))}`);
|
||||
if (subPageId1) {
|
||||
showTaskDetails(params.id)
|
||||
} else {
|
||||
else
|
||||
hideTaskDetails()
|
||||
}
|
||||
break;
|
||||
case 'updates_page': {
|
||||
if (!getRef('updates_page__project_selector').children.length) {
|
||||
@ -1262,8 +1202,8 @@
|
||||
} break;
|
||||
case 'applications':
|
||||
render.taskApplications()
|
||||
if (subPageId1) {
|
||||
showTaskDetails(params.id)
|
||||
if (params?.taskId) {
|
||||
showTaskDetails(params.taskId)
|
||||
} else {
|
||||
hideTaskDetails()
|
||||
}
|
||||
@ -1300,91 +1240,103 @@
|
||||
case 'admin_page':
|
||||
if (typeOfUser !== 'admin') return;
|
||||
//show projects
|
||||
render.projectList(getRef('admin_page__project_list'), getSortedProjectList(), true)
|
||||
if (subPageId1) {
|
||||
if (params && RIBC.getProjectList().includes(params.id)) {
|
||||
const { id: projectCode, branch } = params
|
||||
renderAdminProjectView(projectCode)
|
||||
if (branch) {
|
||||
renderBranchTasks()
|
||||
}
|
||||
getRef('projects_container__left').classList.add('hide-on-mobile')
|
||||
getRef('project_editing_panel').classList.remove('hidden')
|
||||
}
|
||||
} else {
|
||||
getRef('projects_container__left').classList.remove('hide-on-mobile')
|
||||
getRef('project_editing_panel').classList.add('hidden')
|
||||
history.replaceState(null, '', '#/admin_page')
|
||||
}
|
||||
function removeRequest(requestCard) {
|
||||
requestCard.animate([
|
||||
{
|
||||
transform: 'translateX(0)',
|
||||
opacity: 1
|
||||
},
|
||||
{
|
||||
transform: 'translateX(-100%)',
|
||||
opacity: 0
|
||||
},
|
||||
], {
|
||||
duration: floGlobals.prefersReducedMotion ? 0 : 300,
|
||||
easing: 'ease'
|
||||
}).onfinish = () => {
|
||||
requestCard.remove()
|
||||
}
|
||||
}
|
||||
render.internRequests()
|
||||
// accept task request
|
||||
delegate(getRef('requests_list'), 'click', '.accept-request', (e) => {
|
||||
getConfirmation('Are you sure you want to accept this request?').then(result => {
|
||||
if (result) {
|
||||
const vectorClock = e.delegateTarget.closest('.request-card').dataset.vectorClock
|
||||
let result
|
||||
if (RIBC.getInternList())
|
||||
result = RIBC.admin.processTaskRequest(vectorClock, true)
|
||||
if (result === 'Accepted') {
|
||||
notify('Intern assigned, commit changes to make it permanent.', 'success')
|
||||
removeRequest(e.delegateTarget.closest('.request-card'))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
// reject task request
|
||||
delegate(getRef('requests_list'), 'click', '.reject-request', (e) => {
|
||||
getConfirmation('Are you sure you want to reject this request?').then((result) => {
|
||||
if (result) {
|
||||
const vectorClock = e.delegateTarget.closest('.request-card').dataset.vectorClock
|
||||
const type = e.delegateTarget.closest('.request-card').dataset.type
|
||||
let result
|
||||
if (type === 'task') {
|
||||
result = RIBC.admin.processTaskRequest(vectorClock, false)
|
||||
if (result === 'Rejected') {
|
||||
notify('Request rejected', 'success')
|
||||
removeRequest(e.delegateTarget.closest('.request-card'))
|
||||
getRef('admin_view_selector').value = ['projects', 'interns', 'task_display', 'requests'].findIndex(page => page === subPageId1)
|
||||
switch (subPageId1) {
|
||||
case 'projects':
|
||||
render.projectList(getRef('admin_page__project_list'), getSortedProjectList(), true)
|
||||
if (params && RIBC.getProjectList().includes(params.id)) {
|
||||
const { id: projectCode, branch } = params
|
||||
renderAdminProjectView(projectCode)
|
||||
if (branch) {
|
||||
renderBranchTasks()
|
||||
}
|
||||
} else if (type === 'internship') {
|
||||
result = RIBC.admin.processInternRequest(vectorClock, false)
|
||||
if (result === 'Rejected') {
|
||||
notify('Request rejected', 'success')
|
||||
removeRequest(e.delegateTarget.closest('.request-card'))
|
||||
getRef('projects_container__left').classList.add('hide-on-mobile')
|
||||
getRef('project_editing_panel').classList.remove('hidden')
|
||||
} else {
|
||||
getRef('projects_container__left').classList.remove('hide-on-mobile')
|
||||
getRef('project_editing_panel').classList.add('hidden')
|
||||
history.replaceState(null, '', '#/admin_page/projects')
|
||||
}
|
||||
break;
|
||||
case 'interns':
|
||||
//show interns
|
||||
renderElem(getRef('admin_page__intern_list'), filterInterns(''))
|
||||
break;
|
||||
case 'requests':
|
||||
function removeRequest(requestCard) {
|
||||
requestCard.animate([
|
||||
{
|
||||
transform: 'translateX(0)',
|
||||
opacity: 1
|
||||
},
|
||||
{
|
||||
transform: 'translateX(-100%)',
|
||||
opacity: 0
|
||||
},
|
||||
], {
|
||||
duration: floGlobals.prefersReducedMotion ? 0 : 150,
|
||||
easing: 'ease'
|
||||
}).onfinish = () => {
|
||||
requestCard.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
//show interns
|
||||
renderElem(getRef('admin_page__intern_list'), filterInterns(''))
|
||||
|
||||
//show display tasks map
|
||||
render.taskDisplayMap()
|
||||
if (dragger)
|
||||
dragger.destroy()
|
||||
dragger = dragula([getRef('display_task_map'), getRef('all_tasks')])
|
||||
dragger.on('dragend', function (el, source) {
|
||||
const newOrder = Array.from(getRef('display_task_map').children).map(el => el.dataset.taskId)
|
||||
RIBC.admin.setDisplayedTasks(newOrder)
|
||||
});
|
||||
render.internRequests()
|
||||
// accept task request
|
||||
delegate(getRef('requests_list'), 'click', '.accept-request', (e) => {
|
||||
getConfirmation('Are you sure you want to accept this request?').then(result => {
|
||||
if (result) {
|
||||
const vectorClock = e.delegateTarget.closest('.request-card').dataset.vectorClock
|
||||
let result
|
||||
if (RIBC.getInternList())
|
||||
result = RIBC.admin.processTaskRequest(vectorClock, true)
|
||||
if (result === 'Accepted') {
|
||||
notify('Intern assigned, commit changes to make it permanent.', 'success')
|
||||
removeRequest(e.delegateTarget.closest('.request-card'))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
// reject task request
|
||||
delegate(getRef('requests_list'), 'click', '.reject-request', (e) => {
|
||||
getConfirmation('Are you sure you want to reject this request?').then((result) => {
|
||||
if (result) {
|
||||
const vectorClock = e.delegateTarget.closest('.request-card').dataset.vectorClock
|
||||
const type = e.delegateTarget.closest('.request-card').dataset.type
|
||||
let result
|
||||
if (type === 'task') {
|
||||
result = RIBC.admin.processTaskRequest(vectorClock, false)
|
||||
if (result === 'Rejected') {
|
||||
notify('Request rejected', 'success')
|
||||
removeRequest(e.delegateTarget.closest('.request-card'))
|
||||
}
|
||||
} else if (type === 'internship') {
|
||||
result = RIBC.admin.processInternRequest(vectorClock, false)
|
||||
if (result === 'Rejected') {
|
||||
notify('Request rejected', 'success')
|
||||
removeRequest(e.delegateTarget.closest('.request-card'))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
break;
|
||||
case 'task_display':
|
||||
//show display tasks map
|
||||
render.taskDisplayMap()
|
||||
if (dragger)
|
||||
dragger.destroy()
|
||||
dragger = dragula([getRef('display_task_map'), getRef('all_tasks')])
|
||||
dragger.on('dragend', function (el, source) {
|
||||
const newOrder = Array.from(getRef('display_task_map').children).map(el => el.dataset.taskId)
|
||||
RIBC.admin.setDisplayedTasks(newOrder)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'settings_page':
|
||||
renderElem(getRef('settings_page'), render.settings())
|
||||
break;
|
||||
}
|
||||
switch (appState.lastPage) {
|
||||
@ -1412,18 +1364,24 @@
|
||||
let ogOverflow = getRef(pageId).parentNode.style.overflow
|
||||
getRef(pageId).parentNode.style.overflow = 'hidden';
|
||||
if (appState.lastPage) {
|
||||
getRef(appState.lastPage).animate(routingAnimation.out, { duration: floGlobals.prefersReducedMotion ? 0 : 300, fill: 'forwards', easing: 'ease' }).onfinish = (e) => {
|
||||
getRef(appState.lastPage).animate(routingAnimation.out, { duration: floGlobals.prefersReducedMotion ? 0 : 150, fill: 'forwards', easing: 'ease' }).onfinish = (e) => {
|
||||
e.target.effect.target.classList.add('hidden')
|
||||
}
|
||||
}
|
||||
getRef(pageId).classList.remove('hidden')
|
||||
getRef(pageId).animate(routingAnimation.in, { duration: floGlobals.prefersReducedMotion ? 0 : 300, fill: 'forwards', easing: 'ease' }).onfinish = (e) => {
|
||||
getRef(pageId).animate(routingAnimation.in, { duration: floGlobals.prefersReducedMotion ? 0 : 150, fill: 'forwards', easing: 'ease' }).onfinish = (e) => {
|
||||
getRef(pageId).parentNode.style.overflow = ogOverflow;
|
||||
switch (pageId) {
|
||||
case 'sign_in':
|
||||
getRef('private_key_field').focusIn()
|
||||
break;
|
||||
}
|
||||
if (pageId !== 'dashboard_page') {
|
||||
renderElem(getRef('dashboard_page'), html``)
|
||||
}
|
||||
if (pageId !== 'settings_page') {
|
||||
renderElem(getRef('settings_page'), html``)
|
||||
}
|
||||
}
|
||||
appState.lastPage = pageId
|
||||
}
|
||||
@ -1738,12 +1696,12 @@
|
||||
<li class=${`display-task`}>
|
||||
<div class="flex align-center space-between">
|
||||
<a class="display-task__category" href=${`#/landing?category=${category}`} title=${`See all ${floGlobals.taskCategories[category]} tasks`}>${floGlobals.taskCategories[category]}</a>
|
||||
<a href=${`#/${appState.currentPage}/task?id=${projectCode}_${branch}_${task}`} class="display-task__link button button--small button--colored">
|
||||
<a href=${`${location.hash.split('?')[0]}?taskId=${projectCode}_${branch}_${task}`} class="display-task__link button button--small button--colored">
|
||||
View details
|
||||
<svg class="icon" style="margin-right: -0.5rem" 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="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6-6-6z"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<a href=${`#/${appState.currentPage}/task?id=${projectCode}_${branch}_${task}`} class="display-task__link flex flex-direction-column gap-1">
|
||||
<a href=${`${location.hash.split('?')[0]}?taskId=${projectCode}_${branch}_${task}`} class="display-task__link flex flex-direction-column gap-1">
|
||||
<h4 class="display-task__title">${title}</h4>
|
||||
<div class="display-task__details flex flex-wrap gap-0-3">
|
||||
${duration ? html`
|
||||
@ -1828,7 +1786,8 @@
|
||||
projectCard(projectCode, isAdmin = false, ref) {
|
||||
const projectName = RIBC.getProjectDetails(projectCode).projectName
|
||||
const page = isAdmin ? 'admin_page' : 'project_explorer'
|
||||
return html.for(ref, projectCode)`<a class="project-card flex align-center interact" title="Project information" href=${`#/${page}/project?id=${projectCode}&branch=mainLine`}>${projectName}</a>`
|
||||
const projectLink = isAdmin ? `#/${page}/projects?id=${projectCode}&branch=mainLine` : `#/${page}/project?id=${projectCode}&branch=mainLine`
|
||||
return html.for(ref, projectCode)`<a class="project-card flex align-center interact" title="Project information" href=${projectLink}>${projectName}</a>`
|
||||
},
|
||||
taskCard(task) {
|
||||
const { title, description, category, maxSlots, duration, durationType, reward } = RIBC.getTaskDetails(appState.params.id, appState.params.branch, task)
|
||||
@ -1907,7 +1866,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 }} title="Intern Information">
|
||||
<label class="intern-card align-center interact" .dataset=${{ internFloId }} onclick=${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>
|
||||
@ -2116,7 +2075,7 @@
|
||||
</li>
|
||||
`;
|
||||
},
|
||||
dashProject(projectCode, ref) {
|
||||
dashProject(projectCode) {
|
||||
const { projectName } = RIBC.getProjectDetails(projectCode)
|
||||
const projectMap = RIBC.getProjectMap(projectCode)
|
||||
const projectTasks = []
|
||||
@ -2134,7 +2093,7 @@
|
||||
} else {
|
||||
pinIcon = html`<svg class="icon" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M16 12V4H17V2H7V4H8V12L6 14V16H11.2V22H12.8V16H18V14L16 12ZM8.8 14L10 12.8V4H14V12.8L15.2 14H8.8Z"/> </svg>`;
|
||||
}
|
||||
return html.for(ref, projectCode)`
|
||||
return html`
|
||||
<div class="pinned-card" data-id=${projectCode}>
|
||||
<div class="project-icon">
|
||||
<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.414 5H21a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h7.414l2 2zM4 7v12h16V7H4z" /> </svg>
|
||||
@ -2153,8 +2112,30 @@
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
dashProjects(where, projects) {
|
||||
renderElem(where, html`${projects.map(project => render.dashProject(project, where))} `)
|
||||
dashProjects() {
|
||||
const unpinnedProjects = RIBC.getProjectList().filter(project => !pinnedProjects.includes(project)).reverse().map(project => render.dashProject(project))
|
||||
const renderedPinned = pinnedProjects.map(project => render.dashProject(project))
|
||||
return html`
|
||||
<section id="pinned_project_section" class="w-100">
|
||||
<h4>Pinned</h4>
|
||||
<div id="pinned_projects" class="observe-empty-state">${renderedPinned}</div>
|
||||
<div class="empty-state">
|
||||
<h4>There are no pinned projects</h4>
|
||||
<p class="margin-block-0-5">
|
||||
You can pin projects for easier monitoring by clicking on the 'pin' icon on project card.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
${unpinnedProjects.length ? html`
|
||||
<div id="project_list_container">
|
||||
<div class="flex align-center space-between margin-bottom-0-5">
|
||||
<h4>Projects</h4>
|
||||
<a href="#/project_explorer" class="button open-first-project">All</a>
|
||||
</div>
|
||||
<div id="project_list" class="flex flex-direction-column gap-0-3">${unpinnedProjects}</div>
|
||||
</div>
|
||||
`: ''}
|
||||
`;
|
||||
},
|
||||
internRequests() {
|
||||
const requestCategories = new Set()
|
||||
@ -2208,7 +2189,7 @@
|
||||
<li class=${`status-card ${status?.toLowerCase() || 'pending'}`}>
|
||||
<time class="status-card__time capitalize">${getFormattedTime(timestamp, 'relative')}</time>
|
||||
<p class="status-card__details">
|
||||
You applied for <a class="capitalize" href=${`#/${appState.currentPage}/task?id=${taskId}`}>${RIBC.getTaskDetails(projectCode, branch, task).title}</a>
|
||||
You applied for <a class="capitalize" href=${`${location.hash.split('?')[0]}?taskId=${taskId}`}>${RIBC.getTaskDetails(projectCode, branch, task).title}</a>
|
||||
</p>
|
||||
<div class="flex align-center status-card__status">
|
||||
${icon}
|
||||
@ -2250,6 +2231,29 @@
|
||||
<h4>${RIBC.getTaskDetails(projectCode, branch, task).title}</h4>
|
||||
</li>
|
||||
`;
|
||||
},
|
||||
settings() {
|
||||
return html`
|
||||
<section class="grid gap-1 card">
|
||||
<div class="grid">
|
||||
<h4>FLO address</h4>
|
||||
<sm-copy id="user_flo_id" value=${myFloID}></sm-copy>
|
||||
</div>
|
||||
<button id="logout" class="justify-self-start button button--danger" onclick="signOut()">
|
||||
<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="M4 18h2v2h12V4H6v2H4V3a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-3zm2-7h7v2H6v3l-5-4 5-4v3z" /> </svg>
|
||||
Sign out
|
||||
</button>
|
||||
</section>
|
||||
<div class="grid gap-1 card">
|
||||
<div class="grid gap-0-5">
|
||||
<h4>Secure private key</h4>
|
||||
<p>
|
||||
You can set a password to secure your private key and use the password instead of private key. This is applied to this browser only.
|
||||
</p>
|
||||
</div>
|
||||
<button id="secure_pwd_button" class=${`button button--primary justify-self-start secure-priv-key ${floGlobals.isPrivKeySecured ? 'hidden' : ''}`} onclick="openPopup('secure_pwd_popup')">Set password</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
const selectedColors = [
|
||||
@ -2360,7 +2364,7 @@
|
||||
}
|
||||
function hideTaskDetails() {
|
||||
if (getRef('task_details').classList.contains('hidden')) return;
|
||||
history.replaceState(null, null, `#/${appState.currentPage}`);
|
||||
history.replaceState(null, null, location.hash.split('?')[0]);
|
||||
const animOptions = {
|
||||
duration: floGlobals.prefersReducedMotion ? 0 : 300,
|
||||
easing: 'ease',
|
||||
@ -2391,12 +2395,18 @@
|
||||
|
||||
function handleDashboardViewChange(e) {
|
||||
document.querySelectorAll('.dashboard-view__item').forEach(item => {
|
||||
if (item.id === 'best_interns_container')
|
||||
if (item.id === 'intern_leaderboard_container')
|
||||
item.classList.add('hide-on-mobile')
|
||||
else
|
||||
item.classList.add('hidden')
|
||||
})
|
||||
document.querySelector(`#${e.target.value}`).classList.remove('hide-on-mobile', 'hidden')
|
||||
const dashboardPages = {
|
||||
'intern_view': 'my_tasks',
|
||||
'dashboard_tasks_wrapper': 'all_tasks',
|
||||
'projects_wrapper': 'projects'
|
||||
}
|
||||
location.hash = `#/${appState.currentPage}/${dashboardPages[e.target.value]}`
|
||||
}
|
||||
|
||||
|
||||
@ -2455,7 +2465,8 @@
|
||||
})
|
||||
|
||||
// opens a popup containing various intern information
|
||||
function showInternInfo(internFloId) {
|
||||
function showInternInfo(e) {
|
||||
const internFloId = e.target.closest('.intern-card').dataset.internFloId;
|
||||
const internName = RIBC.getInternList()[internFloId]
|
||||
getRef('intern_info__initials').textContent = internName.split(' ').map(v => v.charAt(0)).join('');
|
||||
getRef('intern_info__initials').style.setProperty('--color', `var(${getInternColor(internFloId)})`)
|
||||
@ -2543,6 +2554,9 @@
|
||||
const newViewIndex = parseInt(e.target.value);
|
||||
showChildElement(getRef('admin_views'), newViewIndex, { entry: newViewIndex > currentViewIndex ? slideInLeft : slideInRight, exit: newViewIndex > currentViewIndex ? slideOutLeft : slideOutRight });
|
||||
currentViewIndex = parseInt(e.target.value);
|
||||
const viewIds = ['projects', 'interns', 'task_display', 'requests']
|
||||
location.hash = `#/${appState.currentPage}/${viewIds[e.target.value]}`
|
||||
getRef('admin_page_nav_button').href = `#/${appState.currentPage}/${viewIds[e.target.value]}`
|
||||
})
|
||||
|
||||
function toggleEditing(target) {
|
||||
@ -2947,14 +2961,7 @@
|
||||
pinnedProjects.push(projectCode)
|
||||
}
|
||||
localStorage.setItem(`${myFloID}_pinned_projects`, pinnedProjects.join())
|
||||
render.dashProjects(getRef('pinned_projects'), pinnedProjects)
|
||||
const unpinnedProjects = RIBC.getProjectList().filter(project => !pinnedProjects.includes(project)).reverse()
|
||||
if (unpinnedProjects.length > 0) {
|
||||
getRef('project_list_container').classList.remove('hidden')
|
||||
} else {
|
||||
getRef('project_list_container').classList.add('hidden')
|
||||
}
|
||||
render.dashProjects(getRef('project_list'), unpinnedProjects)
|
||||
renderElem(getRef('projects_wrapper'), render.dashProjects())
|
||||
}
|
||||
|
||||
let sessionTaskRequests = new Set();
|
||||
@ -3012,13 +3019,6 @@
|
||||
function toggleUpdatesFilter() {
|
||||
getRef('update_filters_wrapper').classList.toggle('hide-on-mobile')
|
||||
}
|
||||
// Event listeners
|
||||
delegate(getRef('all_interns_page'), 'click', '.intern-card', e => {
|
||||
showInternInfo(e.delegateTarget.dataset.internFloId)
|
||||
})
|
||||
delegate(getRef('admin_page__intern_list'), 'click', '.intern-card', e => {
|
||||
showInternInfo(e.delegateTarget.dataset.internFloId)
|
||||
})
|
||||
|
||||
document.addEventListener('popupopened', e => {
|
||||
getRef('main_page').setAttribute('inert', '')
|
||||
@ -3048,7 +3048,8 @@
|
||||
|
||||
let sortedProjectList = getSortedProjectList()
|
||||
document.querySelectorAll('.open-first-project').forEach(link => {
|
||||
link.href = `${link.href}/project?id=${sortedProjectList[0]}&branch=mainLine`
|
||||
const adminPage = link.id === 'admin_page_nav_button'
|
||||
link.href = adminPage ? `${link.href}/projects?id=${sortedProjectList[0]}&branch=mainLine` : `${link.href}/project?id=${sortedProjectList[0]}&branch=mainLine`
|
||||
})
|
||||
|
||||
pinnedProjects = localStorage.getItem(`${myFloID}_pinned_projects`) ? localStorage.getItem(`${myFloID}_pinned_projects`).split(',') : []
|
||||
@ -3125,7 +3126,6 @@
|
||||
delegate(getRef('explorer_task_list'), 'click', '.apply-button', e => {
|
||||
requestForTask(e.delegateTarget)
|
||||
})
|
||||
getRef('user_flo_id').value = myFloID;
|
||||
}
|
||||
|
||||
let currentTaskId;
|
||||
@ -3245,13 +3245,11 @@
|
||||
getRef('private_key_field').removeAttribute('data-private-key');
|
||||
getRef('private_key_field').setAttribute('placeholder', 'Password');
|
||||
getRef('private_key_field').customValidation = null
|
||||
getRef('secure_pwd_button').closest('.card').classList.add('hidden');
|
||||
} else {
|
||||
floGlobals.isPrivKeySecured = false;
|
||||
getRef('private_key_field').dataset.privateKey = ''
|
||||
getRef('private_key_field').setAttribute('placeholder', 'FLO private key');
|
||||
getRef('private_key_field').customValidation = floCrypto.getPubKeyHex;
|
||||
getRef('secure_pwd_button').closest('.card').classList.remove('hidden');
|
||||
}
|
||||
if (!generalPages.find(page => window.location.hash.includes(page))) {
|
||||
location.hash = floGlobals.isPrivKeySecured ? '#/sign_in' : `#/landing`;
|
||||
|
||||
@ -105,7 +105,7 @@
|
||||
Ribc.getInternRating = (floID) => _.internRating[floID];
|
||||
Ribc.getAssignedInterns = (projectCode, branch, taskNumber) => _.internsAssigned[projectCode + "_" + branch + "_" + taskNumber]
|
||||
Ribc.getAllTasks = () => _.projectTaskDetails
|
||||
Ribc.getDisplayedTasks = () => floGlobals.appObjects.RIBC.displayedTasks.filter(v => v)
|
||||
Ribc.getDisplayedTasks = () => floGlobals.appObjects.RIBC.displayedTasks.filter(v => v) || [];
|
||||
|
||||
Admin.updateObjects = () => new Promise((resolve, reject) => {
|
||||
floCloudAPI.updateObjectData("RIBC")
|
||||
@ -168,6 +168,18 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
Admin.removeIntern = function (floID) {
|
||||
if (!(floID in _.internList))
|
||||
return false
|
||||
delete _.internList[floID]
|
||||
delete _.internRating[floID]
|
||||
for (const taskId in _.projectTaskDetails) {
|
||||
if (_.internsAssigned[taskId].includes(floID))
|
||||
_.internsAssigned[taskId] = _.internsAssigned[taskId].filter(id => id != floID)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Admin.updateInternRating = function (floID, change = 0) {
|
||||
if (!(floID in _.internList))
|
||||
return "Intern not found!"
|
||||
|
||||
2
scripts/ribc.min.js
vendored
2
scripts/ribc.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user