Added lazy loading to intern updates

This commit is contained in:
sairaj mote 2021-07-27 16:09:15 +05:30
parent 9d9d6b5373
commit c321106d6f
5 changed files with 172 additions and 196 deletions

View File

@ -3548,8 +3548,20 @@ customElements.define('sm-select', class extends HTMLElement {
this.setAttribute('value', val)
}
reset() {
reset(fire = true) {
if (this.availableOptions[0]) {
const firstElement = this.availableOptions[0];
if (this.previousOption) {
this.previousOption.classList.remove('check-selected')
}
firstElement.classList.add('check-selected')
this.value = firstElement.getAttribute('value')
this.selectedOptionText.textContent = firstElement.textContent
this.previousOption = firstElement;
if (fire) {
this.fireEvent()
}
}
}
open() {
@ -3657,16 +3669,7 @@ customElements.define('sm-select', class extends HTMLElement {
let slot = this.shadowRoot.querySelector('slot')
slot.addEventListener('slotchange', e => {
this.availableOptions = slot.assignedElements()
if (this.availableOptions[0]) {
let firstElement = this.availableOptions[0];
this.previousOption = firstElement;
firstElement.classList.add('check-selected')
this.value = firstElement.getAttribute('value')
this.selectedOptionText.textContent = firstElement.textContent
this.availableOptions.forEach((element) => {
element.setAttribute('tabindex', "0");
})
}
this.reset(false)
});
this.addEventListener('click', this.handleClick)
this.addEventListener('keydown', this.handleKeydown)
@ -3704,13 +3707,13 @@ smOption.innerHTML = `
display: flex;
}
.option{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
display: grid;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
min-width: 100%;
gap: 0.5rem;
grid-template-columns: max-content minmax(0, 1fr);
padding: 0.8rem 1.2rem;
cursor: pointer;
overflow-wrap: break-word;
@ -3725,7 +3728,6 @@ smOption.innerHTML = `
opacity: 0;
height: 1.2rem;
width: 1.2rem;
margin-right: 0.5rem;
fill: rgba(var(--text-color), 0.8);
}
:host(:focus) .option .icon{
@ -3757,5 +3759,6 @@ customElements.define('sm-option', class extends HTMLElement {
connectedCallback() {
this.setAttribute('role', 'option')
this.setAttribute('tabindex', '0')
}
})

View File

@ -645,45 +645,27 @@ ul {
margin-left: 0.2rem;
}
.card {
display: flex;
flex-direction: row;
position: relative;
align-items: center;
margin-bottom: 0.5rem;
padding: 1rem;
}
.request-card {
display: flex;
display: grid;
position: relative;
margin-bottom: 0.5rem;
align-items: left;
flex-wrap: wrap;
padding: 1rem;
border-bottom: 1px solid rgba(var(--text-color), 0.1);
}
.request-card p {
margin-top: 0;
width: 100%;
font-size: 1rem;
}
.request-card b {
font-weight: 500;
}
.request-card button {
padding: 0.2rem 0.6rem 0.2rem 0;
.request-card sm-button {
--padding: 0.5rem 0.8rem;
}
.request-card button:first-of-type {
.request-card__description {
width: 100%;
font-size: 1rem;
margin-bottom: 1rem;
}
.reject-app {
margin-left: auto;
}
.request-card:last-of-type {
border-bottom: none;
margin-right: 0.5rem;
}
#intern_updates .container-header {
@ -707,13 +689,6 @@ ul {
border-bottom: 0.2rem solid var(--accent-color);
}
#requests_container {
display: flex;
max-height: 80vh;
overflow-y: auto;
flex-direction: column;
}
#updates_page sm-select {
--max-height: 50vh;
}
@ -737,6 +712,7 @@ ul {
.update__topic {
font-weight: 500;
font-size: 1rem;
margin-top: 0.5rem;
text-transform: capitalize;
}
@ -978,13 +954,6 @@ ul {
display: inline-flexbox;
}
.appear-on-scroll-up {
position: fixed !important;
top: 0;
width: 100%;
height: 4rem !important;
}
#loading_page {
display: grid;
position: fixed;
@ -1062,17 +1031,8 @@ ul {
border: 1px solid rgba(var(--text-color), 0.06);
}
.center {
position: relative;
display: grid;
place-content: center;
height: 100%;
text-align: center;
}
#show_all,
#project_explorer {
margin: 0;
padding: 0;
}
#admin_page {
@ -1189,6 +1149,14 @@ ul {
height: 100%;
overflow-y: auto;
}
#admin_page__left .empty-state {
padding: 1rem;
text-align: center;
}
#update_filters_wrapper {
gap: 1.5rem;
}
@media only screen and (min-width: 640px) {
.hide-on-desktop {
@ -1321,7 +1289,6 @@ ul {
}
#update_filters_wrapper {
gap: 1.5rem;
padding: 1rem;
border-radius: 0.5rem;
align-content: flex-start;

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -666,46 +666,28 @@ ul {
margin-left: 0.2rem;
}
.card {
display: flex;
flex-direction: row;
position: relative;
align-items: center;
margin-bottom: 0.5rem;
padding: 1rem;
}
.request-card {
display: flex;
display: grid;
position: relative;
margin-bottom: 0.5rem;
align-items: left;
flex-wrap: wrap;
padding: 1rem;
border-bottom: 1px solid rgba(var(--text-color), 0.1);
b {
font-weight: 500;
}
sm-button{
--padding: 0.5rem 0.8rem;
}
}
.request-card p {
margin-top: 0;
.request-card__description{
width: 100%;
font-size: 1rem;
margin-bottom: 1rem;
}
.request-card b {
font-weight: 500;
}
.request-card button {
padding: 0.2rem 0.6rem 0.2rem 0;
}
.request-card button:first-of-type {
.reject-app{
margin-left: auto;
margin-right: 0.5rem;
}
.request-card:last-of-type {
border-bottom: none;
}
#intern_updates{
.container-header {
@ -730,13 +712,6 @@ ul {
}
}
#requests_container {
display: flex;
max-height: 80vh;
overflow-y: auto;
flex-direction: column;
}
#updates_page{
sm-select{
--max-height: 50vh;
@ -763,6 +738,7 @@ ul {
.update__topic {
font-weight: 500;
font-size: 1rem;
margin-top: 0.5rem;
text-transform: capitalize;
}
@ -1010,13 +986,6 @@ ul {
display: inline-flexbox;
}
.appear-on-scroll-up {
position: fixed !important;
top: 0;
width: 100%;
height: 4rem !important;
}
#loading_page {
display: grid;
position: fixed;
@ -1094,17 +1063,8 @@ ul {
border: 1px solid rgba(var(--text-color), 0.06);
}
.center {
position: relative;
display: grid;
place-content: center;
height: 100%;
text-align: center;
}
#show_all,
#project_explorer {
margin: 0;
padding: 0;
}
#admin_page {
@ -1225,6 +1185,13 @@ ul {
height: 100%;
overflow-y: auto;
}
.empty-state{
padding: 1rem;
text-align: center;
}
}
#update_filters_wrapper{
gap: 1.5rem;
}
//
@ -1365,7 +1332,6 @@ ul {
grid-template-columns: minmax(0, 1fr) 20rem;
}
#update_filters_wrapper{
gap: 1.5rem;
padding: 1rem;
border-radius: 0.5rem;
align-content: flex-start;

182
new.html
View File

@ -202,10 +202,6 @@
Sign out
</sm-button>
</section>
<section>
<h3>About</h3>
<h5>Version 8.2.5</h5>
</section>
</section>
<section id="admin_page" class="page hide-completely">
<header id="admin_page__header">
@ -249,7 +245,10 @@
</div>
<div id="interns" class="list-container"></div>
</section>
<div id="requests_container" class="list-container"></div>
<section>
<ul id="requests_list" class="list-container observe-empty-state"></ul>
<h4 class="empty-state">No pending requests</h4>
</section>
</sm-tab-panels>
</section>
<div id="project_editing_panel" class="inner-page container-card">
@ -311,6 +310,7 @@
<h5 class="uppercase">By Intern</h5>
<sm-select id="updates_page__intern_selector"></sm-select>
</div>
<sm-button onclick="clearFilter()">Clear</sm-button>
</section>
<section id="updates_wrapper">
<ul id="all_updates_list" class="grid gap-1 observe-empty-state"></ul>
@ -10305,7 +10305,7 @@
textContent: projectName
});
},
taskCard: function (currentProject, currentBranch, taskNo) {
taskCard(currentProject, currentBranch, taskNo) {
const card = getRef('timeline_task_card').content.cloneNode(true),
assignedInterns = RIBC.getAssignedInterns(currentProject, currentBranch, taskNo),
frag = document.createDocumentFragment();
@ -10430,27 +10430,31 @@
mapItems.push(card, card.id, branchContainer.id, mapBody.id)
return mapItems;
},
requestCard: function (floId, projectCode, branch, taskNo) {
let card = document.createElement('div'), name;
card.classList.add('request-card')
requestCard(floId, projectCode, branch, taskNo) {
let name;
name = floId;
if (getInternDetails(floId).length !== 0)
name = getInternDetails(floId)[0].split(':')[1];
card.innerHTML = `<p>
<b class="capitalize">${name}</b> applied for
<b class="capitalize">${RIBC.getTaskDetails(projectCode, branch, taskNo).taskTitle}</b> from
<b class="capitalize">${branch}</b> of
<b class="capitalize">${RIBC.getProjectDetails(projectCode).projectName}</b>
</p>
<button class="hover reject-app">
<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>
return createElement('li', {
className: 'request-card',
innerHTML: `<p class="request-card__description">
<b class="capitalize">${name}</b> applied for
<b class="capitalize">${RIBC.getTaskDetails(projectCode, branch, taskNo).taskTitle}</b> from
<b class="capitalize">${branch}</b> of
<b class="capitalize">${RIBC.getProjectDetails(projectCode).projectName}</b>
</p>
<div class="flex justify-end">
<sm-button class="reject-app">
<svg class="icon button__icon--left" 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>
Reject
</button>
<button class="hover accept-app" data-flo-id="${floId}" data-project-code="${projectCode}" data-branch="${branch}" data-task-no="${taskNo}">
</sm-button>
<sm-button class="accept-app button__icon--left" data-flo-id="${floId}" data-project-code="${projectCode}" data-branch="${branch}" data-task-no="${taskNo}">
<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="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z"/></svg>
Accept
</button>`;
return card;
</sm-button>
</div>
`
})
},
internTaskCard(taskObj) {
const { uniqueId, projectId, projectName, projectBranch, task } = taskObj
@ -10499,7 +10503,7 @@
return internInfo;
}
let i = currentProgress = projectIndex = 0, prevProject = '', allInternsList = [], newInternList = [], lastState,
let i = 0, allInternsList = [], newInternList = [],
frag = document.createDocumentFragment(), watchList = [], currentIntern, dashboardProject, currentTaskId,
typeOfUser = 'general';
@ -10508,14 +10512,14 @@
let internName = getRef('intern_name_field').value.trim(),
internFLOID = getRef('intern_flo_id_field').value.trim();
if (RIBC.manage.addIntern(internFLOID, internName)) {
document.getElementById('interns').append(render.internCard(internName, internFLOID, '1', 'interns'))
getRef('interns').append(render.internCard(internName, internFLOID, '1', 'interns'))
hidePopup();
notify(`${internName} added as an intern.`, 'success')
}
}
function addProjectToList() {
let projectName = document.getElementById('project_name_field').value.trim(),
projectDescription = document.getElementById('project_description_field').value.trim();
let projectName = getRef('project_name_field').value.trim(),
projectDescription = getRef('project_description_field').value.trim();
if (!projectName) {
notify('Project name is important!', 'error')
return
@ -10810,24 +10814,6 @@
hidePopup()
}
}
function renderInternUpdates(updates) {
getRef('all_updates_list').innerHTML = ``;
if(!updates){
updates = RIBC.getInternUpdates();
}
updates.forEach((entry) => {
const { floID, time, update: { topic, description } } = entry
const updateObj = {
internName: getInternDetails(floID)[0].split(':')[1],
time: parseInt(time),
topic,
description
}
frag.append(render.updateCard(updateObj))
})
getRef('all_updates_list').append(frag)
}
function renderProjectSelectorOptions() {
// Render All the projects inside updates page
@ -10889,28 +10875,77 @@
return fuse.search(floId).map(v => v.item)
}
async function renderCorrectUpdates() {
let updateStartIndex = 0
let updateEndIndex = 0
const intersectionObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if(entry.isIntersecting){
observer.disconnect()
renderFilteredUpdates({lazyLoad: true})
}
})
},{
threshold: 0.3
})
function renderInternUpdates(options = {}) {
let {updates, lazyLoad = false} = options
if(!updates){
updates = RIBC.getInternUpdates();
}
if(lazyLoad){
updateStartIndex = updateEndIndex
updateEndIndex = updates.length > updateEndIndex + 10 ? updateEndIndex + 10 : updates.length
}else{
intersectionObserver.disconnect()
getRef('all_updates_list').innerHTML = ``;
updateStartIndex = 0
updateEndIndex = updates.length > 10 ? 10 : updates.length
}
for (let index = updateStartIndex; index < updateEndIndex; index++) {
const element = updates[index];
const { floID, time, update: { topic, description } } = element
const updateObj = {
internName: getInternDetails(floID)[0].split(':')[1],
time: parseInt(time),
topic,
description
}
frag.append(render.updateCard(updateObj))
}
getRef('all_updates_list').append(frag)
if(getRef('all_updates_list').lastElementChild){
intersectionObserver.observe(getRef('all_updates_list').lastElementChild)
}
}
async function renderFilteredUpdates(options = {}) {
const {lazyLoad = false} = options
const selectedProject = getRef('updates_page__project_selector').value
const selectedintern = getRef('updates_page__intern_selector').value
if(selectedProject === 'all' && selectedintern === 'all'){
renderInternUpdates()
renderInternUpdates({lazyLoad})
}else if(selectedProject !== 'all' && selectedintern === 'all'){
const projectName = RIBC.getProjectDetails(selectedProject).projectName
const matchedUpdates = await getUpdatesByProject(projectName)
renderInternUpdates(matchedUpdates)
renderInternUpdates({updates: matchedUpdates, lazyLoad})
}else if(selectedProject === 'all' && selectedintern !== 'all'){
const matchedUpdates = await getUpdatesByIntern(selectedintern)
renderInternUpdates(matchedUpdates)
renderInternUpdates({updates: matchedUpdates, lazyLoad})
}else{
const projectName = RIBC.getProjectDetails(selectedProject).projectName
let matchedUpdates = await getUpdatesByProject(projectName)
matchedUpdates = await getUpdatesByIntern(selectedintern, matchedUpdates)
renderInternUpdates(matchedUpdates)
renderInternUpdates({updates: matchedUpdates, lazyLoad})
}
}
getRef('updates_page__project_selector').addEventListener('change', renderCorrectUpdates)
getRef('updates_page__intern_selector').addEventListener('change', renderCorrectUpdates)
function clearFilter(){
getRef('updates_page__project_selector').reset()
getRef('updates_page__intern_selector').reset()
}
getRef('updates_page__project_selector').addEventListener('change', renderFilteredUpdates)
getRef('updates_page__intern_selector').addEventListener('change', renderFilteredUpdates)
function watchThisProject(thisBtn) {
@ -11146,43 +11181,48 @@
// admin view
if (floGlobals.subAdmins.includes(myFloID)) {
typeOfUser = 'admin'
getRef('requests_list').innerHTML = ''
RIBC.manage.getTaskRequests().forEach((app) => {
try {
if (!Array.isArray(RIBC.getAssignedInterns(app.projectCode, app.branch, app.task)) && typeof RIBC.getTaskDetails(app.projectCode, app.branch, app.task) !== 'undefined')
frag.appendChild(render.requestCard(app.floID, app.projectCode, app.branch, app.task))
frag.append(render.requestCard(app.floID, app.projectCode, app.branch, app.task))
}
catch (error) {
console.error(error)
}
})
getRef('requests_container').appendChild(frag)
if (getRef('requests_container').children.length === 0)
getRef('requests_container').innerHTML = '<h4 class="padding">Nothing to see here.</h4>'
getRef('requests_container').addEventListener('click', (e) => {
getRef('requests_list').append(frag)
getRef('requests_list').addEventListener('click', (e) => {
function removeRequest(requestCard){
requestCard.animate([
{
transform: 'translateX(0)',
opacity: 1
},
{
transform: 'translateX(-100%)',
opacity: 0
},
], {
duration: 300,
easing: 'ease'
}).onfinish = () => {
requestCard.remove()
}
}
if (e.target.closest('.accept-app')) {
let btn = e.target.closest('.accept-app'),
parent = e.target.closest('.request-card');
requestCard = e.target.closest('.request-card');
if (RIBC.manage.assignInternToTask(btn.dataset.floId, btn.dataset.projectCode, btn.dataset.branch, btn.dataset.taskNo)) {
notify('Intern assinged.', 'success')
parent.classList.add('slide-left')
setTimeout(() => {
parent.remove()
}, 600)
if (getRef('requests_container').children.length === 0)
getRef('requests_container').innerHTML = '<h4 class="padding">Nothing to see here.</h4>'
removeRequest(requestCard)
}
else {
notify('Intern already assinged.', 'error')
}
}
if (e.target.closest('.reject-app')) {
let parent = e.target.closest('.request-card');
parent.classList.add('slide-left')
setTimeout(() => {
parent.remove()
}, 400)
if (getRef('requests_container').children.length === 0)
getRef('requests_container').innerHTML = '<h4 class="padding">Nothing to see here.</h4>'
}else if (e.target.closest('.reject-app')) {
let requestCard = e.target.closest('.request-card');
removeRequest(requestCard)
}
})