From 01103dcff8d1f721e1b26027a75736ab6bcbbe17 Mon Sep 17 00:00:00 2001 From: sairaj mote Date: Fri, 28 Oct 2022 17:06:19 +0530 Subject: [PATCH] Feature update Adding option to specify displayed tasks --- css/main.css | 28 +- css/main.min.css | 2 +- css/main.scss | 27 +- index.html | 2523 ++++++++++++++++++++++++++++++++++++++++++- scripts/app_ui.js | 1608 --------------------------- scripts/ribc.js | 7 +- scripts/ribc.min.js | 2 +- scripts/std_ui.js | 819 -------------- 8 files changed, 2565 insertions(+), 2451 deletions(-) delete mode 100644 scripts/app_ui.js delete mode 100644 scripts/std_ui.js diff --git a/css/main.css b/css/main.css index 7b8f869..05a89f6 100644 --- a/css/main.css +++ b/css/main.css @@ -80,7 +80,6 @@ body[data-theme=dark] ::-webkit-calendar-picker-indicator { p, strong { line-height: 1.7; - font-size: 0.9rem; color: rgba(var(--text-color), 0.9); max-width: 70ch; } @@ -246,14 +245,9 @@ input[type=range]:active { cursor: grab; } -sm-copy { - font-size: 0.9rem; -} - sm-input, sm-textarea, tags-input { - font-size: 0.9rem; --border-radius: 0.5rem; --background-color: rgba(var(--foreground-color), 1); } @@ -296,7 +290,6 @@ sm-form { sm-select { --padding: 0.8rem; - font-size: 0.9rem; --min-width: fit-content; --select-border-radius: 0.5rem; } @@ -1016,7 +1009,6 @@ ul { background-color: rgba(var(--text-color), 0.06); border-radius: 1rem; padding: 0.4rem 0.8rem; - font-size: 0.9rem; color: rgba(var(--text-color), 0.8); } .display-task__detail__value { @@ -1490,6 +1482,25 @@ ul { margin: 0; } +#task_display_container { + padding: 0 1rem; +} + +.displayable-task { + padding: 1rem; + border-radius: 0.5rem; + border: solid thin rgba(var(--text-color), 0.1); + background-color: rgba(var(--foreground-color), 1); + margin-bottom: 0.5rem; +} +.displayable-task__project { + font-size: 0.9rem; + padding: 0.2rem 0.5rem; + background-color: rgba(var(--text-color), 0.06); + border-radius: 0.3rem; + opacity: 0.8; +} + #loading { display: grid; text-align: center; @@ -1593,7 +1604,6 @@ ul { word-wrap: break-word; overflow-wrap: break-word; color: rgba(var(--text-color), 0.8); - font-size: 0.9rem; margin-top: 0.2rem; } diff --git a/css/main.min.css b/css/main.min.css index 8854259..8a0e357 100644 --- a/css/main.min.css +++ b/css/main.min.css @@ -1 +1 @@ -*{padding:0;margin:0;box-sizing:border-box;font-family:"Roboto",sans-serif}:root{font-size:clamp(1rem,1.2vmax,1.2rem)}html,body{height:100%}body{--accent-color: #3d5afe;--secondary-color: #ffac2e;--text-color: 20, 20, 20;--foreground-color: 252, 253, 255;--background-color: 241, 243, 248;--danger-color: rgb(255, 75, 75);--green: #1cad59;--yellow: rgb(220, 165, 0);--dark-red: #d40e1e;--red: #f50000;--kinda-pink: #e40273;--purple: #462191;--shady-blue: #324de6;--nice-blue: #3d5afe;--maybe-cyan: #00b0ff;--teal: #00bcd4;--mint-green: #16c79a;--yellowish-green: #66bb6a;--greenish-yellow: #8bc34a;--dark-teal: #11698e;--tangerine: #ff6f00;--orange: #ff9100;--redish-orange: #ff3d00;color:rgba(var(--text-color), 1);background-color:rgba(var(--background-color), 1);overflow:hidden}body[data-theme=dark]{--accent-color: #6d83ff;--secondary-color: #d60739;--text-color: 200, 200, 200;--foreground-color: 27, 28, 29;--background-color: 21, 22, 22;--danger-color: rgb(255, 106, 106);--green: #00e676;--yellow: rgb(255, 213, 5);--dark-red: #ff5e7e;--red: #ff6098;--kinda-pink: #c44ae6;--purple: #9565f7;--shady-blue: #8295fb;--nice-blue: #6d83ff;--maybe-cyan: #66cfff;--teal: #6aeeff;--mint-green: #4dffd2;--yellowish-green: #9effa2;--greenish-yellow: #c7fc8b;--dark-teal: #51cbff;--tangerine: #ffac6d;--orange: #ffbe68;--redish-orange: #ff8560}body[data-theme=dark] ::-webkit-calendar-picker-indicator{filter:invert(1)}.calistoga{font-weight:400;font-family:"Calistoga",cursive}p,strong{line-height:1.7;font-size:.9rem;color:rgba(var(--text-color), 0.9);max-width:70ch}img{-o-object-fit:cover;object-fit:cover}a:where([class]){color:inherit;text-decoration:none}a:where([class]):focus-visible{box-shadow:0 0 0 .1rem rgba(var(--text-color), 1) inset}a{color:var(--accent-color)}a:-webkit-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:-moz-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}button,.button{-webkit-user-select:none;-moz-user-select:none;user-select:none;position:relative;display:inline-flex;border:none;background-color:rgba(0,0,0,0);overflow:hidden;color:inherit;-webkit-tap-highlight-color:rgba(0,0,0,0);align-items:center;font-size:.9rem;font-weight:500;white-space:nowrap;padding:.8rem;border-radius:.3rem;justify-content:center}button:focus-visible,.button:focus-visible{outline:var(--accent-color) solid medium}button:not(:disabled),.button:not(:disabled){cursor:pointer}.button{background-color:rgba(var(--text-color), 0.02);border:solid thin rgba(var(--text-color), 0.06)}.button--primary{color:rgba(var(--background-color), 1) !important}.button--primary .icon{fill:rgba(var(--background-color), 1)}.button--danger{color:var(--danger-color)}.button--danger .icon{fill:var(--danger-color)}.button--primary{background-color:var(--accent-color)}.button--colored{color:var(--accent-color)}.button--colored .icon{fill:var(--accent-color)}.button--small{padding:.4rem .6rem}.button--outlined{border:solid rgba(var(--text-color), 0.3) .1rem;background-color:rgba(var(--foreground-color), 1)}.button--transparent{background-color:rgba(0,0,0,0)}.cta{text-transform:uppercase;font-size:.8rem;font-weight:700;letter-spacing:.05em;padding:.8rem 1rem}.icon{width:1.2rem;height:1.2rem;fill:rgba(var(--text-color), 0.8);flex-shrink:0}.icon-only{padding:.5rem;border-radius:.3rem;aspect-ratio:1/1}button:disabled{opacity:.5}a:-webkit-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:-moz-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}details summary{display:flex;-webkit-user-select:none;-moz-user-select:none;user-select:none;cursor:pointer;align-items:center;justify-content:space-between;color:var(--accent-color)}details[open] summary{margin-bottom:1rem}details[open]>summary .down-arrow{transform:rotate(180deg)}fieldset{border:none}input{accent-color:var(--accent-color)}input[type=range]:active{cursor:-webkit-grab;cursor:grab}sm-copy{font-size:.9rem}sm-input,sm-textarea,tags-input{font-size:.9rem;--border-radius: 0.5rem;--background-color: rgba(var(--foreground-color), 1)}sm-input button .icon,sm-textarea button .icon,tags-input button .icon{fill:var(--accent-color)}sm-textarea{--max-height: 32ch}sm-button{--padding: 0.8rem}sm-button[variant=primary] .icon{fill:rgba(var(--background-color), 1)}sm-button[disabled] .icon{fill:rgba(var(--text-color), 0.6)}sm-button.danger{--background: var(--danger-color);color:rgba(var(--background-color), 1)}sm-spinner{--size: 1.5rem;--stroke-width: 0.1rem}cube-loader{--size: 1.2rem}sm-form{--gap: 1rem}sm-select{--padding: 0.8rem;font-size:.9rem;--min-width: fit-content;--select-border-radius: 0.5rem}sm-select[open]{z-index:10}sm-option{font-size:.9rem}strip-select{--gap: 0.3rem}strip-option{position:relative;font-size:.9rem;--border-radius: 0.3rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}sm-button{--border-radius: 0.3rem}sm-button[variant=primary] .icon{fill:rgba(var(--background-color), 1)}sm-button[disabled] .icon{fill:rgba(var(--text-color), 0.6)}ul{list-style:none}.overflow-ellipsis{width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.wrap-around{overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;-webkit-hyphens:auto;hyphens:auto}.full-bleed{grid-column:1/-1}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.sticky{position:-webkit-sticky;position:sticky}.top-0{top:0}.flex{display:flex}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.grid{display:grid}.flow-column{grid-auto-flow:column}.gap-0-3{gap:.3rem}.gap-0-5{gap:.5rem}.gap-1{gap:1rem}.gap-1-5{gap:1.5rem}.gap-2{gap:2rem}.gap-3{gap:3rem}.text-align-right{text-align:right}.text-align-left{text-align:left}.align-items-start{align-items:flex-start}.align-content-start{align-content:flex-start}.align-start{align-content:flex-start}.align-center{align-items:center}.align-end{align-items:flex-end}.text-center{text-align:center}.justify-start{justify-items:start}.justify-content-start{justify-content:start}.justify-center{justify-content:center}.justify-right{margin-left:auto}.align-self-center{align-self:center}.align-self-end{align-self:end}.justify-self-center{justify-self:center}.justify-self-start{justify-self:start}.justify-self-end{justify-self:end}.flex-direction-column{flex-direction:column}.space-between{justify-content:space-between}.w-100{width:100%}.h-100{height:100%}.padding-block-1{padding-block:1rem}.margin-right-0-3{margin-right:.3rem}.margin-right-0-5{margin-right:.5rem}.margin-left-0-5{margin-left:.5rem}.margin-left-auto{margin-left:auto}.margin-right-auto{margin-right:auto}.margin-top-1{margin-top:1rem}.margin-bottom-0-5{margin-bottom:.5rem}.margin-bottom-1{margin-bottom:1rem}.margin-bottom-2{margin-bottom:2rem}.margin-block-0-5{margin-block:.5rem}.margin-block-1{margin-block:1rem}.margin-block-1-5{margin-block:1.5rem}.margin-inline-1{margin-inline:1rem}.margin-inline-1-5{margin-inline:1.5rem}.hidden{display:none !important}.no-transformations{transform:none !important}.full-bleed{grid-column:1/4}.h1{font-size:2.5rem}.h2{font-size:2rem}.h3{font-size:1.4rem}.h4{font-size:1rem}.h5{font-size:.8rem}.grid-3{grid-template-columns:1fr auto auto}.flow-column{grid-auto-flow:column}.w-100{width:100%}.color-0-8{color:rgba(var(--text-color), 0.8)}.weight-400{font-weight:400}.weight-500{font-weight:500}.ws-pre-line{white-space:pre-line}.card{background-color:rgba(var(--foreground-color), 1);border-radius:.5rem;padding:max(1rem,3vw)}.ripple{height:8rem;width:8rem;position:absolute;border-radius:50%;transform:scale(0);background:radial-gradient(circle, rgba(var(--text-color), 0.3) 0%, rgba(0, 0, 0, 0) 50%);pointer-events:none}.interact{position:relative;overflow:hidden;cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}.observe-empty-state:empty{display:none}.observe-empty-state:not(:empty)~.empty-state{display:none}.button__icon{height:1.2rem;width:1.2rem}.button__icon--left{margin-right:.5rem}.button__icon--right{margin-left:.5rem}[data-editable]{transition:padding .2s}[data-editable]:focus-within{padding:.5em;border-radius:.3rem;outline:none;background-color:rgba(var(--text-color), 0.06);box-shadow:0 0 0 .1rem var(--accent-color) inset}.multi-state-button{display:grid;text-align:center;align-items:center}.multi-state-button>*{grid-area:1/1/2/2}.multi-state-button button{z-index:1}.password-field label{display:flex;justify-content:center}.password-field label input:checked~.visible{display:none}.password-field label input:not(:checked)~.invisible{display:none}#confirmation_popup,#prompt_popup{flex-direction:column}#confirmation_popup h4,#prompt_popup h4{font-weight:500;margin-bottom:.5rem}#confirmation_popup .flex,#prompt_popup .flex{margin-top:1rem}.popup__header{display:grid;gap:.5rem;width:100%;padding:0 1.5rem 0 .5rem;align-items:center;grid-template-columns:auto 1fr auto}.popup__header__close{padding:.5rem;cursor:pointer}.page{height:100%}.page__header{display:flex;justify-content:space-between;margin-bottom:1.5rem;min-height:8rem}.page__header .grid{margin-top:auto}.page__header h1{margin-top:auto;font-size:2rem}.page-layout{display:grid;gap:1.5rem 0;grid-template-columns:1.5rem minmax(0, 1fr) 1.5rem;align-content:flex-start}.page-layout>*{grid-column:2/3}#secondary_pages{display:grid;width:100%;grid-template-rows:-webkit-min-content minmax(0, 1fr);grid-template-rows:min-content minmax(0, 1fr);grid-template-areas:"header" "content"}#secondary_pages header{padding:1rem;background-color:rgba(var(--foreground-color), 0.3)}#secondary_pages .inner-page{width:100%;height:100%;grid-area:content}.inner-page{gap:1rem;display:grid;position:relative;padding:1rem;grid-template-columns:minmax(0, 1fr);height:100%;background-color:rgba(var(--foreground-color), 0.3)}#landing{padding:0 1rem;overflow-y:auto;padding-bottom:3rem;align-content:flex-start}.landing__card{display:grid;position:relative;flex-shrink:0;margin:0 auto;padding:2rem max(1rem,4vw);border-radius:1rem;align-items:center}.landing__card h1{font-size:max(1.5rem,2vw)}.landing__card img{width:min(100%,16rem)}.landing__card:first-of-type{background-color:#2a2c35;color:#fff}.landing__card:first-of-type h1{mix-blend-mode:soft-light}#landing_tasks_wrapper{margin:0 auto;width:min(100%,48rem)}#display_task_list{margin-top:1rem}#sign_in,#sign_up{justify-items:center;align-content:center}#sign_in section,#sign_up section{margin-top:-8rem;width:min(26rem,100%)}#sign_in sm-form,#sign_up sm-form{margin:2rem 0}#sign_up .h2{margin-bottom:.5rem}.generated-keys-wrapper{padding:1rem;background-color:rgba(var(--foreground-color), 1);border-radius:.5rem}#flo_id_warning{padding-bottom:1.5rem}#flo_id_warning .icon{height:3rem;width:3rem;padding:.8rem;overflow:visible;background-color:#ffc107;border-radius:3rem;fill:rgba(0,0,0,.8)}#task_details{position:fixed;width:100%;height:100%;inset:0;display:grid;overflow:hidden auto;z-index:10}#task_details>*{grid-area:1/1/2/2}#task_details__backdrop{background-color:rgba(0,0,0,.5)}#task_details_wrapper{padding:0 max(1rem,4vw);background-color:rgba(var(--foreground-color), 1);padding-bottom:3rem;max-width:70ch;justify-self:flex-end;box-shadow:-1rem 0 2rem rgba(0,0,0,.1)}#task_description{margin-top:1rem}#main_page{height:100%;grid-template-rows:auto 1fr auto;grid-template-areas:"main-header" "sub-pages" "main-nav"}#sub_page_container{grid-area:sub-pages;height:100%;overflow-y:auto;display:grid}#sub_page_container>*{grid-area:1/1}#main_header{grid-area:main-header;display:flex;gap:1rem;align-items:center;position:-webkit-sticky;position:sticky;padding:1rem;background:rgba(var(--foreground-color), 1);z-index:1}#main_nav{grid-area:main-nav;position:relative;display:flex;align-items:center;background-color:rgba(var(--foreground-color), 1)}.nav-list__item{display:flex;flex-direction:column;align-items:center;width:100%;padding:.5rem 0;-webkit-tap-highlight-color:rgba(0,0,0,0);font-size:.8rem;font-weight:500;color:rgba(var(--text-color), 0.8)}.nav-list__item--active{color:var(--accent-color)}.nav-list__item--active .icon{fill:var(--accent-color)}.nav-list__item--active .icon--outlined{display:none}.nav-list__item--active .icon--filled{display:inline-block}.nav-list__item:not(.nav-list__item--active) .icon--outlined{display:inline-block}.nav-list__item:not(.nav-list__item--active) .icon--filled{display:none}.nav-list__item .icon{margin-bottom:.3rem}.container-card{position:relative;background:rgba(var(--foreground-color), 1);border-radius:.5rem}#sign_in_page{display:grid;position:fixed;z-index:5;top:0;bottom:0;left:0;right:0;place-content:center;background-color:rgba(var(--foreground-color), 1);gap:1rem}.display-task{display:flex;flex-direction:column;gap:.8rem;padding:max(2vw,1rem);border-radius:.5rem;background-color:rgba(var(--foreground-color), 1);width:100%;border:solid .2rem rgba(var(--text-color), 0.8)}.display-task__category{display:inline-flex;padding:.3rem .5rem;background-color:rgba(var(--text-color), 0.06);border-radius:.3rem;font-size:.9rem;color:rgba(var(--text-color), 0.8);text-transform:capitalize;font-weight:500;height:100%;align-items:center}.display-task__category:is(a){color:var(--accent-color)}.display-task__title{font-size:1.2rem}.display-task__description{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;white-space:pre-wrap}.display-task__detail{display:flex;gap:.3rem;background-color:rgba(var(--text-color), 0.06);border-radius:1rem;padding:.4rem .8rem;font-size:.9rem;color:rgba(var(--text-color), 0.8)}.display-task__detail__value{font-weight:500}.display-task p{line-height:1.5}.task{display:grid;grid-template-columns:auto 1fr;margin-right:1rem}.task .task__branch_container{padding-bottom:2rem}.task:last-of-type .left .line{transform:scaleY(0)}.task .left{display:flex;position:relative;justify-content:center;padding-top:.3rem}.task .left .circle{display:inline-flex;position:relative;align-self:flex-start;height:1.4rem;padding:.15rem;aspect-ratio:1/1;border-radius:50%;background:rgba(var(--text-color), 0.1);z-index:1}.task .left .circle .icon{width:100%;height:100%}.task .left .line{position:absolute;left:50%;height:100%;width:2px;transform:translateX(-50%) scaleY(1);background-color:rgba(var(--text-color), 0.4)}.task .right{margin-left:1rem;display:flex;flex-direction:column;width:100%;gap:.7rem}.task .right .apply-cont{width:100%;display:flex;flex-direction:row}.task .right .apply-cont h4{flex:1}.task .right:last-child{margin-bottom:1rem}.task h4{margin-top:.4rem}.task .assigned-interns .assigned-intern{padding:.4rem}.admin-reply__description{max-width:100%}.completed .left .circle{background:rgba(0,200,83,.1254901961)}.completed .left .circle .icon{fill:#00c853}.completed .left .line{background-color:#00c853 !important}.task-title{font-weight:500}.padding{padding:1rem}#dashboard_page{padding-bottom:5rem;grid-template-columns:minmax(0, 1fr);overflow-y:auto;align-content:flex-start}#dashboard_view_selector{border-radius:2rem;margin:0 auto;padding:.3rem;background-color:rgba(var(--text-color), 0.04)}#dashboard_view_selector strip-option{--border-radius: 2rem}.logo{display:flex;align-items:center}.project-card{padding:1rem;margin:.2rem;border-radius:.5rem;font-weight:500;line-height:1.5;text-transform:capitalize;color:rgba(var(--text-color), 0.8)}.intern-card{display:flex;padding:1rem;margin:.2rem;border-radius:.5rem;-webkit-user-select:none;-moz-user-select:none;user-select:none;padding:.8rem 1rem;gap:.8rem;cursor:pointer}.intern-card input{height:1.3em;width:1.3em}.intern-card .icon{height:1rem;width:1rem;margin-left:.2rem}.intern-card__name{flex:1}.intern-card__initials{display:flex;height:2.6rem;width:2.6rem;justify-content:center;align-items:center;border-radius:50%;color:var(--color);font-weight:700;font-size:1rem;text-transform:uppercase;background-color:rgba(var(--text-color), 0.06)}.intern-card__score-wrapper{font-weight:500;font-size:1.2rem}.request-card{display:grid;position:relative;padding:1rem;width:min(64rem,100%);margin:0 auto;gap:.3rem;background-color:rgba(var(--foreground-color), 1);border-radius:.5rem;margin-bottom:.5rem;border:solid rgba(var(--text-color), 0.1) thin}.request-card sm-button{--padding: 0.5rem 0.8rem}.request-card__description{width:100%;font-size:1rem}.reject-app{margin-left:auto;margin-right:.5rem}#updates_page{align-content:flex-start}#updates_page sm-select{--max-height: 50vh}#updates{transition:opacity .3s ease}.intern-update{display:grid;gap:.5rem;padding:1rem;border-radius:.5rem;background-color:rgba(var(--foreground-color), 1)}.update__topic{font-weight:500;font-size:1rem;margin-top:.5rem;text-transform:capitalize;max-width:65ch}.update__sender,.admin-reply__title{font-size:.85rem;font-weight:500;background-color:rgba(var(--text-color), 0.06);padding:.3rem .5rem;margin:0 -0.5rem;border-radius:1rem}.update__time{font-size:.85rem;color:rgba(var(--text-color), 0.8)}.admin-reply{position:relative;padding:1rem;padding-left:1.5rem;margin-left:.5rem;gap:.3rem}.admin-reply::before{content:"";position:absolute;width:.1rem;height:calc(100% - 1rem);left:0;background-color:rgba(var(--text-color), 0.5)}.admin-reply__title{justify-self:flex-start}.container-header{display:flex;align-items:center;width:100%;padding:1rem}.container-header h4{flex:1;font-weight:500}#intern_info_popup .grid>*{justify-self:center}#intern_info_popup #update_intern_score{width:100%;margin-top:1rem}#intern_info__initials{position:relative;height:4rem;width:4rem;font-size:1.3rem;color:var(--color)}#intern_info__name{font-size:1.5rem;margin-bottom:.5rem}.icon--star{fill:var(--orange)}#intern_info__score{font-size:1.5rem}#project_info{flex-direction:column}.branch-button{display:flex;padding:.5rem;border-radius:.2rem;text-transform:capitalize;justify-self:start;align-items:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;font-size:.85rem;font-weight:500}.branch-button--active{opacity:1;color:#fff;background:var(--accent-color)}#task_list{gap:.5rem;padding:1rem 0 1.5rem 0}.task-list-item{display:grid;align-content:flex-start;padding:1rem;gap:.5rem;border-radius:.5rem;background:rgba(var(--foreground-color), 1)}.task-list-item h4{font-weight:500;margin:0}.task-list-item .task-title{line-height:1.6}.task-list-item__task-number{font-size:.8rem;color:rgba(var(--text-color), 0.8);border:solid .1em var(--accent-color);border-radius:.3rem;padding:.2rem .4rem;font-weight:500}.task__branch_container:not(:empty){display:grid;gap:.5rem;padding:.5rem 0}.task__branch_container .branch-button{position:relative;background-color:rgba(0,0,0,0);padding:0;padding-left:2rem;margin:.5rem 0}.task__branch_container .branch-button::before{position:absolute;content:"";top:-50%;left:0;display:inline-flex;width:1rem;height:100%;align-self:flex-start;margin-right:.8rem;border-left:solid;border-bottom:solid;border-width:.15rem;border-color:rgba(var(--text-color), 0.6);border-radius:0 0 0 .2rem}.task__branch_container .branch-button+.branch-button::before{top:calc(-50% - 1.5rem);height:calc(100% + 1.5rem)}.task-option{margin-right:-0.5rem}.task-description{margin:0;overflow-wrap:break-word;word-wrap:break-word}.assigned-interns{display:flex;flex-wrap:wrap;gap:.5rem}.assigned-interns .assigned-intern{-webkit-user-select:none;-moz-user-select:none;user-select:none;display:flex;font-size:.8rem;padding:.2rem 0 .2rem .4rem;border-radius:.2rem;border:1px solid rgba(var(--text-color), 0.24);align-items:center;white-space:nowrap;text-transform:capitalize}.assigned-interns .assigned-intern button{padding:.2rem}.assigned-interns .assigned-intern button .icon{height:1rem;width:1rem}#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:.5rem;transition:.3s opacity;background-color:rgba(var(--foreground-color), 1);box-shadow:0 1rem 2rem rgba(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:.9rem;margin:.2rem;padding:.6rem .8rem;border-radius:.3rem}#task_context li .icon{margin-right:.5rem}#branch_container{display:flex;flex-flow:row wrap;margin:.5rem 0 1rem 0}#intern_list_popup{flex-direction:column}#intern_search_field{margin-bottom:1rem}#intern_list_container{height:100%;overflow-y:auto}#intern_list_container .intern-card{padding:.8rem 0;margin:0}#loading{display:grid;text-align:center;place-content:center;justify-items:center;background-color:rgba(var(--foreground-color), 1)}#pinned_project_section{position:relative;overflow:hidden}#project_explorer{padding:0}#project_explorer__right{gap:1rem;align-items:flex-start;align-content:flex-start;padding:1rem}#pin_project_button{margin-left:1rem}#admin_page{position:relative;display:grid;padding:0;height:100%;overflow:hidden;grid-template-rows:auto 1fr}#admin_views{display:grid;height:100%;overflow-y:hidden}#admin_views>*{grid-area:1/1}#project_editing_panel{position:relative;height:100%;padding:0 max(4vw,1rem);overflow-y:auto;padding-bottom:2rem;flex:1}#update_of_project{color:rgba(var(--text-color), 0.8)}#update_of_task{font-size:1.3rem;margin:.4rem 0 1.8rem 0}ul{padding:0;list-style:none}#assigned_task_list{display:grid;gap:1rem;margin-top:1rem;align-content:flex-start;grid-template-columns:minmax(0, 1fr)}.task-card{display:grid;gap:.5rem;padding:1rem;border-radius:.5rem;background-color:rgba(var(--foreground-color), 1)}.task__project-title{font-size:.8rem;margin:0 -0.5em;margin-bottom:.5rem;border-radius:1rem;padding:.3rem .5rem;justify-self:flex-start;color:rgba(var(--text-color), 0.8);background-color:rgba(var(--text-color), 0.06)}.task__title{font-size:1.1rem;margin-bottom:1rem}.task__description{word-wrap:break-word;overflow-wrap:break-word;color:rgba(var(--text-color), 0.8);font-size:.9rem;margin-top:.2rem}.send-update-button,.init-update-replay{color:var(--accent-color);background-color:rgba(var(--text-color), 0.04)}.send-update-button .icon,.init-update-replay .icon{fill:var(--accent-color)}.temp-task{padding:1rem;background-color:rgba(var(--foreground-color), 1);border-radius:.5rem}#internship_requests_list{padding-bottom:2rem}.status-card{display:grid;gap:1rem;padding:1rem;border-radius:.5rem;background-color:rgba(var(--foreground-color), 1)}.status-card__time{font-size:.8rem;color:rgba(var(--text-color), 0.8)}.status-card__status{justify-content:flex-end}.status-card__status .icon{height:1em;width:1em}.status-card.accepted .icon{fill:var(--green)}.status-card.rejected .icon{fill:var(--danger-color)}.status-card.pending .icon{fill:var(--yellow)}#projects_container{display:flex;height:100%;overflow-y:hidden}#projects_container__left{height:100%;overflow-y:auto;width:100%}#projects_container__left .list-container{height:100%;overflow-y:auto;padding-bottom:2rem}#projects_container__left .empty-state{padding:1rem;text-align:center}#update_filters_wrapper{gap:1.5rem}input[type=date]{display:flex;width:100%;padding:.5rem;border:rgba(var(--text-color), 0.2) solid thin;border-radius:.3rem;font-family:inherit;font-size:inherit;color:inherit;background-color:rgba(var(--text-color), 0.06)}input[type=date]:focus{outline:none;box-shadow:0 0 0 .1rem var(--accent-color)}#requests_container{padding:0 1rem;gap:1.5rem;overflow-y:auto}#user_role{justify-self:start;font-size:.7rem;font-weight:500;text-transform:uppercase;letter-spacing:.05em;padding:.4rem .8rem;border-radius:.3rem;border:solid var(--accent-color) thin}#pinned_project_section{display:grid;gap:1rem}#pinned_projects{display:grid;gap:.3rem;grid-template-columns:repeat(auto-fill, minmax(20rem, 1fr))}.pinned-card{color:inherit;display:grid;border-radius:.5rem;padding:1rem;background-color:rgba(var(--foreground-color), 1);grid-template-columns:auto 1fr}.pinned-card .project-icon{display:flex;background-color:rgba(var(--text-color), 0.06);justify-self:start;align-self:flex-start;padding:.8rem;border-radius:2rem;margin-right:.8rem;grid-row:span 3}.pinned-card .project-icon .icon{fill:var(--accent-color)}.pinned-card .project__title{font-weight:500;color:rgba(var(--text-color), 0.9)}.pinned-card .project__title:hover{color:var(--accent-color)}.pinned-card .project__complete-percent{font-size:.8rem;opacity:.8;margin-top:.5rem}.progress-bar{display:flex;height:.2rem;background-color:rgba(var(--text-color), 0.2);border-radius:1rem;overflow:hidden;align-self:flex-end}.progress-bar .progress-value{background-color:var(--accent-color);transition:width .3s}#settings_page{align-content:flex-start}#settings_page>*{width:min(48rem,100%);margin:0 auto}@media only screen and (max-width: 640px){.list-container{padding-bottom:5rem}.status-card__status{grid-area:1/2/2/3}.status-card__details{grid-area:2/1/3/3}.landing__card:first-of-type{text-align:center;justify-items:center}.landing__card:first-of-type .flex{justify-content:center}.landing__card:first-of-type img{grid-area:1/1/2/2}#task_search_input{width:100%}.hide-on-mobile,.hide-page-on-mobile{display:none}}@media only screen and (min-width: 640px){.hide-on-desktop{display:none !important}sm-popup{--width: 26rem}.popup__header{padding:1.5rem 1.5rem 0 .75rem}#secondary_pages header{padding:1.5rem 8vw}.landing__card{grid-template-columns:1fr auto}.landing__card img{justify-self:flex-end}#task_details .button--primary{width:-webkit-max-content;width:-moz-max-content;width:max-content}#main_nav{padding:.5rem;background-color:rgba(var(--background-color), 1);flex-direction:column}#main_nav theme-toggle{margin:1rem;margin-top:auto}.nav-list__item{flex-direction:row;align-items:center;border-radius:.5rem;padding:.8rem;margin-bottom:.25rem;font-size:1rem}.nav-list__item--active{background-color:rgba(var(--text-color), 0.06)}.nav-list__item .icon{margin-bottom:0}.nav-list__item_title{display:none}.project-card--active{background-color:rgba(var(--text-color), 0.1)}.project-card--active::before{content:"";position:absolute;top:0;left:0;bottom:0;margin:auto 0;width:.2rem;height:1.5em;background-color:var(--accent-color);border-radius:0 .2rem .2rem 0}#sign_in{width:24rem;height:auto;border-radius:.4rem}#dashboard_page{grid-template-columns:1fr 18rem}#dashboard_page>:not(#best_interns_container,#dashboard_view_selector){grid-column:1;width:min(48rem,100%);margin:0 auto}#best_interns_container{position:-webkit-sticky;position:sticky;top:0;grid-column:2;grid-row:1/4;align-self:flex-start}#all_interns_page__header{grid-template-columns:1fr auto}#admin_page{padding:0}#projects_container__left{width:18rem}#project_explorer{display:grid;height:100%;gap:0;grid-template-columns:16rem 3fr;grid-template-areas:"left right";background-color:rgba(var(--foreground-color), 0.3);overflow-y:auto}#project_explorer__left{grid-area:left;height:100%;overflow-y:auto;padding-bottom:1.5rem}#project_explorer__left h4{margin-top:0;margin-bottom:.5rem;color:var(--accent-color);font-size:.9rem}#project_explorer__right{grid-area:right;height:100%;overflow-y:auto;padding:1.5rem 4vw;background-color:rgba(var(--foreground-color), 0.5)}#main_page{grid-template-columns:4rem minmax(0, 1fr);grid-template-areas:"main-header main-header" "main-nav sub-pages"}#post_update_popup{--width: 28rem}#updates_page{height:100%;gap:1rem;grid-template-areas:"updates update-filters";grid-template-columns:minmax(0, 1fr) 20rem;overflow-y:hidden}#update_filters_wrapper{padding:1rem;border-radius:.5rem;align-content:flex-start;grid-area:update-filters;background-color:rgba(var(--foreground-color), 1)}#updates_wrapper{height:100%;overflow-y:auto;grid-area:updates}#all_interns_list{gap:.5rem;grid-template-columns:repeat(auto-fill, minmax(16rem, 1fr))}#all_interns_list .intern-card{margin:0;gap:1rem;border-radius:.5rem;background-color:rgba(var(--foreground-color), 1)}#intern_list_popup{--height: 80vh}.status-card{align-items:center;font-size:.9rem;grid-template-columns:6rem 1fr 8rem}#requests_container{padding:1rem;grid-template-columns:14rem 1fr}#requests_container>:nth-child(2){width:min(48rem,100%);margin:0 auto}}@media only screen and (min-width: 1280px){#main_page{grid-template-columns:12rem minmax(0, 1fr);grid-template-areas:"main-header main-header" "main-nav sub-pages"}#main_nav{align-items:flex-start}.nav-list__item .icon{margin-right:.5rem}.nav-list__item_title{display:inline-block}}@media(any-hover: hover){::-webkit-scrollbar{width:.5rem;height:.5rem}::-webkit-scrollbar-thumb{background:rgba(var(--text-color), 0.3);border-radius:1rem}::-webkit-scrollbar-thumb:hover{background:rgba(var(--text-color), 0.5)}.interact{transition:background-color .2s}.interact:hover{background-color:rgba(var(--text-color), 0.04)}} \ No newline at end of file +*{padding:0;margin:0;box-sizing:border-box;font-family:"Roboto",sans-serif}:root{font-size:clamp(1rem,1.2vmax,1.2rem)}html,body{height:100%}body{--accent-color: #3d5afe;--secondary-color: #ffac2e;--text-color: 20, 20, 20;--foreground-color: 252, 253, 255;--background-color: 241, 243, 248;--danger-color: rgb(255, 75, 75);--green: #1cad59;--yellow: rgb(220, 165, 0);--dark-red: #d40e1e;--red: #f50000;--kinda-pink: #e40273;--purple: #462191;--shady-blue: #324de6;--nice-blue: #3d5afe;--maybe-cyan: #00b0ff;--teal: #00bcd4;--mint-green: #16c79a;--yellowish-green: #66bb6a;--greenish-yellow: #8bc34a;--dark-teal: #11698e;--tangerine: #ff6f00;--orange: #ff9100;--redish-orange: #ff3d00;color:rgba(var(--text-color), 1);background-color:rgba(var(--background-color), 1);overflow:hidden}body[data-theme=dark]{--accent-color: #6d83ff;--secondary-color: #d60739;--text-color: 200, 200, 200;--foreground-color: 27, 28, 29;--background-color: 21, 22, 22;--danger-color: rgb(255, 106, 106);--green: #00e676;--yellow: rgb(255, 213, 5);--dark-red: #ff5e7e;--red: #ff6098;--kinda-pink: #c44ae6;--purple: #9565f7;--shady-blue: #8295fb;--nice-blue: #6d83ff;--maybe-cyan: #66cfff;--teal: #6aeeff;--mint-green: #4dffd2;--yellowish-green: #9effa2;--greenish-yellow: #c7fc8b;--dark-teal: #51cbff;--tangerine: #ffac6d;--orange: #ffbe68;--redish-orange: #ff8560}body[data-theme=dark] ::-webkit-calendar-picker-indicator{filter:invert(1)}.calistoga{font-weight:400;font-family:"Calistoga",cursive}p,strong{line-height:1.7;color:rgba(var(--text-color), 0.9);max-width:70ch}img{-o-object-fit:cover;object-fit:cover}a:where([class]){color:inherit;text-decoration:none}a:where([class]):focus-visible{box-shadow:0 0 0 .1rem rgba(var(--text-color), 1) inset}a{color:var(--accent-color)}a:-webkit-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:-moz-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}button,.button{-webkit-user-select:none;-moz-user-select:none;user-select:none;position:relative;display:inline-flex;border:none;background-color:rgba(0,0,0,0);overflow:hidden;color:inherit;-webkit-tap-highlight-color:rgba(0,0,0,0);align-items:center;font-size:.9rem;font-weight:500;white-space:nowrap;padding:.8rem;border-radius:.3rem;justify-content:center}button:focus-visible,.button:focus-visible{outline:var(--accent-color) solid medium}button:not(:disabled),.button:not(:disabled){cursor:pointer}.button{background-color:rgba(var(--text-color), 0.02);border:solid thin rgba(var(--text-color), 0.06)}.button--primary{color:rgba(var(--background-color), 1) !important}.button--primary .icon{fill:rgba(var(--background-color), 1)}.button--danger{color:var(--danger-color)}.button--danger .icon{fill:var(--danger-color)}.button--primary{background-color:var(--accent-color)}.button--colored{color:var(--accent-color)}.button--colored .icon{fill:var(--accent-color)}.button--small{padding:.4rem .6rem}.button--outlined{border:solid rgba(var(--text-color), 0.3) .1rem;background-color:rgba(var(--foreground-color), 1)}.button--transparent{background-color:rgba(0,0,0,0)}.cta{text-transform:uppercase;font-size:.8rem;font-weight:700;letter-spacing:.05em;padding:.8rem 1rem}.icon{width:1.2rem;height:1.2rem;fill:rgba(var(--text-color), 0.8);flex-shrink:0}.icon-only{padding:.5rem;border-radius:.3rem;aspect-ratio:1/1}button:disabled{opacity:.5}a:-webkit-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:-moz-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}details summary{display:flex;-webkit-user-select:none;-moz-user-select:none;user-select:none;cursor:pointer;align-items:center;justify-content:space-between;color:var(--accent-color)}details[open] summary{margin-bottom:1rem}details[open]>summary .down-arrow{transform:rotate(180deg)}fieldset{border:none}input{accent-color:var(--accent-color)}input[type=range]:active{cursor:-webkit-grab;cursor:grab}sm-input,sm-textarea,tags-input{--border-radius: 0.5rem;--background-color: rgba(var(--foreground-color), 1)}sm-input button .icon,sm-textarea button .icon,tags-input button .icon{fill:var(--accent-color)}sm-textarea{--max-height: 32ch}sm-button{--padding: 0.8rem}sm-button[variant=primary] .icon{fill:rgba(var(--background-color), 1)}sm-button[disabled] .icon{fill:rgba(var(--text-color), 0.6)}sm-button.danger{--background: var(--danger-color);color:rgba(var(--background-color), 1)}sm-spinner{--size: 1.5rem;--stroke-width: 0.1rem}cube-loader{--size: 1.2rem}sm-form{--gap: 1rem}sm-select{--padding: 0.8rem;--min-width: fit-content;--select-border-radius: 0.5rem}sm-select[open]{z-index:10}sm-option{font-size:.9rem}strip-select{--gap: 0.3rem}strip-option{position:relative;font-size:.9rem;--border-radius: 0.3rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}sm-button{--border-radius: 0.3rem}sm-button[variant=primary] .icon{fill:rgba(var(--background-color), 1)}sm-button[disabled] .icon{fill:rgba(var(--text-color), 0.6)}ul{list-style:none}.overflow-ellipsis{width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.wrap-around{overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;-webkit-hyphens:auto;hyphens:auto}.full-bleed{grid-column:1/-1}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.sticky{position:-webkit-sticky;position:sticky}.top-0{top:0}.flex{display:flex}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.grid{display:grid}.flow-column{grid-auto-flow:column}.gap-0-3{gap:.3rem}.gap-0-5{gap:.5rem}.gap-1{gap:1rem}.gap-1-5{gap:1.5rem}.gap-2{gap:2rem}.gap-3{gap:3rem}.text-align-right{text-align:right}.text-align-left{text-align:left}.align-items-start{align-items:flex-start}.align-content-start{align-content:flex-start}.align-start{align-content:flex-start}.align-center{align-items:center}.align-end{align-items:flex-end}.text-center{text-align:center}.justify-start{justify-items:start}.justify-content-start{justify-content:start}.justify-center{justify-content:center}.justify-right{margin-left:auto}.align-self-center{align-self:center}.align-self-end{align-self:end}.justify-self-center{justify-self:center}.justify-self-start{justify-self:start}.justify-self-end{justify-self:end}.flex-direction-column{flex-direction:column}.space-between{justify-content:space-between}.w-100{width:100%}.h-100{height:100%}.padding-block-1{padding-block:1rem}.margin-right-0-3{margin-right:.3rem}.margin-right-0-5{margin-right:.5rem}.margin-left-0-5{margin-left:.5rem}.margin-left-auto{margin-left:auto}.margin-right-auto{margin-right:auto}.margin-top-1{margin-top:1rem}.margin-bottom-0-5{margin-bottom:.5rem}.margin-bottom-1{margin-bottom:1rem}.margin-bottom-2{margin-bottom:2rem}.margin-block-0-5{margin-block:.5rem}.margin-block-1{margin-block:1rem}.margin-block-1-5{margin-block:1.5rem}.margin-inline-1{margin-inline:1rem}.margin-inline-1-5{margin-inline:1.5rem}.hidden{display:none !important}.no-transformations{transform:none !important}.full-bleed{grid-column:1/4}.h1{font-size:2.5rem}.h2{font-size:2rem}.h3{font-size:1.4rem}.h4{font-size:1rem}.h5{font-size:.8rem}.grid-3{grid-template-columns:1fr auto auto}.flow-column{grid-auto-flow:column}.w-100{width:100%}.color-0-8{color:rgba(var(--text-color), 0.8)}.weight-400{font-weight:400}.weight-500{font-weight:500}.ws-pre-line{white-space:pre-line}.card{background-color:rgba(var(--foreground-color), 1);border-radius:.5rem;padding:max(1rem,3vw)}.ripple{height:8rem;width:8rem;position:absolute;border-radius:50%;transform:scale(0);background:radial-gradient(circle, rgba(var(--text-color), 0.3) 0%, rgba(0, 0, 0, 0) 50%);pointer-events:none}.interact{position:relative;overflow:hidden;cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}.observe-empty-state:empty{display:none}.observe-empty-state:not(:empty)~.empty-state{display:none}.button__icon{height:1.2rem;width:1.2rem}.button__icon--left{margin-right:.5rem}.button__icon--right{margin-left:.5rem}[data-editable]{transition:padding .2s}[data-editable]:focus-within{padding:.5em;border-radius:.3rem;outline:none;background-color:rgba(var(--text-color), 0.06);box-shadow:0 0 0 .1rem var(--accent-color) inset}.multi-state-button{display:grid;text-align:center;align-items:center}.multi-state-button>*{grid-area:1/1/2/2}.multi-state-button button{z-index:1}.password-field label{display:flex;justify-content:center}.password-field label input:checked~.visible{display:none}.password-field label input:not(:checked)~.invisible{display:none}#confirmation_popup,#prompt_popup{flex-direction:column}#confirmation_popup h4,#prompt_popup h4{font-weight:500;margin-bottom:.5rem}#confirmation_popup .flex,#prompt_popup .flex{margin-top:1rem}.popup__header{display:grid;gap:.5rem;width:100%;padding:0 1.5rem 0 .5rem;align-items:center;grid-template-columns:auto 1fr auto}.popup__header__close{padding:.5rem;cursor:pointer}.page{height:100%}.page__header{display:flex;justify-content:space-between;margin-bottom:1.5rem;min-height:8rem}.page__header .grid{margin-top:auto}.page__header h1{margin-top:auto;font-size:2rem}.page-layout{display:grid;gap:1.5rem 0;grid-template-columns:1.5rem minmax(0, 1fr) 1.5rem;align-content:flex-start}.page-layout>*{grid-column:2/3}#secondary_pages{display:grid;width:100%;grid-template-rows:-webkit-min-content minmax(0, 1fr);grid-template-rows:min-content minmax(0, 1fr);grid-template-areas:"header" "content"}#secondary_pages header{padding:1rem;background-color:rgba(var(--foreground-color), 0.3)}#secondary_pages .inner-page{width:100%;height:100%;grid-area:content}.inner-page{gap:1rem;display:grid;position:relative;padding:1rem;grid-template-columns:minmax(0, 1fr);height:100%;background-color:rgba(var(--foreground-color), 0.3)}#landing{padding:0 1rem;overflow-y:auto;padding-bottom:3rem;align-content:flex-start}.landing__card{display:grid;position:relative;flex-shrink:0;margin:0 auto;padding:2rem max(1rem,4vw);border-radius:1rem;align-items:center}.landing__card h1{font-size:max(1.5rem,2vw)}.landing__card img{width:min(100%,16rem)}.landing__card:first-of-type{background-color:#2a2c35;color:#fff}.landing__card:first-of-type h1{mix-blend-mode:soft-light}#landing_tasks_wrapper{margin:0 auto;width:min(100%,48rem)}#display_task_list{margin-top:1rem}#sign_in,#sign_up{justify-items:center;align-content:center}#sign_in section,#sign_up section{margin-top:-8rem;width:min(26rem,100%)}#sign_in sm-form,#sign_up sm-form{margin:2rem 0}#sign_up .h2{margin-bottom:.5rem}.generated-keys-wrapper{padding:1rem;background-color:rgba(var(--foreground-color), 1);border-radius:.5rem}#flo_id_warning{padding-bottom:1.5rem}#flo_id_warning .icon{height:3rem;width:3rem;padding:.8rem;overflow:visible;background-color:#ffc107;border-radius:3rem;fill:rgba(0,0,0,.8)}#task_details{position:fixed;width:100%;height:100%;inset:0;display:grid;overflow:hidden auto;z-index:10}#task_details>*{grid-area:1/1/2/2}#task_details__backdrop{background-color:rgba(0,0,0,.5)}#task_details_wrapper{padding:0 max(1rem,4vw);background-color:rgba(var(--foreground-color), 1);padding-bottom:3rem;max-width:70ch;justify-self:flex-end;box-shadow:-1rem 0 2rem rgba(0,0,0,.1)}#task_description{margin-top:1rem}#main_page{height:100%;grid-template-rows:auto 1fr auto;grid-template-areas:"main-header" "sub-pages" "main-nav"}#sub_page_container{grid-area:sub-pages;height:100%;overflow-y:auto;display:grid}#sub_page_container>*{grid-area:1/1}#main_header{grid-area:main-header;display:flex;gap:1rem;align-items:center;position:-webkit-sticky;position:sticky;padding:1rem;background:rgba(var(--foreground-color), 1);z-index:1}#main_nav{grid-area:main-nav;position:relative;display:flex;align-items:center;background-color:rgba(var(--foreground-color), 1)}.nav-list__item{display:flex;flex-direction:column;align-items:center;width:100%;padding:.5rem 0;-webkit-tap-highlight-color:rgba(0,0,0,0);font-size:.8rem;font-weight:500;color:rgba(var(--text-color), 0.8)}.nav-list__item--active{color:var(--accent-color)}.nav-list__item--active .icon{fill:var(--accent-color)}.nav-list__item--active .icon--outlined{display:none}.nav-list__item--active .icon--filled{display:inline-block}.nav-list__item:not(.nav-list__item--active) .icon--outlined{display:inline-block}.nav-list__item:not(.nav-list__item--active) .icon--filled{display:none}.nav-list__item .icon{margin-bottom:.3rem}.container-card{position:relative;background:rgba(var(--foreground-color), 1);border-radius:.5rem}#sign_in_page{display:grid;position:fixed;z-index:5;top:0;bottom:0;left:0;right:0;place-content:center;background-color:rgba(var(--foreground-color), 1);gap:1rem}.display-task{display:flex;flex-direction:column;gap:.8rem;padding:max(2vw,1rem);border-radius:.5rem;background-color:rgba(var(--foreground-color), 1);width:100%;border:solid .2rem rgba(var(--text-color), 0.8)}.display-task__category{display:inline-flex;padding:.3rem .5rem;background-color:rgba(var(--text-color), 0.06);border-radius:.3rem;font-size:.9rem;color:rgba(var(--text-color), 0.8);text-transform:capitalize;font-weight:500;height:100%;align-items:center}.display-task__category:is(a){color:var(--accent-color)}.display-task__title{font-size:1.2rem}.display-task__description{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;white-space:pre-wrap}.display-task__detail{display:flex;gap:.3rem;background-color:rgba(var(--text-color), 0.06);border-radius:1rem;padding:.4rem .8rem;color:rgba(var(--text-color), 0.8)}.display-task__detail__value{font-weight:500}.display-task p{line-height:1.5}.task{display:grid;grid-template-columns:auto 1fr;margin-right:1rem}.task .task__branch_container{padding-bottom:2rem}.task:last-of-type .left .line{transform:scaleY(0)}.task .left{display:flex;position:relative;justify-content:center;padding-top:.3rem}.task .left .circle{display:inline-flex;position:relative;align-self:flex-start;height:1.4rem;padding:.15rem;aspect-ratio:1/1;border-radius:50%;background:rgba(var(--text-color), 0.1);z-index:1}.task .left .circle .icon{width:100%;height:100%}.task .left .line{position:absolute;left:50%;height:100%;width:2px;transform:translateX(-50%) scaleY(1);background-color:rgba(var(--text-color), 0.4)}.task .right{margin-left:1rem;display:flex;flex-direction:column;width:100%;gap:.7rem}.task .right .apply-cont{width:100%;display:flex;flex-direction:row}.task .right .apply-cont h4{flex:1}.task .right:last-child{margin-bottom:1rem}.task h4{margin-top:.4rem}.task .assigned-interns .assigned-intern{padding:.4rem}.admin-reply__description{max-width:100%}.completed .left .circle{background:rgba(0,200,83,.1254901961)}.completed .left .circle .icon{fill:#00c853}.completed .left .line{background-color:#00c853 !important}.task-title{font-weight:500}.padding{padding:1rem}#dashboard_page{padding-bottom:5rem;grid-template-columns:minmax(0, 1fr);overflow-y:auto;align-content:flex-start}#dashboard_view_selector{border-radius:2rem;margin:0 auto;padding:.3rem;background-color:rgba(var(--text-color), 0.04)}#dashboard_view_selector strip-option{--border-radius: 2rem}.logo{display:flex;align-items:center}.project-card{padding:1rem;margin:.2rem;border-radius:.5rem;font-weight:500;line-height:1.5;text-transform:capitalize;color:rgba(var(--text-color), 0.8)}.intern-card{display:flex;padding:1rem;margin:.2rem;border-radius:.5rem;-webkit-user-select:none;-moz-user-select:none;user-select:none;padding:.8rem 1rem;gap:.8rem;cursor:pointer}.intern-card input{height:1.3em;width:1.3em}.intern-card .icon{height:1rem;width:1rem;margin-left:.2rem}.intern-card__name{flex:1}.intern-card__initials{display:flex;height:2.6rem;width:2.6rem;justify-content:center;align-items:center;border-radius:50%;color:var(--color);font-weight:700;font-size:1rem;text-transform:uppercase;background-color:rgba(var(--text-color), 0.06)}.intern-card__score-wrapper{font-weight:500;font-size:1.2rem}.request-card{display:grid;position:relative;padding:1rem;width:min(64rem,100%);margin:0 auto;gap:.3rem;background-color:rgba(var(--foreground-color), 1);border-radius:.5rem;margin-bottom:.5rem;border:solid rgba(var(--text-color), 0.1) thin}.request-card sm-button{--padding: 0.5rem 0.8rem}.request-card__description{width:100%;font-size:1rem}.reject-app{margin-left:auto;margin-right:.5rem}#updates_page{align-content:flex-start}#updates_page sm-select{--max-height: 50vh}#updates{transition:opacity .3s ease}.intern-update{display:grid;gap:.5rem;padding:1rem;border-radius:.5rem;background-color:rgba(var(--foreground-color), 1)}.update__topic{font-weight:500;font-size:1rem;margin-top:.5rem;text-transform:capitalize;max-width:65ch}.update__sender,.admin-reply__title{font-size:.85rem;font-weight:500;background-color:rgba(var(--text-color), 0.06);padding:.3rem .5rem;margin:0 -0.5rem;border-radius:1rem}.update__time{font-size:.85rem;color:rgba(var(--text-color), 0.8)}.admin-reply{position:relative;padding:1rem;padding-left:1.5rem;margin-left:.5rem;gap:.3rem}.admin-reply::before{content:"";position:absolute;width:.1rem;height:calc(100% - 1rem);left:0;background-color:rgba(var(--text-color), 0.5)}.admin-reply__title{justify-self:flex-start}.container-header{display:flex;align-items:center;width:100%;padding:1rem}.container-header h4{flex:1;font-weight:500}#intern_info_popup .grid>*{justify-self:center}#intern_info_popup #update_intern_score{width:100%;margin-top:1rem}#intern_info__initials{position:relative;height:4rem;width:4rem;font-size:1.3rem;color:var(--color)}#intern_info__name{font-size:1.5rem;margin-bottom:.5rem}.icon--star{fill:var(--orange)}#intern_info__score{font-size:1.5rem}#project_info{flex-direction:column}.branch-button{display:flex;padding:.5rem;border-radius:.2rem;text-transform:capitalize;justify-self:start;align-items:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;font-size:.85rem;font-weight:500}.branch-button--active{opacity:1;color:#fff;background:var(--accent-color)}#task_list{gap:.5rem;padding:1rem 0 1.5rem 0}.task-list-item{display:grid;align-content:flex-start;padding:1rem;gap:.5rem;border-radius:.5rem;background:rgba(var(--foreground-color), 1)}.task-list-item h4{font-weight:500;margin:0}.task-list-item .task-title{line-height:1.6}.task-list-item__task-number{font-size:.8rem;color:rgba(var(--text-color), 0.8);border:solid .1em var(--accent-color);border-radius:.3rem;padding:.2rem .4rem;font-weight:500}.task__branch_container:not(:empty){display:grid;gap:.5rem;padding:.5rem 0}.task__branch_container .branch-button{position:relative;background-color:rgba(0,0,0,0);padding:0;padding-left:2rem;margin:.5rem 0}.task__branch_container .branch-button::before{position:absolute;content:"";top:-50%;left:0;display:inline-flex;width:1rem;height:100%;align-self:flex-start;margin-right:.8rem;border-left:solid;border-bottom:solid;border-width:.15rem;border-color:rgba(var(--text-color), 0.6);border-radius:0 0 0 .2rem}.task__branch_container .branch-button+.branch-button::before{top:calc(-50% - 1.5rem);height:calc(100% + 1.5rem)}.task-option{margin-right:-0.5rem}.task-description{margin:0;overflow-wrap:break-word;word-wrap:break-word}.assigned-interns{display:flex;flex-wrap:wrap;gap:.5rem}.assigned-interns .assigned-intern{-webkit-user-select:none;-moz-user-select:none;user-select:none;display:flex;font-size:.8rem;padding:.2rem 0 .2rem .4rem;border-radius:.2rem;border:1px solid rgba(var(--text-color), 0.24);align-items:center;white-space:nowrap;text-transform:capitalize}.assigned-interns .assigned-intern button{padding:.2rem}.assigned-interns .assigned-intern button .icon{height:1rem;width:1rem}#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:.5rem;transition:.3s opacity;background-color:rgba(var(--foreground-color), 1);box-shadow:0 1rem 2rem rgba(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:.9rem;margin:.2rem;padding:.6rem .8rem;border-radius:.3rem}#task_context li .icon{margin-right:.5rem}#branch_container{display:flex;flex-flow:row wrap;margin:.5rem 0 1rem 0}#intern_list_popup{flex-direction:column}#intern_search_field{margin-bottom:1rem}#intern_list_container{height:100%;overflow-y:auto}#intern_list_container .intern-card{padding:.8rem 0;margin:0}#task_display_container{padding:0 1rem}.displayable-task{padding:1rem;border-radius:.5rem;border:solid thin rgba(var(--text-color), 0.1);background-color:rgba(var(--foreground-color), 1);margin-bottom:.5rem}.displayable-task__project{font-size:.9rem;padding:.2rem .5rem;background-color:rgba(var(--text-color), 0.06);border-radius:.3rem;opacity:.8}#loading{display:grid;text-align:center;place-content:center;justify-items:center;background-color:rgba(var(--foreground-color), 1)}#pinned_project_section{position:relative;overflow:hidden}#project_explorer{padding:0}#project_explorer__right{gap:1rem;align-items:flex-start;align-content:flex-start;padding:1rem}#pin_project_button{margin-left:1rem}#admin_page{position:relative;display:grid;padding:0;height:100%;overflow:hidden;grid-template-rows:auto 1fr}#admin_views{display:grid;height:100%;overflow-y:hidden}#admin_views>*{grid-area:1/1}#project_editing_panel{position:relative;height:100%;padding:0 max(4vw,1rem);overflow-y:auto;padding-bottom:2rem;flex:1}#update_of_project{color:rgba(var(--text-color), 0.8)}#update_of_task{font-size:1.3rem;margin:.4rem 0 1.8rem 0}ul{padding:0;list-style:none}#assigned_task_list{display:grid;gap:1rem;margin-top:1rem;align-content:flex-start;grid-template-columns:minmax(0, 1fr)}.task-card{display:grid;gap:.5rem;padding:1rem;border-radius:.5rem;background-color:rgba(var(--foreground-color), 1)}.task__project-title{font-size:.8rem;margin:0 -0.5em;margin-bottom:.5rem;border-radius:1rem;padding:.3rem .5rem;justify-self:flex-start;color:rgba(var(--text-color), 0.8);background-color:rgba(var(--text-color), 0.06)}.task__title{font-size:1.1rem;margin-bottom:1rem}.task__description{word-wrap:break-word;overflow-wrap:break-word;color:rgba(var(--text-color), 0.8);margin-top:.2rem}.send-update-button,.init-update-replay{color:var(--accent-color);background-color:rgba(var(--text-color), 0.04)}.send-update-button .icon,.init-update-replay .icon{fill:var(--accent-color)}.temp-task{padding:1rem;background-color:rgba(var(--foreground-color), 1);border-radius:.5rem}#internship_requests_list{padding-bottom:2rem}.status-card{display:grid;gap:1rem;padding:1rem;border-radius:.5rem;background-color:rgba(var(--foreground-color), 1)}.status-card__time{font-size:.8rem;color:rgba(var(--text-color), 0.8)}.status-card__status{justify-content:flex-end}.status-card__status .icon{height:1em;width:1em}.status-card.accepted .icon{fill:var(--green)}.status-card.rejected .icon{fill:var(--danger-color)}.status-card.pending .icon{fill:var(--yellow)}#projects_container{display:flex;height:100%;overflow-y:hidden}#projects_container__left{height:100%;overflow-y:auto;width:100%}#projects_container__left .list-container{height:100%;overflow-y:auto;padding-bottom:2rem}#projects_container__left .empty-state{padding:1rem;text-align:center}#update_filters_wrapper{gap:1.5rem}input[type=date]{display:flex;width:100%;padding:.5rem;border:rgba(var(--text-color), 0.2) solid thin;border-radius:.3rem;font-family:inherit;font-size:inherit;color:inherit;background-color:rgba(var(--text-color), 0.06)}input[type=date]:focus{outline:none;box-shadow:0 0 0 .1rem var(--accent-color)}#requests_container{padding:0 1rem;gap:1.5rem;overflow-y:auto}#user_role{justify-self:start;font-size:.7rem;font-weight:500;text-transform:uppercase;letter-spacing:.05em;padding:.4rem .8rem;border-radius:.3rem;border:solid var(--accent-color) thin}#pinned_project_section{display:grid;gap:1rem}#pinned_projects{display:grid;gap:.3rem;grid-template-columns:repeat(auto-fill, minmax(20rem, 1fr))}.pinned-card{color:inherit;display:grid;border-radius:.5rem;padding:1rem;background-color:rgba(var(--foreground-color), 1);grid-template-columns:auto 1fr}.pinned-card .project-icon{display:flex;background-color:rgba(var(--text-color), 0.06);justify-self:start;align-self:flex-start;padding:.8rem;border-radius:2rem;margin-right:.8rem;grid-row:span 3}.pinned-card .project-icon .icon{fill:var(--accent-color)}.pinned-card .project__title{font-weight:500;color:rgba(var(--text-color), 0.9)}.pinned-card .project__title:hover{color:var(--accent-color)}.pinned-card .project__complete-percent{font-size:.8rem;opacity:.8;margin-top:.5rem}.progress-bar{display:flex;height:.2rem;background-color:rgba(var(--text-color), 0.2);border-radius:1rem;overflow:hidden;align-self:flex-end}.progress-bar .progress-value{background-color:var(--accent-color);transition:width .3s}#settings_page{align-content:flex-start}#settings_page>*{width:min(48rem,100%);margin:0 auto}@media only screen and (max-width: 640px){.list-container{padding-bottom:5rem}.status-card__status{grid-area:1/2/2/3}.status-card__details{grid-area:2/1/3/3}.landing__card:first-of-type{text-align:center;justify-items:center}.landing__card:first-of-type .flex{justify-content:center}.landing__card:first-of-type img{grid-area:1/1/2/2}#task_search_input{width:100%}.hide-on-mobile,.hide-page-on-mobile{display:none}}@media only screen and (min-width: 640px){.hide-on-desktop{display:none !important}sm-popup{--width: 26rem}.popup__header{padding:1.5rem 1.5rem 0 .75rem}#secondary_pages header{padding:1.5rem 8vw}.landing__card{grid-template-columns:1fr auto}.landing__card img{justify-self:flex-end}#task_details .button--primary{width:-webkit-max-content;width:-moz-max-content;width:max-content}#main_nav{padding:.5rem;background-color:rgba(var(--background-color), 1);flex-direction:column}#main_nav theme-toggle{margin:1rem;margin-top:auto}.nav-list__item{flex-direction:row;align-items:center;border-radius:.5rem;padding:.8rem;margin-bottom:.25rem;font-size:1rem}.nav-list__item--active{background-color:rgba(var(--text-color), 0.06)}.nav-list__item .icon{margin-bottom:0}.nav-list__item_title{display:none}.project-card--active{background-color:rgba(var(--text-color), 0.1)}.project-card--active::before{content:"";position:absolute;top:0;left:0;bottom:0;margin:auto 0;width:.2rem;height:1.5em;background-color:var(--accent-color);border-radius:0 .2rem .2rem 0}#sign_in{width:24rem;height:auto;border-radius:.4rem}#dashboard_page{grid-template-columns:1fr 18rem}#dashboard_page>:not(#best_interns_container,#dashboard_view_selector){grid-column:1;width:min(48rem,100%);margin:0 auto}#best_interns_container{position:-webkit-sticky;position:sticky;top:0;grid-column:2;grid-row:1/4;align-self:flex-start}#all_interns_page__header{grid-template-columns:1fr auto}#admin_page{padding:0}#projects_container__left{width:18rem}#project_explorer{display:grid;height:100%;gap:0;grid-template-columns:16rem 3fr;grid-template-areas:"left right";background-color:rgba(var(--foreground-color), 0.3);overflow-y:auto}#project_explorer__left{grid-area:left;height:100%;overflow-y:auto;padding-bottom:1.5rem}#project_explorer__left h4{margin-top:0;margin-bottom:.5rem;color:var(--accent-color);font-size:.9rem}#project_explorer__right{grid-area:right;height:100%;overflow-y:auto;padding:1.5rem 4vw;background-color:rgba(var(--foreground-color), 0.5)}#main_page{grid-template-columns:4rem minmax(0, 1fr);grid-template-areas:"main-header main-header" "main-nav sub-pages"}#post_update_popup{--width: 28rem}#updates_page{height:100%;gap:1rem;grid-template-areas:"updates update-filters";grid-template-columns:minmax(0, 1fr) 20rem;overflow-y:hidden}#update_filters_wrapper{padding:1rem;border-radius:.5rem;align-content:flex-start;grid-area:update-filters;background-color:rgba(var(--foreground-color), 1)}#updates_wrapper{height:100%;overflow-y:auto;grid-area:updates}#all_interns_list{gap:.5rem;grid-template-columns:repeat(auto-fill, minmax(16rem, 1fr))}#all_interns_list .intern-card{margin:0;gap:1rem;border-radius:.5rem;background-color:rgba(var(--foreground-color), 1)}#intern_list_popup{--height: 80vh}.status-card{align-items:center;font-size:.9rem;grid-template-columns:6rem 1fr 8rem}#requests_container{padding:1rem;grid-template-columns:14rem 1fr}#requests_container>:nth-child(2){width:min(48rem,100%);margin:0 auto}}@media only screen and (min-width: 1280px){#main_page{grid-template-columns:12rem minmax(0, 1fr);grid-template-areas:"main-header main-header" "main-nav sub-pages"}#main_nav{align-items:flex-start}.nav-list__item .icon{margin-right:.5rem}.nav-list__item_title{display:inline-block}}@media(any-hover: hover){::-webkit-scrollbar{width:.5rem;height:.5rem}::-webkit-scrollbar-thumb{background:rgba(var(--text-color), 0.3);border-radius:1rem}::-webkit-scrollbar-thumb:hover{background:rgba(var(--text-color), 0.5)}.interact{transition:background-color .2s}.interact:hover{background-color:rgba(var(--text-color), 0.04)}} \ No newline at end of file diff --git a/css/main.scss b/css/main.scss index 2808ced..aa63be3 100644 --- a/css/main.scss +++ b/css/main.scss @@ -80,7 +80,6 @@ body[data-theme="dark"] { p, strong { line-height: 1.7; - font-size: 0.9rem; color: rgba(var(--text-color), 0.9); max-width: 70ch; } @@ -234,14 +233,9 @@ input { } } -sm-copy { - font-size: 0.9rem; -} - sm-input, sm-textarea, tags-input { - font-size: 0.9rem; --border-radius: 0.5rem; --background-color: rgba(var(--foreground-color), 1); @@ -291,7 +285,6 @@ sm-form { sm-select { --padding: 0.8rem; - font-size: 0.9rem; --min-width: fit-content; --select-border-radius: 0.5rem; &[open] { @@ -1006,7 +999,6 @@ ul { background-color: rgba(var(--text-color), 0.06); border-radius: 1rem; padding: 0.4rem 0.8rem; - font-size: 0.9rem; color: rgba(var(--text-color), 0.8); &__value { font-weight: 500; @@ -1468,6 +1460,24 @@ ul { margin: 0; } } +#task_display_container { + padding: 0 1rem; +} +.displayable-task { + padding: 1rem; + border-radius: 0.5rem; + border: solid thin rgba(var(--text-color), 0.1); + background-color: rgba(var(--foreground-color), 1); + margin-bottom: 0.5rem; + &__project { + font-size: 0.9rem; + padding: 0.2rem 0.5rem; + background-color: rgba(var(--text-color), 0.06); + border-radius: 0.3rem; + opacity: 0.8; + } +} + #loading { display: grid; text-align: center; @@ -1566,7 +1576,6 @@ ul { word-wrap: break-word; overflow-wrap: break-word; color: rgba(var(--text-color), 0.8); - font-size: 0.9rem; margin-top: 0.2rem; } } diff --git a/index.html b/index.html index 905e33a..631dd6f 100644 --- a/index.html +++ b/index.html @@ -309,7 +309,8 @@ Projects Interns - Requests + Task display + Requests - - + + + \ No newline at end of file diff --git a/scripts/app_ui.js b/scripts/app_ui.js deleted file mode 100644 index 2183808..0000000 --- a/scripts/app_ui.js +++ /dev/null @@ -1,1608 +0,0 @@ - floGlobals.taskCategories = { - c00: 'Creative Writing', - c01: 'Marketing', - c02: 'Design', - c03: 'Development', - c04: 'Social Media Management', - c05: 'Video Making', - } - const render = { - displayTaskCard(projectCode, branch, task) { - projectCode = projectCode - const taskDetails = { title, description, category, maxSlots, duration, durationType, reward } = RIBC.getTaskDetails(projectCode, branch, task) - return html` -
  • - -

    ${title}

    -
    - ${duration ? html` -
    - Duration: - ${duration} ${durationType} -
    - `: ''} - ${maxSlots ? html` -
    - Slots: - ${maxSlots} -
    - `: ''} - ${reward ? html` -
    - Reward: - ₹${reward} -
    - `: ''} -
    -
  • - `; - }, - displayTasks(category, searchQuery) { - // render tasks - const allTasks = RIBC.getAllTasks() - const filterCategory = category === 'all' ? false : category; - const filtered = [] - const availableCategories = new Set(); - for (const taskId in allTasks) { - const [projectCode, branch, task] = taskId.split('_') - if (filterCategory && allTasks[taskId].category !== filterCategory) continue; - if (RIBC.getTaskStatus(projectCode, branch, task) !== 'incomplete') continue; - if (searchQuery && searchQuery !== '' && !allTasks[taskId].title.toLowerCase().includes(searchQuery.toLowerCase())) continue; - if (RIBC.getAssignedInterns(projectCode, branch, task).length >= allTasks[taskId].maxSlots) continue; - if (typeOfUser && typeOfUser === 'intern' && floDapps.user.id && RIBC.getAssignedInterns(projectCode, branch, task).includes(floDapps.user.id)) continue; - filtered.push(render.displayTaskCard(projectCode, branch, task)) - availableCategories.add(allTasks[taskId].category) - } - let renderedTasks = filtered.reverse() - if (searchQuery && filtered.length === 0) { - renderedTasks = html`

    No tasks related to ${searchQuery}

    ` - } - // render categories - let renderedCategories = [] - if (availableCategories.size > 1) { - renderedCategories = [html`All`]; - availableCategories.forEach(categoryID => { - categories.push(html`${floGlobals.taskCategories[categoryID]}`) - }) - } - setTimeout(() => { - if (document.getElementById('task_search_input') && document.getElementById('task_search_input').value.trim() !== searchQuery) - document.getElementById('task_search_input').value = searchQuery || '' - }, 0); - return html` -
    -
    -

    - Available Tasks -

    - ${(filtered.length > 0 || searchQuery) ? html` - - - - `: ''} -
    - ${availableCategories.size > 1 ? html`${renderedCategories}` : ''} -
    -
    - -
    -

    Nothing to see here

    -
    -
    - `; - }, - projectCard(projectCode, isAdmin = false, ref) { - const projectName = RIBC.getProjectDetails(projectCode).projectName - const page = isAdmin ? 'admin_page' : 'project_explorer' - return html.for(ref, projectCode)`${projectName}` - }, - taskCard(task) { - const taskDetails = { title, description, category, maxSlots, duration, durationType, reward } = RIBC.getTaskDetails(appState.params.id, appState.params.branch, task) - const branches = getAllBranches(appState.params.id) - const branchesButtons = filterMap(branches, (branch) => { - const { branchName, parentBranch, startPoint, endPoint } = branch - if (parentBranch === appState.params.branch && startPoint === task) { - return render.branchButton({ - projectCode: appState.params.id, - branch: branchName, - page: 'project_explorer' - }) - } - }) - const assignedInterns = RIBC.getAssignedInterns(appState.params.id, appState.params.branch, task) || [] - const assignedInternsCards = filterMap(assignedInterns, (internFloId) => render.assignedInternCard(internFloId)); - const status = RIBC.getTaskStatus(appState.params.id, appState.params.branch, task) - let applyButton - if (!assignedInterns.includes(myFloID) && typeOfUser !== 'admin') { - const hasApplied = [...RIBC.getTaskRequests(false), ...sessionTaskRequests].find(({ details }) => { - return `${appState.params.id}_${appState.params.branch}_${task}` === details.taskId - }) - applyButton = html` - `; - } - const linkifyDescription = createElement('p', { - innerHTML: DOMPurify.sanitize(linkify(description)), - className: `timeline-task__description ws-pre-line wrap-around` - }) - return html` -
    -
    -
    - -
    -
    -
    -
    -
    -

    ${title}

    - ${applyButton} -
    - ${assignedInternsCards.length ? html`
    ${assignedInternsCards}
    ` : ''} -
    - Task details - ${linkifyDescription} -
    -
    - ${duration ? html` -
    - Duration: - ${duration} ${durationType} -
    - `: ''} - ${maxSlots ? html` -
    - Slots: - ${maxSlots} -
    - `: ''} - ${reward ? html` -
    - Reward: - ₹${reward} -
    - `: ''} - ${branchesButtons.length ? html`
    ${branchesButtons}
    ` : ''} -
    -
    - `; - }, - internCard(internFloId, { selectable = false } = {}) { - const internName = RIBC.getInternList()[internFloId] - const internPoints = RIBC.getInternRating(internFloId) - const initials = internName.split(' ').map(v => v.charAt(0)).join(''); - return html` - `; - }, - internUpdateCard(update) { - const { floID, time, note, update: { projectCode, branch, task, description, link } } = update - let topic = `${RIBC.getProjectDetails(projectCode).projectName} / ${RIBC.getTaskDetails(projectCode, branch, task).title}` - const internName = RIBC.getInternList()[floID] - let replyButton - if (typeOfUser === 'admin' && !note) { - replyButton = html`` - } - let providedLink - if (link) { - providedLink = html`${link} ` - } - let adminReply - if (note) { - adminReply = html`
    -

    Admin

    -

    ${note}

    -
    ` - } - return html.node` -
  • -
    - ${internName} - ${getFormattedTime(time)} -
    -

    ${topic}

    -

    ${description}

    - ${providedLink} - ${replyButton} - ${adminReply} -
  • `; - }, - branchButton(obj = {}) { - const { projectCode, branch, page, active = false } = obj - return html` - - ${branch} - - `; - }, - assignedInternCard(internFloId, options) { - let optionsButton - if (options) { - optionsButton = html` `; - } - return html` - - ${RIBC.getInternList()[internFloId]} - ${optionsButton} - - ` - }, - taskListItem(task, ref) { - 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) - let assignedInternsCards - if (assignedInterns) { - assignedInternsCards = filterMap(assignedInterns, (internFloId) => render.assignedInternCard(internFloId, true)) - } - const branches = getAllBranches(appState.params.id) - const branchesButtons = filterMap(branches, (branch) => { - const { branchName, parentBranch, startPoint, endPoint } = branch - if (parentBranch === appState.params.branch && startPoint === task) { - return render.branchButton({ - projectCode: appState.params.id, - branch: branchName, - page: 'admin_page' - }) - } - }) - const categories = []; - for (const categoryID in floGlobals.taskCategories) { - categories.push(html`${floGlobals.taskCategories[categoryID]}`) - } - const taskDescription = createElement('p', { - className: 'task-description ws-pre-line wrap-around', - attributes: { - 'data-editable': '', - 'data-edit-field': 'description', - }, - innerHTML: DOMPurify.sanitize(description) - }) - return html.for(ref, `${appState.params.id}_${appState.params.branch}_${task}`)` -
  • -
    -
    - -

    Mark as complete

    -
    -
    ID: ${task}
    -
    - - -
    -

    ${title}

    -
    - - ${assignedInternsCards} -
    - ${taskDescription} -
    - ${categories} -
    - - - - - Days - Months - -
    - - - - -
    - ${branchesButtons.length ? html`
    ${branchesButtons}
    ` : ''} -
  • - `; - }, - taskRequestCard(request) { - const { details: { taskId, name, brief, contact, portfolioLink }, floID, vectorClock } = request - const internName = RIBC.getInternList()[floID]; - const [projectCode, branch, task] = taskId.split('_'); - const { category } = RIBC.getTaskDetails(projectCode, branch, task); - return html` -
  • -
    ${floGlobals.taskCategories[category]}
    -

    - ${internName || name} applied for - ${RIBC.getTaskDetails(projectCode, branch, task).title} -

    - ${!internName ? html` -
    - ${brief ? html` -
    -
    Educational background
    -

    ${brief}

    -
    - ` : ''} - ${contact ? html` -
    -
    Contact
    - -
    - ` : ''} - ${portfolioLink ? html` -
    -
    Portfolio link
    - ${portfolioLink} -
    - ` : ''} -
    - ` : ''} -
    - - -
    -
  • - `; - }, - internTaskCard(uniqueId) { - const [projectCode, branch, task] = uniqueId.split('_'); - const { title, description } = RIBC.getTaskDetails(projectCode, branch, task) - const projectName = RIBC.getProjectDetails(projectCode).projectName - const linkifyDescription = createElement('p', { - innerHTML: DOMPurify.sanitize(linkify(description)), - className: `timeline-task__description ws-pre-line wrap-around` - }) - return html` -
  • - ${projectName} -
    -

    ${title}

    - ${linkifyDescription} -
    - -
  • - `; - }, - dashProject(projectCode, ref) { - const { projectName } = RIBC.getProjectDetails(projectCode) - const projectMap = RIBC.getProjectMap(projectCode) - const projectTasks = [] - RIBC.getProjectBranches(projectCode).forEach(branch => { - projectMap[branch].slice(4).forEach((task) => { - projectTasks.push(RIBC.getTaskStatus(projectCode, branch, task)) - }) - }) - const completedTasks = projectTasks.filter(task => task === 'completed').length - let completePercent = parseFloat(((completedTasks / (projectTasks.length || 1)) * 100).toFixed(2)) - const isPinned = pinnedProjects.includes(projectCode); - let pinIcon = '' - if (isPinned) { - pinIcon = html` `; - } else { - pinIcon = html` `; - } - return html.for(ref, projectCode)` -
    -
    - -
    -
    - -

    ${projectName}

    - -
    - -
    -
    -
    -
    - ${completePercent}% complete -
    - ` - }, - dashProjects(where, projects) { - renderElem(where, html`${projects.map(project => render.dashProject(project, where))} `) - }, - internRequests() { - const requestCategories = new Set() - const requestProjects = new Set() - const shouldFilterByProject = getRef('filter_requests_by_project').value !== 'all' ? getRef('filter_requests_by_project').value : false; - const shouldFilterByCategory = getRef('filter_requests_by_category').value !== 'all' ? getRef('filter_requests_by_category').value : false; - let requestCards = filterMap(RIBC.getTaskRequests().reverse(), (request) => { - if (Array.isArray(request.details) || !request.details.taskId) return; - const [projectCode, branch, task] = request.details.taskId.split('_') - const taskDetails = RIBC.getTaskDetails(projectCode, branch, task) - if (!taskDetails) return; - requestCategories.add(RIBC.getTaskDetails(projectCode, branch, task).category) - requestProjects.add(projectCode) - if (shouldFilterByCategory && taskDetails.category !== shouldFilterByCategory) return; - if (shouldFilterByProject && projectCode !== shouldFilterByProject) return; - return render.taskRequestCard(request) - }) - renderElem(getRef('requests_list'), html`${requestCards}`) - if (requestCategories.size) { - const categoryOptions = [...requestCategories].map(cat => html`${floGlobals.taskCategories[cat]}`); - renderElem(getRef('filter_requests_by_category'), html`${[html`All`, ...categoryOptions]}`) - } - if (requestProjects.size) { - const projectOptions = [...requestProjects].map(project => html`${RIBC.getProjectDetails(project).projectName}`); - renderElem(getRef('filter_requests_by_project'), html`${[html`All`, ...projectOptions]}`) - } - if (requestCategories.size || requestProjects.size) { - getRef('requests_container__filters').classList.remove('hidden') - } else { - getRef('requests_container__filters').classList.add('hidden') - } - }, - projectList(container, projects, isAdminList = false) { - renderElem(container, html`${projects.map(projectCode => render.projectCard(projectCode, isAdminList, container))}`) - }, - requestStatus(request) { - if (Array.isArray(request.details) || !request.details.taskId) return - const { details: { taskId }, status, vectorClock } = request; - const [projectCode, branch, task] = taskId.split('_'); - if (!RIBC.getTaskDetails(projectCode, branch, task)) return - const timestamp = parseInt(vectorClock.split('_')[0]) - let icon = '' - if (status === 'Accepted') { - icon = html`` - } else if (status === 'Rejected') { - icon = html`` - } else { - icon = html`` - } - return html` -
  • - -

    - You applied for ${RIBC.getTaskDetails(projectCode, branch, task).title} -

    -
    - ${icon} - ${status || 'Under review'} -
    -
  • - `; - }, - taskApplications() { - const taskRequests = RIBC.getTaskRequests(false) - taskRequests.sort((a, b) => { - return parseInt(b.vectorClock.split('_')[0]) - parseInt(a.vectorClock.split('_')[0]) - }) - const taskCards = filterMap(taskRequests, request => render.requestStatus(request)) - renderElem(getRef('task_requests_list'), html`${taskCards}`) - } - } - const selectedColors = [ - '--dark-red', - '--red', - '--kinda-pink', - '--purple', - '--shady-blue', - '--nice-blue', - '--maybe-cyan', - '--teal', - '--mint-green', - '--greenish-yellow', - '--yellowish-green', - '--dark-teal', - '--orange', - '--tangerine', - '--redish-orange', - ] - function randomColor() { - return selectedColors[Math.floor(Math.random() * selectedColors.length)]; - } - const renderedIntensColor = {} - function getInternColor(floId) { - if (!renderedIntensColor[floId]) { - renderedIntensColor[floId] = randomColor() - } - return renderedIntensColor[floId] - } - - const filterTasks = debounce((e) => { - const searchQuery = getRef('task_search_input').value.trim(); - const category = getRef('task_category_selector')?.value || 'all'; - window.location.hash = `#/${appState.currentPage}?category=${category}${searchQuery !== '' ? `&search=${searchQuery}` : ''}`; - }, 100) - - function showTaskDetails(taskId) { - const [projectCode, branch, task] = taskId.split('_') - const { title, description, category, maxSlots, duration, durationType, reward } = RIBC.getTaskDetails(projectCode, branch, task) - let hasApplied = false - try { - floDapps.user.id - hasApplied = [...RIBC.getTaskRequests(false), ...sessionTaskRequests].find(({ details }) => { - return taskId === details.taskId - }) - } catch (e) { } - const descriptionTag = createElement('p', { - innerHTML: DOMPurify.sanitize(linkify(description)), - className: 'ws-pre-line wrap-around' - }) - descriptionTag.id = 'task_description' - renderElem(getRef('task_details_wrapper'), html` -
    - -
    -
    -
    ${floGlobals.taskCategories[category]}
    -

    ${title}

    -
    - ${duration ? html` -
    - Duration: - ${duration} ${durationType} -
    - `: ''} - ${maxSlots ? html` -
    - Slots: - ${maxSlots} -
    - `: ''} - ${reward ? html` -
    - Reward: - ₹${reward} -
    - `: ''} -
    - ${descriptionTag} -
    - ${!hasApplied ? html` - - `: ''} - `); - getRef('task_details').classList.remove('hidden') - const animOptions = { - duration: floGlobals.prefersReducedMotion ? 0 : 300, - easing: 'ease', - fill: 'forwards' - } - getRef('task_details__backdrop').animate([ - { opacity: 0 }, - { opacity: 1 } - ], animOptions) - getRef('task_details_wrapper').animate([ - { transform: 'translateX(100%)' }, - { transform: 'translateX(0)' } - ], animOptions) - if (appState.currentPage === 'landing') { - getRef('landing').animate([ - { transform: 'translateX(0)' }, - { transform: 'translateX(-10%)' } - ], animOptions) - } - } - function hideTaskDetails() { - if (getRef('task_details').classList.contains('hidden')) return; - history.replaceState(null, null, `#/${appState.currentPage}`); - const animOptions = { - duration: floGlobals.prefersReducedMotion ? 0 : 300, - easing: 'ease', - fill: 'forwards' - } - getRef('task_details__backdrop').animate([ - { opacity: 1 }, - { opacity: 0 } - ], animOptions).onfinish = () => { - getRef('task_details').classList.add('hidden') - renderElem(getRef('task_details_wrapper'), html``) - } - getRef('task_details_wrapper').animate([ - { transform: 'translateX(0)' }, - { transform: 'translateX(100%)' } - ], animOptions) - if (appState.currentPage === 'landing') { - getRef('landing').animate([ - { transform: 'translateX(-10%)' }, - { transform: 'translateX(0)' }, - ], animOptions) - } - } - - let pinnedProjects = []; - let currentIntern; - let typeOfUser = 'general'; - - function handleDashboardViewChange(e) { - document.querySelectorAll('.dashboard-view__item').forEach(item => { - if (item.id === 'best_interns_container') - item.classList.add('hide-on-mobile') - else - item.classList.add('hidden') - }) - document.querySelector(`#${e.target.value}`).classList.remove('hide-on-mobile', 'hidden') - } - - - // Adds interns to the database **Only SubAdmins can add interns - function addInternToList() { - let internName = getRef('intern_name_field').value.trim(), - internFloId = getRef('intern_flo_id_field').value.trim(); - if (RIBC.admin.addIntern(internFloId, internName)) { - renderElem(getRef('admin_page__intern_list'), filterInterns('')) - closePopup(); - notify(`${internName} added as an intern.`, 'success') - } - } - function addProjectToList() { - let projectName = getRef('project_name_field').value.trim(), - projectDescription = getRef('project_description_field').value.trim(); - if (projectName === '') { - return notify('Project name is important!', 'error') - } - if (projectDescription === '') { - return notify('Project description is important!', 'error') - } - const projectCode = `${new Date().getFullYear()}-project-${RIBC.getProjectList() ? (RIBC.getProjectList().length + 1) : '1'}`; - RIBC.admin.createProject(projectCode) - RIBC.admin.addProjectDetails(projectCode, { projectName, projectDescription }) - render.projectList(getRef('admin_page__project_list'), getSortedProjectList(), true) - getRef('admin_page__project_list').querySelector(`[href="#/admin_page/project?id=${projectCode}&branch=mainLine"]`)?.click() - closePopup(); - } - - function makeEditable(elem) { - floGlobals.tempEditableContent = DOMPurify.sanitize(elem.innerHTML.trim()) - elem.contentEditable = true - elem.focus() - document.execCommand('selectAll', false, null); - } - - getRef('project_details_wrapper').addEventListener('dblclick', e => { - if (e.target.closest('[data-editable]') && !e.target.closest('[data-editable]').isContentEditable) { - makeEditable(e.target.closest('[data-editable]')) - } - }) - getRef('project_details_wrapper').addEventListener('focusout', (e) => { - if (e.target.isContentEditable) { - e.target.contentEditable = false - if (e.target.innerHTML.trim() !== '' && floGlobals.tempEditableContent !== DOMPurify.sanitize(e.target.innerHTML.trim())) { - const newTitle = DOMPurify.sanitize(getRef('editing_panel__title').innerHTML.trim()) - const newDescription = DOMPurify.sanitize(getRef('editing_panel__description').innerHTML.trim()) - RIBC.admin.addProjectDetails(appState.params.id, { projectName: newTitle, projectDescription: newDescription }) - notify('Changes saved locally, commit the changes to make them permanent', 'success') - render.projectList(getRef('admin_page__project_list'), getSortedProjectList(), true) - } else { - e.target.innerHTML = floGlobals.tempEditableContent - } - } - }) - - // opens a popup containing various intern information - function showInternInfo(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)})`) - getRef('intern_info__name').textContent = internName; - getRef('intern_info__flo_id').value = currentIntern = internFloId; - getRef('intern_info__score').textContent = RIBC.getInternRating(internFloId); // points earned by intern - if (RIBC.getInternRating(internFloId) === 1) { - getRef('reduce_score_button').disabled = true; - } - openPopup('intern_info_popup'); - } - - // opens a popup containing various project information - function showProjectInfo(projectCode) { - const { projectName, projectDescription } = RIBC.getProjectDetails(projectCode); - getRef('project_explorer__project_title').textContent = projectName; // project name - getRef('project_explorer__project_description').textContent = projectDescription; - getRef('project_explorer__project_updates').href = `#/updates_page?projectCode=${projectCode}&internId=all`; - renderBranches(); - } - - let currentTask = ''; - function renderAdminProjectView(projectCode) { - const allProjects = getRef('admin_page__project_list').querySelectorAll('.project-card'); - allProjects.forEach(project => project.classList.remove('project-card--active')) - const targetProject = Array.from(allProjects).find(project => project.getAttribute('href').includes(projectCode)) - if (targetProject) - targetProject.classList.add('project-card--active') - const { projectName, projectDescription } = RIBC.getProjectDetails(projectCode); - getRef('editing_panel__title').textContent = projectName; - getRef('editing_panel__description').textContent = projectDescription; - renderBranches() - } - function renderBranches() { - const { id: projectCode, branch } = appState.params - const taskListContainer = appState.currentPage === 'admin_page' ? 'branch_container' : 'explorer_branch_container'; - const branchList = filterMap(RIBC.getProjectBranches(appState.params.id), (branch) => { - return render.branchButton({ projectCode, branch, page: appState.currentPage, active: branch === appState.params.branch }) - }) - if (branchList.length > 1) { - renderElem(getRef(taskListContainer), html`${branchList}`) - getRef(taskListContainer).classList.remove('hidden') - } else { - getRef(taskListContainer).classList.add('hidden') - } - } - function renderBranchTasks() { - const { id: projectCode, branch } = appState.params - const taskListContainer = appState.currentPage === 'admin_page' ? 'task_list' : 'explorer_task_list'; - let branchTasks = RIBC.getProjectMap(appState.params.id)[appState.params.branch]; - if (branchTasks[1] && !taskListContainer === 'task_list') { - getRef(taskListContainer).textContent = "No tasks added yet, Please explore other projects" - } else { - let tasks = [] - if (branch !== 'mainLine') { - const { startPoint, parentBranch } = getAllBranches(projectCode).find(({ branchName }) => branchName === branch) - tasks.push(html`

    - Branched off from ${parentBranch} -

    `) - } - if (taskListContainer === 'task_list') { - branchTasks.slice(4).forEach((task) => tasks.push(render.taskListItem(task, getRef(taskListContainer)))) - } else { - branchTasks.slice(4).forEach((task) => tasks.push(render.taskCard(task))) - } - renderElem(getRef(taskListContainer), html`${tasks}`) - } - } - function getAllBranches(projectCode) { - const projectMap = RIBC.getProjectMap(projectCode) - const projectBranches = RIBC.getProjectBranches(projectCode) - return projectBranches.slice(1).map((branchName, index) => { - const [parentBranch, , startPoint, endPoint] = projectMap[branchName] - return { - branchName, - parentBranch, - startPoint, - endPoint - } - }) - } - - let currentViewIndex = 0; - getRef('admin_view_selector').addEventListener('change', (e) => { - 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); - }) - - function toggleEditing(target) { - if (target === 'title') { - makeEditable(currentTask.querySelector('.task-title')) - } else { - makeEditable(currentTask.querySelector('.task-description')) - } - } - function formatAmount(amount = 0, currency = 'inr') { - if (!amount) - return '₹0'; - return amount.toLocaleString(currency === 'inr' ? `en-IN` : 'en-US', { style: 'currency', currency, maximumFractionDigits: 0 }) - } - delegate(getRef('task_list'), 'change', 'sm-checkbox', (e) => { - currentTask = e.target.closest('.task-list-item'); - const taskStatus = e.target.checked ? 'completed' : 'incomplete' - RIBC.admin.putTaskStatus(taskStatus, appState.params.id, appState.params.branch, currentTask.dataset.taskId) - }) - delegate(getRef('task_list'), 'change', 'sm-select', (e) => { - currentTask = e.target.closest('.task-list-item'); - const taskDetails = { - [e.target.dataset.editField]: e.target.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') - }) - getRef('task_list').addEventListener('focusout', (e) => { - currentTask = e.target.closest('.task-list-item'); - if (!currentTask) return; - const ogTaskDetails = RIBC.getTaskDetails(appState.params.id, appState.params.branch, currentTask.dataset.taskId) - const newTaskDetails = {} - let valid = false; - if (e.target.isContentEditable) { - e.target.contentEditable = false - newTaskDetails[e.target.dataset.editField] = DOMPurify.sanitize(e.target.innerHTML.trim()) - valid = true; - } else if (e.target.closest('sm-input')) { - newTaskDetails[e.target.dataset.editField] = parseInt(e.target.value) - valid = true; - } - if (!valid) 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) - notify('Changes saved locally, commit the changes to make them permanent', 'success') - } - }) - getRef('task_list').addEventListener('dblclick', (e) => { - if (e.target.closest('[data-editable]') && !e.target.closest('[data-editable]').isContentEditable) { - makeEditable(e.target.closest('[data-editable]')) - } - }) - getRef('task_list').addEventListener('click', (e) => { - if (e.target.closest('.task-list-item')) { - currentTask = e.target.closest('.task-list-item'); - } - 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('.assigned-intern button')) { - getConfirmation('Do you want to unassign this intern from this task?', { confirmText: 'Unassign' }).then((result) => { - if (result) { - RIBC.admin.unassignInternFromTask(e.target.closest('.assigned-intern').dataset.floId, appState.params.id, appState.params.branch, currentTask.dataset.taskId) - notify('Intern removed from the task') - renderBranchTasks() - } - }) - } - else if (e.target.closest('.cancel-task-button')) { - const card = e.target.closest('.temp-task') - card.remove(); - getRef('add_task').classList.remove('hidden') - } - else if (e.target.closest('.add-task-button')) { - const card = e.target.closest('.temp-task') - const title = card.querySelector('.temp-task__title').value.trim(); - const description = card.querySelector('.temp-task__description').value.trim(); - const category = card.querySelector('.temp-task__category').value.trim(); - const maxSlots = parseInt(card.querySelector('.temp-task__max-slots').value.trim()); - const duration = parseInt(card.querySelector('.temp-task__duration').value.trim()); - const durationType = card.querySelector('.temp-task__duration-type').value.trim(); - const reward = parseInt(card.querySelector('.temp-task__reward').value.trim()); - if (title === '') { - return notify('Please enter task title', 'error') - } - if (description === '') { - return notify('Please enter description of the task', 'error') - - } - const taskDetails = { - title, - description, - category, - maxSlots, - duration, - durationType, - reward - } - const task = RIBC.admin.addTaskInMap(appState.params.id, appState.params.branch) - RIBC.admin.editTaskDetails(taskDetails, appState.params.id, appState.params.branch, task) - RIBC.admin.putTaskStatus('incomplete', appState.params.id, appState.params.branch, task) - card.remove() - renderBranchTasks() - getRef('add_task').classList.remove('hidden') - notify('Task added to current branch', 'success') - } - }) - function addPlaceholderTask() { - const categories = []; - let first = true; - for (const categoryID in floGlobals.taskCategories) { - categories.push(html`${floGlobals.taskCategories[categoryID]}`) - first = false; - } - const placeholderTask = html.node` -
    - - - -
    - ${categories} - -
    - - - - - Days - Months - -
    - - - -
    -
    - - -
    -
    -
    - `; - getRef('task_list').append(placeholderTask) - getRef('task_list').querySelector('.temp-task__title').focusIn() - getRef('add_task').classList.add('hidden') - getRef('task_list').lastElementChild.scrollIntoView({ behavior: "smooth" }); - } - function commitToChanges() { - getConfirmation("Do you want to commit to changes?").then((result) => { - if (result) { - RIBC.admin.updateObjects().then(res => { - notify('Changes committed.', 'success') - }).catch(err => { - console.error(err) - }) - } - }) - } - function removeThisTask() { - getConfirmation("Are you sure to delete this task?", { confirmText: 'Delete' }).then((result) => { - if (result) { - RIBC.admin.deleteTaskInMap(appState.params.id, appState.params.branch, currentTask.dataset.taskId) - renderBranchTasks() - } - }) - } - floGlobals.selectedInterns = new Set() - delegate(getRef('intern_list_container'), 'change', '.intern-card', (e) => { - const floId = e.target.closest('.intern-card').dataset.internFloId; - if (e.target.checked) { - floGlobals.selectedInterns.add(floId) - } else { - floGlobals.selectedInterns.delete(floId) - } - getRef('assign_interns_button').disabled = !floGlobals.selectedInterns.size - }) - function assignSelectedInterns() { - floGlobals.selectedInterns.forEach(floId => { - RIBC.admin.assignInternToTask(floId, appState.params.id, appState.params.branch, currentTask.dataset.taskId) - renderBranchTasks() - }) - notify(`Assigned task`, 'success') - closePopup() - } - - function renderAllInterns() { - renderElem(getRef('all_interns_list'), filterInterns('', { sortByRating: true })) - } - - function changeScore(scoreUpdate) { - let score = parseInt(getRef('intern_info__score').textContent) - score += scoreUpdate; - getRef('intern_info__score').textContent = score - document.querySelectorAll(`[data-intern-flo-id="${currentIntern}"]`).forEach(internCard => { - internCard.querySelector('.intern-card__score').textContent = score - }) - if (score > 0) { - getRef('reduce_score_button').disabled = false; - RIBC.admin.updateInternRating(currentIntern, scoreUpdate) - } - if (score === 1 && scoreUpdate === -1) { - getRef('reduce_score_button').disabled = true; - } - } - - function showNewBranchPopup() { - openPopup('create_branch_popup') - const startPoint = parseInt(currentTask.dataset.taskId) - getRef('branch_start_point').value = startPoint; - } - getRef('create_branch_btn').onclick = () => { - const startPoint = parseInt(currentTask.dataset.taskId) - const userMergePoint = getRef('branch_merge_point').value.trim() - const mergePoint = (userMergePoint === '') ? startPoint : parseInt(userMergePoint) - const branchName = RIBC.admin.addBranch(appState.params.id, appState.params.branch, startPoint, mergePoint); - notify(`Branch added ${branchName}`, 'success') - renderBranches() - closePopup() - } - - function clearRequestFilters() { - getRef('filter_requests_by_category').reset() - getRef('filter_requests_by_project').reset() - } - - function renderProjectSelectorOptions() { - const options = [html`All`]; - RIBC.getProjectList().reverse().forEach(project => { - options.push(html`${RIBC.getProjectDetails(project).projectName}`); - }) - renderElem(getRef('updates_page__project_selector'), html`${options}`) - } - function renderInternSelectorOptions() { - const options = [html`All`]; - const allInterns = Object.entries(RIBC.getInternList()).sort((a, b) => a[1].toLowerCase().localeCompare(b[1].toLowerCase())); - allInterns.forEach(intern => { - options.push(html`${intern[1]}`); - }) - renderElem(getRef('updates_page__intern_selector'), html`${options}`) - } - - function getUpdatesByProject(projectCode) { - const projectName = RIBC.getProjectDetails(projectCode).projectName - const allUpdates = RIBC.getInternUpdates() - const filteredUpdates = allUpdates.filter(({ update: { projectCode: updateProjectCode } }) => { - return projectCode === updateProjectCode - }) - return filteredUpdates - } - - function getUpdatesByIntern(floId, allUpdates = RIBC.getInternUpdates()) { - return allUpdates.filter(update => update.floID === floId) - } - function getUpdatesByDate(date, allUpdates = RIBC.getInternUpdates()) { - const filteredUpdates = [] - const dateStart = new Date(`${date} 00:00:00`).getTime() - const dateEnd = new Date(`${date} 23:59:59`).getTime() - let isFromDate = false - for (const update of allUpdates) { - if (update.time > dateStart && update.time < dateEnd) { - filteredUpdates.push(update) - isFromDate = true - } else if (isFromDate) break - } - return filteredUpdates - } - let updatesLazyLoader - function renderInternUpdates(updates = RIBC.getInternUpdates()) { - if (updatesLazyLoader) { - updatesLazyLoader.update(updates) - } else { - updatesLazyLoader = new LazyLoader('#all_updates_list', updates, render.internUpdateCard) - } - updatesLazyLoader.init() - } - delegate(getRef('all_updates_list'), 'click', '.init-update-replay', (e) => { - const vectorClock = e.delegateTarget.closest('.intern-update').dataset.vectorClock; - e.delegateTarget.after(html.node` - - -
    - -
    - -
    -
    -
    - `) - e.delegateTarget.classList.add('hidden') - e.target.closest('.intern-update').querySelector('.update-reply-textarea').focusIn() - }) - - function cancelUpdateReply(replayBox) { - replayBox.previousElementSibling.classList.remove('hidden') - replayBox.remove() - } - function submitUpdateReply(replayBox) { - buttonLoader(replayBox.querySelector('.update-replay__submit'), true) - const vectorClock = replayBox.previousElementSibling.closest('.intern-update').dataset.vectorClock; - const replyText = replayBox.querySelector('.update-reply-textarea').value.trim() - if (replyText !== '') { - RIBC.admin.commentInternUpdate(vectorClock, replyText).then(res => { - replayBox.previousElementSibling.remove() - replayBox.replaceWith(html.node` -
    -

    Admin

    -

    ${replyText}

    -
    `) - }).catch(err => { - notify(err, 'error') - buttonLoader(replayBox.querySelector('.update-replay__submit'), false) - }) - } - } - function setUpdateFilters(filters) { - const { projectCode, internId, date } = filters || getUpdateFilters() - if (filters) { - getRef('updates_page__project_selector').value = projectCode - getRef('updates_page__intern_selector').value = internId - getRef('updates_page__date_selector').value = date || '' - } else { - const dateParam = date !== '' ? `&date=${date}` : '' - location.hash = `/updates_page?projectCode=${projectCode}&internId=${internId}${dateParam}` - } - } - function getUpdateFilters() { - const projectCode = getRef('updates_page__project_selector').value || 'all' - const internId = getRef('updates_page__intern_selector').value || 'all' - const date = getRef('updates_page__date_selector').value || '' - return { projectCode, internId, date } - } - - function clearUpdatesFilter() { - getRef('updates_page__project_selector').reset() - getRef('updates_page__intern_selector').reset() - getRef('updates_page__date_selector').value = '' - setUpdateFilters() - } - - getRef('updates_page__project_selector').addEventListener('change', e => setUpdateFilters()) - getRef('updates_page__intern_selector').addEventListener('change', e => setUpdateFilters()) - getRef('updates_page__date_selector').addEventListener('change', e => setUpdateFilters()) - function pinProject(thisBtn) { - const projectCode = thisBtn.closest('.pinned-card').dataset.id; - pinnedProjects = localStorage.getItem(`${myFloID}_pinned_projects`) ? localStorage.getItem(`${myFloID}_pinned_projects`).split(',') : [] - if (pinnedProjects.includes(projectCode)) { - pinnedProjects = pinnedProjects.filter(project => project !== projectCode) - } else { - 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) - } - - let sessionTaskRequests = new Set(); - function requestForTask(btn) { - hideTaskDetails() - try { - floDapps.user.id - const taskId = btn ? btn.dataset.taskId : floGlobals.tempUserTaskRequest - floGlobals.tempUserTaskRequest = taskId - if (typeOfUser === 'general') { - getRef('intern_apply__task').textContent = RIBC.getAllTasks()[taskId].title - openPopup('apply_for_task_popup', true) - } else if (typeOfUser === 'intern') { - const hasApplied = [...RIBC.getTaskRequests(false), ...sessionTaskRequests].find(({ details }) => { - return taskId === details.taskId - }) - if (hasApplied) { - notify('You have already applied for this task', 'error') - } else { - if (floGlobals.assignedTasks.has(taskId)) - return notify('You have already been assigned this task', 'error'); - const [projectCode, branch, task] = taskId.split('_') - const { title } = RIBC.getTaskDetails(projectCode, branch, task) - getConfirmation(`Do you want to apply for "${title}"`, { confirmText: 'Apply' }).then((result) => { - if (result) { - if (btn) { - btn.textContent = 'Applying...' - btn.disabled = true - } - RIBC.applyForTask({ taskId }).then((result) => { - notify('Applied successfully.', 'success') - sessionTaskRequests.add({ details: { taskId } }) - floGlobals.tempUserTaskRequest = null - btn.textContent = 'Applied' - }).catch((err) => { - if (btn) { - btn.textContent = 'Apply' - btn.disabled = false - } - notify(err, 'error') - }) - } - }).catch((error) => { - notify(error, 'error') - }) - } - } - } catch (err) { - floGlobals.tempUserTaskRequest = btn.dataset.taskId; - location.hash = '#/sign_in' - floGlobals.signInNotification = notify('Please login to apply for task.') - } - } - - 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', '') - switch (e.detail.popup.id) { - case 'intern_list_popup': - renderElem(getRef('intern_list_container'), filterInterns('', { availableInternsOnly: true })) - break; - } - }) - document.addEventListener('popupclosed', e => { - switch (e.detail.popup.id) { - case 'intern_list_popup': - renderElem(getRef('intern_list_container'), html``) - getRef('intern_search_field').value = '' - floGlobals.selectedInterns.clear() - getRef('assign_interns_button').disabled = true - break; - } - if (popupStack.items.length === 0) { - getRef('main_page').removeAttribute('inert') - } - }) - - floGlobals.assignedTasks = new Set() - - function renderAllElements() { - - let sortedProjectList = getSortedProjectList() - document.querySelectorAll('.open-first-project').forEach(link => { - link.href = `${link.href}/project?id=${sortedProjectList[0]}&branch=mainLine` - }) - - pinnedProjects = localStorage.getItem(`${myFloID}_pinned_projects`) ? localStorage.getItem(`${myFloID}_pinned_projects`).split(',') : [] - - // Intern's view - - if (RIBC.getInternList()[myFloID] && !floGlobals.subAdmins.includes(myFloID)) { - typeOfUser = 'intern'; - document.querySelectorAll('.intern-option').forEach((option) => { - option.classList.remove('hidden') - }) - floGlobals.assignedProjectsList = new Set(); - // store all the projects assigned to interns in array - const allTasks = RIBC.getAllTasks() - for (const taskKey in allTasks) { - const [projectCode, branch, task] = taskKey.split('_') - const assignedInterns = RIBC.getAssignedInterns(projectCode, branch, task) - if (Array.isArray(assignedInterns) && assignedInterns.includes(myFloID)) { - floGlobals.assignedProjectsList.add(projectCode) - if (RIBC.getTaskStatus(projectCode, branch, task) === 'incomplete') { - floGlobals.assignedTasks.add(taskKey); - } - } - } - } else { - document.querySelectorAll('.intern-option').forEach((option) => { - option.classList.add('hidden') - }) - } - - // admin view - if (floGlobals.subAdmins.includes(myFloID)) { - typeOfUser = 'admin' - 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')) - } - } else if (type === 'internship') { - result = RIBC.admin.processInternRequest(vectorClock, false) - if (result === 'Rejected') { - notify('Request rejected', 'success') - removeRequest(e.delegateTarget.closest('.request-card')) - } - } - } - }) - }) - - document.querySelectorAll('.admin-option').forEach((option) => { - option.classList.remove('hidden') - }) - - //show interns - renderElem(getRef('admin_page__intern_list'), filterInterns('')) - - //show projects - render.projectList(getRef('admin_page__project_list'), getSortedProjectList(), true) - } else { - document.querySelectorAll('.admin-option').forEach((option) => { - option.classList.add('hidden') - }) - } - - // General only view for non admin and non intern - if (!RIBC.getInternList()[myFloID] && !floGlobals.subAdmins.includes(myFloID)) { - document.querySelectorAll('.general-only').forEach((elem) => { - elem.classList.remove('hidden') - }) - } - else { - document.querySelectorAll('.general-only').forEach((elem) => { - elem.classList.add('hidden') - }) - } - if (typeOfUser === 'admin') { - document.querySelectorAll('.not-for-admin').forEach((elem) => { - elem.classList.add('hidden') - }) - } else { - document.querySelectorAll('.not-for-admin').forEach((elem) => { - elem.classList.remove('hidden') - }) - } - - if (typeOfUser === 'intern') { - render.projectList(getRef('my_projects'), [...floGlobals.assignedProjectsList]) - sortedProjectList = sortedProjectList.filter(val => !floGlobals.assignedProjectsList.has(val)); - } - if (sortedProjectList.length > 0) { - getRef('other_projects').previousElementSibling.classList.remove('hidden') - render.projectList(getRef('other_projects'), sortedProjectList) - } else { - getRef('other_projects').previousElementSibling.classList.add('hidden') - } - delegate(getRef('explorer_task_list'), 'click', '.apply-button', e => { - requestForTask(e.delegateTarget) - }) - getRef('user_flo_id').value = myFloID; - } - - let currentTaskId; - function initTaskUpdate(e) { - const taskCard = e.target.closest('.task-card') - currentTaskId = taskCard.dataset.uniqueId - const [projectCode, branch, task] = currentTaskId.split('_') - getRef('update_of_project').textContent = RIBC.getProjectDetails(projectCode).projectName - getRef('update_of_task').textContent = RIBC.getTaskDetails(projectCode, branch, task).title - openPopup('post_update_popup') - } - - function postUpdate() { - const [projectCode, branch, task] = currentTaskId.split('_') - const description = getRef('update__brief').value.trim() - const linkText = getRef('update__link').value.trim() - const link = linkText !== '' ? linkText : null - if (description !== '') { - RIBC.postInternUpdate({ projectCode, branch, task, description, link }) - .then((result) => { - notify('Update posted', 'success') - closePopup() - }) - .catch((error) => { - notify(error, 'error') - }) - } - else { - notify('Please enter description', 'error') - } - } - function filterInterns(searchKey, options = {}) { - const { - sortByRating = false, - availableInternsOnly = false - } = options - let filtered = []; - const allInterns = RIBC.getInternList(); - const highPerformingInterns = Object.keys(allInterns).sort((a, b) => { - return RIBC.getInternRating(b) - RIBC.getInternRating(a) - }); - let arrayOfInterns = Object.keys(allInterns).sort((a, b) => { - return allInterns[a].toLowerCase().localeCompare(allInterns[b].toLowerCase()) - }) - if (availableInternsOnly) { - arrayOfInterns = arrayOfInterns.filter(intern => !RIBC.getAssignedInterns(appState.params.id, appState.params.branch, currentTask.dataset.taskId)?.includes(intern)) - } - if (searchKey === '') { - filtered = (sortByRating ? highPerformingInterns : arrayOfInterns).map(floId => { - return render.internCard(floId, { selectable: availableInternsOnly }) - }) - } else { - filtered = filterMap(arrayOfInterns, (floId) => { - if (allInterns[floId].toLowerCase().includes(searchKey.toLowerCase())) { - return render.internCard(floId, { selectable: availableInternsOnly }) - } - }) - } - return html`${filtered}` - } - const searchInternPopup = debounce((e) => { - renderElem(getRef('intern_list_container'), filterInterns(e.target.value.trim(), { availableInternsOnly: true })) - }, 150) - const searchInternPage = debounce((e) => { - renderElem(getRef('all_interns_list'), filterInterns(e.target.value.trim(), { sortByRating: true })) - }, 150) - getRef('intern_search_field').addEventListener('input', searchInternPopup) - getRef('interns_page__search').addEventListener('input', searchInternPage) - - - function applyForInternship() { - buttonLoader(getRef('intern_apply__button'), true) - const name = getRef('intern_apply__name').value.trim(); - const contact = getRef('intern_apply__contact').value.trim(); - const brief = getRef('intern_apply__brief').value.trim(); - // const resumeLink = getRef('intern_apply__resume_link').value.trim(); - const portfolioLink = getRef('intern_apply__portfolio_link').value.trim(); - const details = { - name, - brief, - // resumeLink, - contact, - portfolioLink: portfolioLink !== '' ? portfolioLink : null, - taskId: floGlobals.tempUserTaskRequest - } - RIBC.applyForTask(details) - .then((result) => { - notify('Application submitted', 'success') - closePopup() - }) - .catch((error) => { - notify(error, 'error') - }).finally(() => { - buttonLoader(getRef('intern_apply__button'), false) - floGlobals.tempUserTaskRequest = null - }) - } - - function getSortedProjectList() { - return RIBC.getProjectList().sort((a, b) => RIBC.getProjectDetails(a).projectName.toLowerCase().localeCompare(RIBC.getProjectDetails(b).projectName.toLowerCase())) - } - - - function getSignedIn(passwordType) { - return new Promise((resolve, reject) => { - try { - getPromptInput('Enter password', '', { - isPassword: true, - }).then(password => { - if (password) { - resolve(password) - } - }) - } catch (err) { - if (passwordType === 'PIN/Password') { - floGlobals.isPrivKeySecured = true; - 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`; - } - getRef('sign_in_button').onclick = () => { - resolve(getRef('private_key_field').value.trim()); - getRef('private_key_field').value = ''; - routeTo('loading'); - getRef("notification_drawer").remove(floGlobals.signInNotification) - }; - getRef('sign_up_button').onclick = () => { - resolve(getRef('generated_private_key').value); - getRef('generated_private_key').value = ''; - routeTo('loading'); - getRef("notification_drawer").remove(floGlobals.signInNotification) - }; - } - }); - } - function setSecurePassword() { - if (!floGlobals.isPrivKeySecured) { - const password = getRef('secure_pwd_input').value.trim(); - floDapps.securePrivKey(password).then(() => { - floGlobals.isPrivKeySecured = true; - notify('Password set successfully', 'success'); - getRef('secure_pwd_button').closest('.card').classList.add('hidden'); - closePopup(); - }).catch(err => { - notify(err, 'error'); - }) - } - } - function signOut() { - getConfirmation('Sign out?', { message: 'You are about to sign out of the app, continue?', confirmText: 'Leave', cancelText: 'Stay' }) - .then(async (res) => { - if (res) { - await floDapps.clearCredentials(); - location.reload(); - } - }); - } - // detect url within text and convert to link - function linkify(inputText) { - let replacedText, replacePattern1, replacePattern2, replacePattern3; - //URLs starting with http://, https://, or ftp:// - replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim; - replacedText = inputText.replace(replacePattern1, '$1'); - //URLs starting with "www." (without // before it, or it'd re-link the ones done above). - replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim; - replacedText = replacedText.replace(replacePattern2, '$1$2'); - //Change email addresses to mailto:: links. - replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim; - replacedText = replacedText.replace(replacePattern3, '$1'); - return replacedText; - } \ No newline at end of file diff --git a/scripts/ribc.js b/scripts/ribc.js index dd6ffb2..ad589a5 100644 --- a/scripts/ribc.js +++ b/scripts/ribc.js @@ -15,7 +15,7 @@ floCloudAPI.requestObjectData("RIBC").then(result => { if (!floGlobals.appObjects.RIBC) floGlobals.appObjects.RIBC = {}; - var objectList = ["projectMap", "projectBranches", "projectTaskDetails", "projectDetails", "internList", "internRating", "internsAssigned", "projectTaskStatus"] + var objectList = ["projectMap", "projectBranches", "projectTaskDetails", "projectDetails", "internList", "internRating", "internsAssigned", "projectTaskStatus", "displayedTasks"] objectList.forEach(obj => { if (!floGlobals.appObjects.RIBC[obj]) floGlobals.appObjects.RIBC[obj] = {}; @@ -105,6 +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 Admin.updateObjects = () => new Promise((resolve, reject) => { floCloudAPI.updateObjectData("RIBC") @@ -232,6 +233,10 @@ _.projectTaskStatus[projectCode + "_" + branch + "_" + taskNumber] = taskStatus; }; + Admin.setDisplayedTasks = function (tasksArr = []) { + floGlobals.appObjects.RIBC.displayedTasks = tasksArr; + } + Admin.createProject = function (projectCode) { if (projectCode in _.projectMap) { return "Project Name already exists"; diff --git a/scripts/ribc.min.js b/scripts/ribc.min.js index 0c7691f..afe16d1 100644 --- a/scripts/ribc.min.js +++ b/scripts/ribc.min.js @@ -1 +1 @@ -(function(){function e(e){if(a.projectBranches.hasOwnProperty(e))var t=a.projectBranches[e].split(",");else t=!1;return t}function t(e){for(var t={},n=a.projectBranches[e].split(","),r=0;r{Promise.all([n.refreshObjectData(),n.refreshGeneralData(e)]).then(e=>t(e)).catch(e=>r(e))})},n.refreshObjectData=(()=>new Promise((e,t)=>{floCloudAPI.requestObjectData("RIBC").then(t=>{floGlobals.appObjects.RIBC||(floGlobals.appObjects.RIBC={});var n=["projectMap","projectBranches","projectTaskDetails","projectDetails","internList","internRating","internsAssigned","projectTaskStatus"];n.forEach(e=>{floGlobals.appObjects.RIBC[e]||(floGlobals.appObjects.RIBC[e]={}),a[e]=floGlobals.appObjects.RIBC[e]}),e("Object Data Refreshed Successfully")}).catch(e=>t(e))})),n.refreshGeneralData=(e=>new Promise((t,n)=>{var r=["InternUpdates"],a=[],o=[];(e?r:o).push("TaskRequests","InternRequests");let s=[];for(let e of r)s.push(floCloudAPI.requestGeneralData(e));for(let e of a)s.push(floCloudAPI.requestGeneralData(e,{senderID:floGlobals.subAdmins}));for(let e of o)s.push(floCloudAPI.requestGeneralData(e,{senderID:floDapps.user.id}));Promise.all(s).then(e=>t("General Data Refreshed Successfully")).catch(e=>n(e))}));const a={};n.applyForIntern=(e=>new Promise((t,n)=>{floCloudAPI.sendGeneralData(e,"InternRequests").then(e=>t(e)).catch(e=>n(e))})),n.postInternUpdate=(e=>new Promise((t,n)=>{floCloudAPI.sendGeneralData(e,"InternUpdates").then(e=>t(e)).catch(e=>n(e))})),n.getInternUpdates=function(e=null){let t=Object.values(floGlobals.generalDataset("InternUpdates")).map(e=>({floID:e.senderID,update:e.message,time:e.vectorClock.split("_")[0],note:e.note}));return t=t.filter(e=>e.floID in a.internList),t.reverse(),e&&enew Promise((n,r)=>{if(!(e in floGlobals.generalDataset("InternUpdates")))return r("Intern update not found");floCloudAPI.noteApplicationData(e,t).then(e=>n(e)).catch(e=>r(e))})),n.applyForTask=(e=>new Promise((t,n)=>{floCloudAPI.sendGeneralData(e,"TaskRequests").then(e=>t(e)).catch(e=>n(e))})),n.getProjectList=(()=>Object.keys(a.projectMap)),n.getProjectDetails=(e=>a.projectDetails[e]),n.getProjectMap=(e=>a.projectMap[e]),n.getProjectBranches=(t=>e(t)),n.getTaskDetails=((e,t,n)=>a.projectTaskDetails[e+"_"+t+"_"+n]),n.getTaskStatus=((e,t,n)=>a.projectTaskStatus[e+"_"+t+"_"+n]),n.getInternList=(()=>a.internList),n.getInternRating=(e=>a.internRating[e]),n.getAssignedInterns=((e,t,n)=>a.internsAssigned[e+"_"+t+"_"+n]),n.getAllTasks=(()=>a.projectTaskDetails),r.updateObjects=(()=>new Promise((e,t)=>{floCloudAPI.updateObjectData("RIBC").then(t=>e(t)).catch(e=>t(e))})),r.resetObjects=(()=>new Promise((e,t)=>{floCloudAPI.resetObjectData("RIBC").then(t=>e(t)).catch(e=>t(e))})),r.addProjectDetails=function(e,t){if(!(e in a.projectMap))return"Project not Found!";if(e in a.projectDetails&&"object"==typeof e&&"object"==typeof t)for(let n in t)a.projectDetails[e][n]=t[n];else a.projectDetails[e]=t;return"added project details for "+e},n.getInternRequests=function(e=!0){var t=Object.values(floGlobals.generalDataset("InternRequests")).map(e=>({floID:e.senderID,vectorClock:e.vectorClock,details:e.message,status:e.note}));return t=t.filter(e=>!(e.floID in a.internList)),e&&(t=t.filter(e=>!e.status)),t},r.processInternRequest=function(e,t=!0){let n=floGlobals.generalDataset("InternRequests")[e];return n?(r=t&&o(n.senderID,n.message[0])?"Accepted":"Rejected",floCloudAPI.noteApplicationData(e,r).then(e=>null).catch(e=>console.error(e)),r):"Request not found";var r};const o=r.addIntern=function(e,t){return!(e in a.internList)&&(a.internList[e]=t,a.internRating[e]=1,!0)};r.updateInternRating=function(e,t=0){return e in a.internList?(a.internRating[e]+=t,"Intern rating Updated"):"Intern not found!"},n.getTaskRequests=function(e=!0){var t=Object.values(floGlobals.generalDataset("TaskRequests")).map(e=>({floID:e.senderID,vectorClock:e.vectorClock,details:e.message,status:e.note}));try{floDapps.user.id&&!floGlobals.subAdmins.includes(floDapps.user.id)&&(t=t.filter(e=>e.floID===floDapps.user.id))}catch(e){return[]}return e&&(t=t.filter(e=>!e.status)),t},r.processTaskRequest=function(e,t=!0){let n=floGlobals.generalDataset("TaskRequests")[e];if(!n)return"Request not found";const{message:{taskId:r,name:a},senderID:i}=n,[c,p,l]=r.split("_");var u;return o(i,a),u=t&&s(i,c,p,l)?"Accepted":"Rejected",floCloudAPI.noteApplicationData(e,u).then(e=>null).catch(e=>console.error(e)),u};const s=r.assignInternToTask=function(e,t,n,r){var o=t+"_"+n+"_"+r;return Array.isArray(a.internsAssigned[o])||(a.internsAssigned[o]=[]),!a.internsAssigned[o].includes(e)&&(a.internsAssigned[o].push(e),!0)};r.unassignInternFromTask=function(e,t,n,r){const o=t+"_"+n+"_"+r;a.internsAssigned[o]=a.internsAssigned[o].filter(t=>t!=e)},r.putTaskStatus=function(e,t,n,r){a.projectTaskStatus[t+"_"+n+"_"+r]=e},r.createProject=function(e){return e in a.projectMap?"Project Name already exists":(i(e),"Project Create: "+e)},r.copyBranchToNewProject=function(e,t,n,r,o,s){if("mainLine"==t)return"You cannot change mainLine";if(0==a.projectMap.hasOwnProperty(n))return"The project does not exist";if(0==a.projectMap[n].hasOwnProperty(c))return"The branch does not exist";if(o>s)return"Startpoint cannot be later than endpoint";var c=i(n,r,o,s);a.projectMap[n][c]=a.projectMap[e][t].slice(),a.projectMap[n][c][0]="undefined"==r?"mainLine":"newBranchConnection","undefined"!=o&&(a.projectMap[n][c][2]=o),"undefined"!=s&&(a.projectMap[n][c][3]=s);var p=a.projectTaskDetails;for(var l in p)if(p.hasOwnProperty(l)&&l.contains(e+"_"+t)){var u=l.replace(e+"_"+t+"_","");a.projectTaskDetails[n+"_"+c+"_"+u]=p[l]}return a.projectMap[n][c]},r.deleteTaskInMap=function(e,t,n){for(var r,o=a.projectMap[e][t],s=4;s4&&re!==t||"mainLine"!==e);for(s=0;s=c&&(c=i[l]+1),i[l]==r&&(p=l);return p>3?(i.splice(p+1,0,c),i[1]++,c):"Not possible to insert here.Try another position"},r.changeBranchLine=function(e,t,n,r,o){return"mainLine"==t?"You cannot change mainLine":0==a.projectMap.hasOwnProperty(e)?"The project does not exist":0==a.projectMap[e].hasOwnProperty(t)?"The branch does not exist":0==a.projectMap[e].hasOwnProperty(n)?"The newConnection does not exist":r>o?"Startpoint cannot be later than endpoint":(a.projectMap[e][t][0]=n,"undefined"!=r&&(a.projectMap[e][t][2]=r),"undefined"!=o&&(a.projectMap[e][t][3]=o),a.projectMap[e][t])},r.changeBranchPoint=function(e,t,n,r){var o;return"mainLine"!=t&&(1==r&&(n<=a.projectMap[e][t][3]?(a.projectMap[e][t][2]=n,o=n):o="Start point cannot be later than end point"),2==r&&(n>=a.projectMap[e][t][2]?(a.projectMap[e][t][3]=n,o=n):o="End point cannot be earlier than start point")),"mainLine"==t&&(o="mainLine cannot be rerouted"),o};const i=r.addBranch=function(t,n,r,o){var s,i=e(t);if(0==i)a.projectMap[t]={},a.projectMap[t].mainLine=["mainLine",0,"Start","Stop"],s="mainLine",a.projectBranches[t]="mainLine";else{var c=i[i.length-1];if(c.includes("branch")){var p=c.split("branch"),l=parseFloat(p[1])+1;s="branch"+l,a.projectMap[t]["branch"+l]=[n,0,r,o],a.projectBranches[t]=a.projectBranches[t]+",branch"+l}c.includes("mainLine")&&(s="branch1",a.projectMap[t].branch1=["mainLine",0,r,o],a.projectBranches[t]="mainLine,branch1")}return s};r.editTaskDetails=function(e,t,n,r){a.projectTaskDetails[t+"_"+n+"_"+r]={...a.projectTaskDetails[t+"_"+n+"_"+r],...e}},r.addTaskInMap=function(e,n){var r=[];r=t(e);var o=r[n],s=o+1;return a.projectMap[e][n].push(s),a.projectMap[e][n][1]++,s}})(); \ No newline at end of file +(function(){function e(e){if(r.projectBranches.hasOwnProperty(e))var t=r.projectBranches[e].split(",");else t=!1;return t}function t(e){for(var t={},n=r.projectBranches[e].split(","),a=0;a{Promise.all([n.refreshObjectData(),n.refreshGeneralData(e)]).then(e=>t(e)).catch(e=>a(e))})},n.refreshObjectData=(()=>new Promise((e,t)=>{floCloudAPI.requestObjectData("RIBC").then(t=>{floGlobals.appObjects.RIBC||(floGlobals.appObjects.RIBC={});var n=["projectMap","projectBranches","projectTaskDetails","projectDetails","internList","internRating","internsAssigned","projectTaskStatus","displayedTasks"];n.forEach(e=>{floGlobals.appObjects.RIBC[e]||(floGlobals.appObjects.RIBC[e]={}),r[e]=floGlobals.appObjects.RIBC[e]}),e("Object Data Refreshed Successfully")}).catch(e=>t(e))})),n.refreshGeneralData=(e=>new Promise((t,n)=>{var a=["InternUpdates"],r=[],s=[];(e?a:s).push("TaskRequests","InternRequests");let o=[];for(let e of a)o.push(floCloudAPI.requestGeneralData(e));for(let e of r)o.push(floCloudAPI.requestGeneralData(e,{senderID:floGlobals.subAdmins}));for(let e of s)o.push(floCloudAPI.requestGeneralData(e,{senderID:floDapps.user.id}));Promise.all(o).then(e=>t("General Data Refreshed Successfully")).catch(e=>n(e))}));const r={};n.applyForIntern=(e=>new Promise((t,n)=>{floCloudAPI.sendGeneralData(e,"InternRequests").then(e=>t(e)).catch(e=>n(e))})),n.postInternUpdate=(e=>new Promise((t,n)=>{floCloudAPI.sendGeneralData(e,"InternUpdates").then(e=>t(e)).catch(e=>n(e))})),n.getInternUpdates=function(e=null){let t=Object.values(floGlobals.generalDataset("InternUpdates")).map(e=>({floID:e.senderID,update:e.message,time:e.vectorClock.split("_")[0],note:e.note}));return t=t.filter(e=>e.floID in r.internList),t.reverse(),e&&enew Promise((n,a)=>{if(!(e in floGlobals.generalDataset("InternUpdates")))return a("Intern update not found");floCloudAPI.noteApplicationData(e,t).then(e=>n(e)).catch(e=>a(e))})),n.applyForTask=(e=>new Promise((t,n)=>{floCloudAPI.sendGeneralData(e,"TaskRequests").then(e=>t(e)).catch(e=>n(e))})),n.getProjectList=(()=>Object.keys(r.projectMap)),n.getProjectDetails=(e=>r.projectDetails[e]),n.getProjectMap=(e=>r.projectMap[e]),n.getProjectBranches=(t=>e(t)),n.getTaskDetails=((e,t,n)=>r.projectTaskDetails[e+"_"+t+"_"+n]),n.getTaskStatus=((e,t,n)=>r.projectTaskStatus[e+"_"+t+"_"+n]),n.getInternList=(()=>r.internList),n.getInternRating=(e=>r.internRating[e]),n.getAssignedInterns=((e,t,n)=>r.internsAssigned[e+"_"+t+"_"+n]),n.getAllTasks=(()=>r.projectTaskDetails),n.getDisplayedTasks=(()=>floGlobals.appObjects.RIBC.displayedTasks),a.updateObjects=(()=>new Promise((e,t)=>{floCloudAPI.updateObjectData("RIBC").then(t=>e(t)).catch(e=>t(e))})),a.resetObjects=(()=>new Promise((e,t)=>{floCloudAPI.resetObjectData("RIBC").then(t=>e(t)).catch(e=>t(e))})),a.addProjectDetails=function(e,t){if(!(e in r.projectMap))return"Project not Found!";if(e in r.projectDetails&&"object"==typeof e&&"object"==typeof t)for(let n in t)r.projectDetails[e][n]=t[n];else r.projectDetails[e]=t;return"added project details for "+e},n.getInternRequests=function(e=!0){var t=Object.values(floGlobals.generalDataset("InternRequests")).map(e=>({floID:e.senderID,vectorClock:e.vectorClock,details:e.message,status:e.note}));return t=t.filter(e=>!(e.floID in r.internList)),e&&(t=t.filter(e=>!e.status)),t},a.processInternRequest=function(e,t=!0){let n=floGlobals.generalDataset("InternRequests")[e];return n?(a=t&&s(n.senderID,n.message[0])?"Accepted":"Rejected",floCloudAPI.noteApplicationData(e,a).then(e=>null).catch(e=>console.error(e)),a):"Request not found";var a};const s=a.addIntern=function(e,t){return!(e in r.internList)&&(r.internList[e]=t,r.internRating[e]=1,!0)};a.updateInternRating=function(e,t=0){return e in r.internList?(r.internRating[e]+=t,"Intern rating Updated"):"Intern not found!"},n.getTaskRequests=function(e=!0){var t=Object.values(floGlobals.generalDataset("TaskRequests")).map(e=>({floID:e.senderID,vectorClock:e.vectorClock,details:e.message,status:e.note}));try{floDapps.user.id&&!floGlobals.subAdmins.includes(floDapps.user.id)&&(t=t.filter(e=>e.floID===floDapps.user.id))}catch(e){return[]}return e&&(t=t.filter(e=>!e.status)),t},a.processTaskRequest=function(e,t=!0){let n=floGlobals.generalDataset("TaskRequests")[e];if(!n)return"Request not found";const{message:{taskId:a,name:r},senderID:i}=n,[c,p,l]=a.split("_");var u;return s(i,r),u=t&&o(i,c,p,l)?"Accepted":"Rejected",floCloudAPI.noteApplicationData(e,u).then(e=>null).catch(e=>console.error(e)),u};const o=a.assignInternToTask=function(e,t,n,a){var s=t+"_"+n+"_"+a;return Array.isArray(r.internsAssigned[s])||(r.internsAssigned[s]=[]),!r.internsAssigned[s].includes(e)&&(r.internsAssigned[s].push(e),!0)};a.unassignInternFromTask=function(e,t,n,a){const s=t+"_"+n+"_"+a;r.internsAssigned[s]=r.internsAssigned[s].filter(t=>t!=e)},a.putTaskStatus=function(e,t,n,a){r.projectTaskStatus[t+"_"+n+"_"+a]=e},a.setDisplayedTasks=function(e=[]){floGlobals.appObjects.RIBC.displayedTasks=e},a.createProject=function(e){return e in r.projectMap?"Project Name already exists":(i(e),"Project Create: "+e)},a.copyBranchToNewProject=function(e,t,n,a,s,o){if("mainLine"==t)return"You cannot change mainLine";if(0==r.projectMap.hasOwnProperty(n))return"The project does not exist";if(0==r.projectMap[n].hasOwnProperty(c))return"The branch does not exist";if(s>o)return"Startpoint cannot be later than endpoint";var c=i(n,a,s,o);r.projectMap[n][c]=r.projectMap[e][t].slice(),r.projectMap[n][c][0]="undefined"==a?"mainLine":"newBranchConnection","undefined"!=s&&(r.projectMap[n][c][2]=s),"undefined"!=o&&(r.projectMap[n][c][3]=o);var p=r.projectTaskDetails;for(var l in p)if(p.hasOwnProperty(l)&&l.contains(e+"_"+t)){var u=l.replace(e+"_"+t+"_","");r.projectTaskDetails[n+"_"+c+"_"+u]=p[l]}return r.projectMap[n][c]},a.deleteTaskInMap=function(e,t,n){for(var a,s=r.projectMap[e][t],o=4;o4&&ae!==t||"mainLine"!==e);for(o=0;o=c&&(c=i[l]+1),i[l]==a&&(p=l);return p>3?(i.splice(p+1,0,c),i[1]++,c):"Not possible to insert here.Try another position"},a.changeBranchLine=function(e,t,n,a,s){return"mainLine"==t?"You cannot change mainLine":0==r.projectMap.hasOwnProperty(e)?"The project does not exist":0==r.projectMap[e].hasOwnProperty(t)?"The branch does not exist":0==r.projectMap[e].hasOwnProperty(n)?"The newConnection does not exist":a>s?"Startpoint cannot be later than endpoint":(r.projectMap[e][t][0]=n,"undefined"!=a&&(r.projectMap[e][t][2]=a),"undefined"!=s&&(r.projectMap[e][t][3]=s),r.projectMap[e][t])},a.changeBranchPoint=function(e,t,n,a){var s;return"mainLine"!=t&&(1==a&&(n<=r.projectMap[e][t][3]?(r.projectMap[e][t][2]=n,s=n):s="Start point cannot be later than end point"),2==a&&(n>=r.projectMap[e][t][2]?(r.projectMap[e][t][3]=n,s=n):s="End point cannot be earlier than start point")),"mainLine"==t&&(s="mainLine cannot be rerouted"),s};const i=a.addBranch=function(t,n,a,s){var o,i=e(t);if(0==i)r.projectMap[t]={},r.projectMap[t].mainLine=["mainLine",0,"Start","Stop"],o="mainLine",r.projectBranches[t]="mainLine";else{var c=i[i.length-1];if(c.includes("branch")){var p=c.split("branch"),l=parseFloat(p[1])+1;o="branch"+l,r.projectMap[t]["branch"+l]=[n,0,a,s],r.projectBranches[t]=r.projectBranches[t]+",branch"+l}c.includes("mainLine")&&(o="branch1",r.projectMap[t].branch1=["mainLine",0,a,s],r.projectBranches[t]="mainLine,branch1")}return o};a.editTaskDetails=function(e,t,n,a){r.projectTaskDetails[t+"_"+n+"_"+a]={...r.projectTaskDetails[t+"_"+n+"_"+a],...e}},a.addTaskInMap=function(e,n){var a=[];a=t(e);var s=a[n],o=s+1;return r.projectMap[e][n].push(o),r.projectMap[e][n][1]++,o}})(); \ No newline at end of file diff --git a/scripts/std_ui.js b/scripts/std_ui.js deleted file mode 100644 index ba4a510..0000000 --- a/scripts/std_ui.js +++ /dev/null @@ -1,819 +0,0 @@ -/*jshint esversion: 8 */ -/** - * @yaireo/relative-time - javascript function to transform timestamp or date to local relative-time - * - * @version v1.0.0 - * @homepage https://github.com/yairEO/relative-time - */ - -!function (e, t) { var o = o || {}; "function" == typeof o && o.amd ? o([], t) : "object" == typeof exports && "object" == typeof module ? module.exports = t() : "object" == typeof exports ? exports.RelativeTime = t() : e.RelativeTime = t() }(this, (function () { const e = { year: 31536e6, month: 2628e6, day: 864e5, hour: 36e5, minute: 6e4, second: 1e3 }, t = "en", o = { numeric: "auto" }; function n(e) { e = { locale: (e = e || {}).locale || t, options: { ...o, ...e.options } }, this.rtf = new Intl.RelativeTimeFormat(e.locale, e.options) } return n.prototype = { from(t, o) { const n = t - (o || new Date); for (let t in e) if (Math.abs(n) > e[t] || "second" == t) return this.rtf.format(Math.round(n / e[t]), t) } }, n })); - -const relativeTime = new RelativeTime({ style: 'narrow' }); -// Global variables -const { html, render: renderElem } = uhtml; -const domRefs = {} -//Checks for internet connection status -if (!navigator.onLine) - notify('There seems to be a problem connecting to the internet, Please check you internet connection.', 'error', '', true) -window.addEventListener('offline', () => { - notify('There seems to be a problem connecting to the internet, Please check you internet connection.', 'error', true, true) -}) -window.addEventListener('online', () => { - getRef('notification_drawer').clearAll() - notify('We are back online.', 'success') -}) -// Use instead of document.getElementById -function getRef(elementId) { - if (!domRefs.hasOwnProperty(elementId)) { - domRefs[elementId] = { - count: 1, - ref: null, - }; - return document.getElementById(elementId); - } else { - if (domRefs[elementId].count < 3) { - domRefs[elementId].count = domRefs[elementId].count + 1; - return document.getElementById(elementId); - } else { - if (!domRefs[elementId].ref) - domRefs[elementId].ref = document.getElementById(elementId); - return domRefs[elementId].ref; - } - } -} - -// returns dom with specified element -function createElement(tagName, options = {}) { - const { className, textContent, innerHTML, attributes = {} } = options - const elem = document.createElement(tagName) - for (let attribute in attributes) { - elem.setAttribute(attribute, attributes[attribute]) - } - if (className) - elem.className = className - if (textContent) - elem.textContent = textContent - if (innerHTML) - elem.innerHTML = innerHTML - return elem -} - -// Use when a function needs to be executed after user finishes changes -const debounce = (callback, wait) => { - let timeoutId = null; - return (...args) => { - window.clearTimeout(timeoutId); - timeoutId = window.setTimeout(() => { - callback.apply(null, args); - }, wait); - }; -} - -let zIndex = 50 -// function required for popups or modals to appear -function openPopup(popupId, pinned) { - zIndex++ - getRef(popupId).setAttribute('style', `z-index: ${zIndex}`) - getRef(popupId).show({ pinned }) - return getRef(popupId); -} - -// hides the popup or modal -function closePopup() { - if (popupStack.peek() === undefined) - return; - popupStack.peek().popup.hide() -} - - -// displays a popup for asking permission. Use this instead of JS confirm -const getConfirmation = (title, options = {}) => { - return new Promise(resolve => { - const { message = '', cancelText = 'Cancel', confirmText = 'OK' } = options - openPopup('confirmation_popup', true) - getRef('confirm_title').innerText = title; - getRef('confirm_message').innerText = message; - const cancelButton = getRef('confirmation_popup').querySelector('.cancel-button'); - const confirmButton = getRef('confirmation_popup').querySelector('.confirm-button') - confirmButton.textContent = confirmText - cancelButton.textContent = cancelText - confirmButton.onclick = () => { - closePopup() - resolve(true); - } - cancelButton.onclick = () => { - closePopup() - resolve(false); - } - }) -} - -//Function for displaying toast notifications. pass in error for mode param if you want to show an error. -function notify(message, mode, options = {}) { - let icon - switch (mode) { - case 'success': - icon = `` - break; - case 'error': - icon = `` - options.pinned = true - break; - } - if (mode === 'error') { - console.error(message) - } - return getRef("notification_drawer").push(message, { icon, ...options }); -} - -// detect browser version -function detectBrowser() { - let ua = navigator.userAgent, - tem, - M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; - if (/trident/i.test(M[1])) { - tem = /\brv[ :]+(\d+)/g.exec(ua) || []; - return 'IE ' + (tem[1] || ''); - } - if (M[1] === 'Chrome') { - tem = ua.match(/\b(OPR|Edge)\/(\d+)/); - if (tem != null) return tem.slice(1).join(' ').replace('OPR', 'Opera'); - } - M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?']; - if ((tem = ua.match(/version\/(\d+)/i)) != null) M.splice(1, 1, tem[1]); - return M.join(' '); -} -window.addEventListener('hashchange', e => routeTo(window.location.hash)) -window.addEventListener("load", () => { - const [browserName, browserVersion] = detectBrowser().split(' '); - const supportedVersions = { - Chrome: 85, - Firefox: 75, - Safari: 13, - } - if (browserName in supportedVersions) { - if (parseInt(browserVersion) < supportedVersions[browserName]) { - notify(`${browserName} ${browserVersion} is not fully supported, some features may not work properly. Please update to ${supportedVersions[browserName]} or higher.`, 'error') - } - } else { - notify('Browser is not fully compatible, some features may not work. for best experience please use Chrome, Edge, Firefox or Safari', 'error') - } - document.body.classList.remove('hidden') - DOMPurify.setConfig = { - FORBID_ATTR: ['style'], - FORBID_TAGS: ['style'] - - } - DOMPurify.addHook('afterSanitizeAttributes', function (node) { - // set all elements owning target to target=_blank - if ('target' in node) { - node.setAttribute('target', '_blank'); - } - // set non-HTML/MathML links to xlink:show=new - if ( - !node.hasAttribute('target') && - (node.hasAttribute('xlink:href') || node.hasAttribute('href')) - ) { - node.setAttribute('xlink:show', 'new'); - } - }); - document.querySelectorAll('sm-input[data-flo-id]').forEach(input => input.customValidation = floCrypto.validateAddr) - document.querySelectorAll('sm-input[data-private-key]').forEach(input => input.customValidation = floCrypto.getPubKeyHex) - document.addEventListener('keyup', (e) => { - if (e.code === 'Escape') { - closePopup() - } - }) - document.addEventListener("pointerdown", (e) => { - if (e.target.closest("button:not([disabled]), .interact")) { - createRipple(e, e.target.closest("button, .interact")); - } - }); - document.addEventListener('copy', () => { - notify('copied', 'success') - }) -}); - -function createRipple(event, target) { - const circle = document.createElement("span"); - const diameter = Math.max(target.clientWidth, target.clientHeight); - const radius = diameter / 2; - const targetDimensions = target.getBoundingClientRect(); - circle.style.width = circle.style.height = `${diameter}px`; - circle.style.left = `${event.clientX - (targetDimensions.left + radius)}px`; - circle.style.top = `${event.clientY - (targetDimensions.top + radius)}px`; - circle.classList.add("ripple"); - const rippleAnimation = circle.animate( - [ - { - transform: "scale(4)", - opacity: 0, - }, - ], - { - duration: floGlobals.prefersReducedMotion ? 0 : 600, - fill: "forwards", - easing: "ease-out", - } - ); - target.append(circle); - rippleAnimation.onfinish = () => { - circle.remove(); - }; -} - -function getFormattedTime(timestamp, format) { - try { - timestamp = parseInt(timestamp) - if (String(timestamp).length < 13) - timestamp *= 1000 - let [day, month, date, year] = new Date(timestamp).toString().split(' '), - minutes = new Date(timestamp).getMinutes(), - hours = new Date(timestamp).getHours(), - currentTime = new Date().toString().split(' ') - - minutes = minutes < 10 ? `0${minutes}` : minutes - let finalHours = ``; - if (hours > 12) - finalHours = `${hours - 12}:${minutes}` - else if (hours === 0) - finalHours = `12:${minutes}` - else - finalHours = `${hours}:${minutes}` - - finalHours = hours >= 12 ? `${finalHours} PM` : `${finalHours} AM` - switch (format) { - case 'date-only': - return `${month} ${date}, ${year}`; - break; - case 'time-only': - return finalHours; - case 'relative': - return relativeTime.from(timestamp) - default: - return `${month} ${date}, ${year} at ${finalHours}`; - } - } catch (e) { - console.error(e); - return timestamp; - } -} - -const appState = { - params: {}, -} -const generalPages = ['sign_up', 'sign_in', 'loading', 'landing'] -function routeTo(targetPage, options = {}) { - const { firstLoad } = options - const routingAnimation = { in: slideInUp, out: slideOutUp } - let pageId - let subPageId1 - let searchParams - let params - if (targetPage === '') { - try { - if (floDapps.user.id) - pageId = 'dashboard_page' - } catch (e) { - pageId = 'landing' - } - } else { - if (targetPage.includes('/')) { - if (targetPage.includes('?')) { - const splitAddress = targetPage.split('?') - searchParams = splitAddress.pop(); - [, pageId, subPageId1] = splitAddress.pop().split('/') - } else { - [, pageId, subPageId1] = targetPage.split('/') - } - } else { - pageId = targetPage - } - } - - if (!document.querySelector(`#${pageId}`)?.classList.contains('inner-page')) return - try { - if (floDapps.user.id && (['sign_up', 'sign_in', 'loading', 'landing'].includes(pageId))) { - history.replaceState(null, null, '#/dashboard_page'); - pageId = 'dashboard_page' - } - } catch (e) { - if (!(generalPages.includes(pageId))) return - } - appState.currentPage = pageId - - if (searchParams) { - const urlSearchParams = new URLSearchParams('?' + searchParams); - params = Object.fromEntries(urlSearchParams.entries()); - } - if (params) - appState.params = params - if (firstLoad && floGlobals.tempUserTaskRequest && RIBC.getAllTasks()[floGlobals.tempUserTaskRequest]) { - requestForTask() - } - switch (pageId) { - case 'landing': - if (!params) { - params = { category: 'all' } - } - renderElem(getRef('landing_tasks_wrapper'), render.displayTasks(params.category, params.search)) - if (subPageId1) { - showTaskDetails(params.id) - } else { - hideTaskDetails() - } - break; - case 'sign_up': - const { floID, privKey } = floCrypto.generateNewID() - getRef('generated_flo_address').value = floID - getRef('generated_private_key').value = privKey - break; - case 'dashboard_page': - let renderedAssignedTasks - if (typeOfUser === 'intern') { - // Render assigned task cards - if (floGlobals.assignedTasks.size) { - renderedAssignedTasks = filterMap(floGlobals.assignedTasks, id => render.internTaskCard(id)) - } else { - renderedAssignedTasks = html`No task assigned yet.`; - } - } - renderElem(getRef('dashboard_page'), html` - - ${typeOfUser === 'intern' ? html`My tasks` : ''} - All tasks - Projects - ${floGlobals.isMobileView ? html`Leaderboard` : ''} - - ${typeOfUser === 'intern' ? html` -
    -
      ${renderedAssignedTasks}
    -
    - ` : ''} -
    ${render.displayTasks('all', params?.search)}
    - -
    -
    - -

    Leaderboard

    - All -
    -
    -
    -

    There are no interns

    -
    -
    - `) - 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') - } - 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 { - hideTaskDetails() - } - break; - case 'updates_page': { - if (!getRef('updates_page__project_selector').children.length) { - renderProjectSelectorOptions() - renderInternSelectorOptions() - } - const { projectCode, internId, date } = params || getUpdateFilters() - if (params) { - setUpdateFilters({ projectCode, internId, date }) - } else if (projectCode) { - const dateParam = date !== '' ? `&date=${date}` : '' - history.replaceState(null, null, `#/updates_page?projectCode=${projectCode}&internId=${internId}${dateParam}`) - } - let matchedUpdates - if (projectCode !== 'all') { - matchedUpdates = getUpdatesByProject(projectCode) - } - if (internId !== 'all') { - matchedUpdates = getUpdatesByIntern(internId, matchedUpdates) - } - if (date) { - matchedUpdates = getUpdatesByDate(date, matchedUpdates) - } - renderInternUpdates(matchedUpdates) - } break; - case 'applications': - render.taskApplications() - if (subPageId1) { - showTaskDetails(params.id) - } else { - hideTaskDetails() - } - break; - case 'all_interns_page': - renderAllInterns() - break; - case 'project_explorer': - if (subPageId1) { - if (params) { - const { id: projectCode, branch } = params - if (appState.params.projectCode !== projectCode) { - showProjectInfo(projectCode) - const allProjects = getRef('project_explorer__left').querySelectorAll('.project-card'); - allProjects.forEach(project => project.classList.remove('project-card--active')) - const targetProject = [...allProjects].find(project => project.getAttribute('href').includes(projectCode)) - if (targetProject) - targetProject.classList.add('project-card--active') - } - if (branch) { - renderBranchTasks() - } - getRef('project_explorer__left').classList.add('hide-on-mobile') - getRef('project_explorer__right').classList.remove('hide-on-mobile') - } else { - getRef('project_explorer__left').querySelectorAll('.project-card').forEach(project => project.classList.remove('project-card--active')) - } - } else { - getRef('project_explorer__left').classList.remove('hide-on-mobile') - getRef('project_explorer__right').classList.add('hide-on-mobile') - history.replaceState(null, '', '#/project_explorer') - } - break; - case 'admin_page': - 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') - } - break; - } - switch (appState.lastPage) { - case 'project_explorer': - case 'all_interns_page': - routingAnimation.in = slideInRight; - routingAnimation.out = slideOutRight; - break; - } - switch (pageId) { - case 'project_explorer': - case 'all_interns_page': - routingAnimation.in = slideInLeft; - routingAnimation.out = slideOutLeft; - break; - } - if (appState.lastPage !== pageId) { - if (document.querySelector('.nav-list__item--active')) - document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active'); - const targetListItem = [...document.querySelectorAll(`a.nav-list__item`)].find(item => item.href.includes(pageId)) - if (targetListItem) - targetListItem.classList.add('nav-list__item--active') - document.querySelectorAll('.page').forEach(page => page.classList.add('hidden')) - getRef(pageId).closest('.page').classList.remove('hidden') - 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) => { - 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).parentNode.style.overflow = ogOverflow; - switch (pageId) { - case 'sign_in': - getRef('private_key_field').focusIn() - break; - } - } - appState.lastPage = pageId - } -} -// class based lazy loading -class LazyLoader { - constructor(container, elementsToRender, renderFn, options = {}) { - const { batchSize = 10, freshRender, bottomFirst = false, domUpdated } = options - - this.elementsToRender = elementsToRender - this.arrayOfElements = (typeof elementsToRender === 'function') ? this.elementsToRender() : elementsToRender || [] - this.renderFn = renderFn - this.intersectionObserver - - this.batchSize = batchSize - this.freshRender = freshRender - this.domUpdated = domUpdated - this.bottomFirst = bottomFirst - - this.shouldLazyLoad = false - this.lastScrollTop = 0 - this.lastScrollHeight = 0 - - this.lazyContainer = document.querySelector(container) - - this.update = this.update.bind(this) - this.render = this.render.bind(this) - this.init = this.init.bind(this) - this.clear = this.clear.bind(this) - } - get elements() { - return this.arrayOfElements - } - init() { - this.intersectionObserver = new IntersectionObserver((entries, observer) => { - entries.forEach(entry => { - if (entry.isIntersecting) { - observer.disconnect() - this.render({ lazyLoad: true }) - } - }) - }) - this.mutationObserver = new MutationObserver(mutationList => { - mutationList.forEach(mutation => { - if (mutation.type === 'childList') { - if (mutation.addedNodes.length) { - if (this.bottomFirst) { - if (this.lazyContainer.firstElementChild) - this.intersectionObserver.observe(this.lazyContainer.firstElementChild) - } else { - if (this.lazyContainer.lastElementChild) - this.intersectionObserver.observe(this.lazyContainer.lastElementChild) - } - } - } - }) - }) - this.mutationObserver.observe(this.lazyContainer, { - childList: true, - }) - this.render() - } - update(elementsToRender) { - this.arrayOfElements = (typeof elementsToRender === 'function') ? this.elementsToRender() : elementsToRender || [] - } - render(options = {}) { - let { lazyLoad = false } = options - this.shouldLazyLoad = lazyLoad - const frag = document.createDocumentFragment(); - if (lazyLoad) { - if (this.bottomFirst) { - this.updateEndIndex = this.updateStartIndex - this.updateStartIndex = this.updateEndIndex - this.batchSize - } else { - this.updateStartIndex = this.updateEndIndex - this.updateEndIndex = this.updateEndIndex + this.batchSize - } - } else { - this.intersectionObserver.disconnect() - if (this.bottomFirst) { - this.updateEndIndex = this.arrayOfElements.length - this.updateStartIndex = this.updateEndIndex - this.batchSize - 1 - } else { - this.updateStartIndex = 0 - this.updateEndIndex = this.batchSize - } - this.lazyContainer.innerHTML = ``; - } - this.lastScrollHeight = this.lazyContainer.scrollHeight - this.lastScrollTop = this.lazyContainer.scrollTop - this.arrayOfElements.slice(this.updateStartIndex, this.updateEndIndex).forEach((element, index) => { - frag.append(this.renderFn(element)) - }) - if (this.bottomFirst) { - this.lazyContainer.prepend(frag) - // scroll anchoring for reverse scrolling - this.lastScrollTop += this.lazyContainer.scrollHeight - this.lastScrollHeight - this.lazyContainer.scrollTo({ top: this.lastScrollTop }) - this.lastScrollHeight = this.lazyContainer.scrollHeight - } else { - this.lazyContainer.append(frag) - } - if (!lazyLoad && this.bottomFirst) { - this.lazyContainer.scrollTop = this.lazyContainer.scrollHeight - } - // Callback to be called if elements are updated or rendered for first time - if (!lazyLoad && this.freshRender) - this.freshRender() - } - clear() { - this.intersectionObserver.disconnect() - this.mutationObserver.disconnect() - this.lazyContainer.innerHTML = ``; - } - reset() { - this.arrayOfElements = (typeof this.elementsToRender === 'function') ? this.elementsToRender() : this.elementsToRender || [] - this.render() - } -} -function buttonLoader(id, show) { - const button = typeof id === 'string' ? getRef(id) : id; - button.disabled = show; - const animOptions = { - duration: floGlobals.prefersReducedMotion ? 0 : 200, - fill: 'forwards', - easing: 'ease' - } - if (show) { - button.animate([ - { - clipPath: 'circle(100%)', - }, - { - clipPath: 'circle(0)', - }, - ], animOptions).onfinish = e => { - e.target.commitStyles() - e.target.cancel() - } - button.parentNode.append(createElement('sm-spinner')) - } else { - button.style = '' - const potentialTarget = button.parentNode.querySelector('sm-spinner') - if (potentialTarget) potentialTarget.remove(); - } -} -// implement event delegation -function delegate(el, event, selector, fn) { - el.addEventListener(event, function (e) { - const potentialTarget = e.target.closest(selector) - if (potentialTarget) { - e.delegateTarget = potentialTarget - fn.call(this, e) - } - }) -} -const slideInLeft = [ - { - opacity: 0, - transform: 'translateX(1rem)' - }, - { - opacity: 1, - transform: 'translateX(0)' - } -] -const slideOutLeft = [ - { - opacity: 1, - transform: 'translateX(0)' - }, - { - opacity: 0, - transform: 'translateX(-1rem)' - }, -] -const slideInRight = [ - { - opacity: 0, - transform: 'translateX(-1rem)' - }, - { - opacity: 1, - transform: 'translateX(0)' - } -] -const slideOutRight = [ - { - opacity: 1, - transform: 'translateX(0)' - }, - { - opacity: 0, - transform: 'translateX(1rem)' - }, -] -const slideInDown = [ - { - opacity: 0, - transform: 'translateY(-1rem)' - }, - { - opacity: 1, - transform: 'translateY(0)' - }, -] -const slideOutDown = [ - { - opacity: 1, - transform: 'translateY(0)' - }, - { - opacity: 0, - transform: 'translateY(1rem)' - }, -] -const slideInUp = [ - { - opacity: 0, - transform: 'translateY(1rem)' - }, - { - opacity: 1, - transform: 'translateY(0)' - }, -] -const slideOutUp = [ - { - opacity: 1, - transform: 'translateY(0)' - }, - { - opacity: 0, - transform: 'translateY(-1rem)' - }, -] - -function showChildElement(id, index, options = {}) { - return new Promise((resolve) => { - const { mobileView = false, entry, exit } = options - const animOptions = { - duration: floGlobals.prefersReducedMotion ? 0 : 150, - easing: 'ease', - fill: 'forwards' - } - const parent = typeof id === 'string' ? document.getElementById(id) : id; - const visibleElement = [...parent.children].find(elem => !elem.classList.contains(mobileView ? 'hide-on-mobile' : 'hidden')); - if (visibleElement === parent.children[index]) return; - visibleElement.getAnimations().forEach(anim => anim.cancel()) - parent.children[index].getAnimations().forEach(anim => anim.cancel()) - if (visibleElement) { - if (exit) { - parent.style.overflow = 'hidden' - visibleElement.animate(exit, animOptions).onfinish = () => { - visibleElement.classList.add(mobileView ? 'hide-on-mobile' : 'hidden') - parent.style.overflow = '' - } - parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden') - if (entry) - parent.children[index].animate(entry, animOptions).onfinish = () => resolve() - } else { - visibleElement.classList.add(mobileView ? 'hide-on-mobile' : 'hidden') - parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden') - resolve() - } - } else { - parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden') - parent.children[index].animate(entry, animOptions).onfinish = () => resolve() - } - }) -} -function togglePrivateKeyVisibility(input) { - const target = input.closest('sm-input') - target.type = target.type === 'password' ? 'text' : 'password'; - target.focusIn() -} -function filterMap(array, mapFn) { - const result = []; - array.forEach((element, index) => { - const mapped = mapFn(element, index) - if (mapped) result.push(mapped) - }) - return result; -} -const mobileQuery = window.matchMedia('(max-width: 40rem)') -function handleMobileChange(e) { - floGlobals.isMobileView = e.matches -} -mobileQuery.addEventListener('change', handleMobileChange) -handleMobileChange(mobileQuery) -const reduceMotionQuery = window.matchMedia('(prefers-reduced-motion: reduce)'); -reduceMotionQuery.addEventListener('change', () => { - floGlobals.prefersReducedMotion = reduceMotionQuery.matches -}); -floGlobals.prefersReducedMotion = reduceMotionQuery.matches \ No newline at end of file